# 使用 QEMU 創建 FreeBSD 16 Current VM


## QEMU

基本的操作如下，來是 Gemini：

![alt text](image.png)

但我們在切換 FreeBSD tty 會用到 Ctrl + Alt 所以反而會切到 Linux host machine 的 TTY，可以在 QEMU Monitor 輸入 `sendkey ctrl-alt-f2` 手動輸入切換。

### VirtIO

在沒有 VirtIO 的年代，虛擬機（Guest）如果要叫宿主機（Host）做事情，必須假裝自己是一台擁有舊硬體的實體機（比如模擬成一張 1990 年代的 Intel 網卡）。這種「演戲」的過程非常消耗 CPU 效能。

VirtIO 的運作原理：半虛擬化 (Para-virtualization)

* 前端 (Front-end)：跑在你的 FreeBSD 虛擬機裡。它知道自己是虛擬的，所以它不傳送複雜的硬體訊號，而是直接把數據丟到記憶體的一塊「共享區域」。
* 後端 (Back-end)：跑在你的 QEMU/KVM 裡。它直接從共享區域抓數據，交給實體硬體處理。

所以這邊可能可以用：

1. VirtIO 模擬網卡 and Disk
2. E1000 模擬 Intel 網卡 and SATA 硬碟

我們這邊使用第一種，FreeBSD 甚至內建 Kenrel 就有一些 virtio 驅動，清參考 Man page [VIRTIO(4)](https://man.freebsd.org/cgi/man.cgi?virtio(4))。

## FreeBSD 安裝

我們先用簡單的 amd64 ISO 檔案 [FreeBSD-16.0-CURRENT-amd64-20260330-e6eba5076929-284768-disc1.iso](https://download.freebsd.org/snapshots/ISO-IMAGES/16.0/)。

```bash
kola:~/proj/freebsd_16_20260330$ ls
FreeBSD-16.0-CURRENT-amd64-20260330-e6eba5076929-284768-disc1.iso
kola:~/proj/freebsd_16_20260330$ qemu-img create -f qcow2 freebsd16.qcow2 50G
Formatting 'freebsd16.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=53687091200 lazy_refcounts=off refcount_bits=16

kola:~/proj/freebsd_16_20260330$ qemu-system-x86_64 \
  -m 8G \
  -cpu host \ # 這代表直接把 Linux 主機的 CPU 特性傳遞給虛擬機
  -smp 6 \
  -enable-kvm \ # 啟動 Linux 核心加速
  -drive file=freebsd16.qcow2,if=virtio \ # 告訴 FreeBSD 這不是傳統的 IDE 或 SATA 硬碟，而是高效能的 VirtIO 區塊設備
  -cdrom FreeBSD-16.0-CURRENT-amd64-20260330-e6eba5076929-284768-disc1.iso \ # 將 ISO 檔掛載到虛擬光碟機。安裝完成後，這行其實可以拿掉
  -net nic,model=virtio -net user \ # 虛擬網卡使用 VirtIO 驅動。在 FreeBSD 裡會顯示為 vtnet0
  -vga virtio \ # 模擬一張 VirtIO GPU。這是目前 QEMU 裡最強大的虛擬顯卡，支援 3D 加速
  -display gtk,gl=on \ # gtk: 使用 Linux 系統常見的 GTK 視窗來顯示 QEM
  -device virtio-tablet-pci \ # 這本來是為了實現「游標無縫進出」虛擬機的技術
  -audiodev pa,id=snd0 \ # 讓 QEMU 的聲音輸出到 Linux 宿主機的 PulseAudio
  -device intel-hda # 在虛擬機裡模擬一個 Intel 高傳真音效卡硬體
  -device hda-duplex,audiodev=snd0 # 模擬的硬體（hda-duplex，支援輸入輸出）與剛才定義的後端（snd0）連接起來

qemu-system-x86_64 \
  -m 8G \
  -cpu host \
  -smp 6 \
  -enable-kvm \
  -drive file=freebsd16.qcow2,if=virtio \
  -net nic,model=virtio -net user \
  -vga virtio \
  -display gtk,gl=on \
  -device virtio-tablet-pci \
  -audiodev pa,id=snd0 \
  -device intel-hda \
  -device hda-duplex,audiodev=snd0

(qemu-system-x86_64:241929): Gtk-WARNING **: 19:23:20.366: Theme parsing error: gtk.css:2560:38: Junk at end of value for background
```

之後就不需要 cdrom 參數了，但因為 `-device virtio-tablet-pci`，virtio-tablet 傳送的是「絕對座標」（例如：滑鼠現在在螢幕的 500, 300 處）。如果 FreeBSD 內核沒有正確載入 virtio_gpu 驅動來告訴系統「螢幕現在解析度是多少」，系統就會不知道這座標該往哪擺，最後只能讓下游標卡在螢幕正中央。

[Mouse cursor not detected on FreeBSD virtual machine on Qemu](https://forums.freebsd.org/threads/mouse-cursor-not-detected-on-freebsd-virtual-machine-on-qemu.92546/)

根據上面文章，在虛擬化環境中，普通的「滑鼠（Mouse）」通常是以相對座標運作，這在圖形介面（X11）中常導致虛擬機滑鼠與主機滑鼠不同步。為了解決這個問題，通常會改用「平板電腦（Tablet）」模式，它使用絕對座標，能讓滑鼠指哪打哪。

然而，FreeBSD 的舊版本核心對 QEMU 提供的 USB Tablet 或 VirtIO Tablet 支援並不完善，需要額外的驅動程式。

* 舊方法（針對 FreeBSD 12 或更早）：需要手動安裝 utouch-kmod 驅動，並在 virt-manager 裡將輸入裝置設為 "EvTouch USB Graphics Tablet"
* 新方法（針對 FreeBSD 13、14 及更新版本）：論壇最後一則回覆（#25）指出，現在不需要安裝額外套件了。FreeBSD 核心現在內建了 hms(4) 驅動來支援 HID 滑鼠/平板設備，但預設沒啟用

---

所以改成以下用 `-usb -device usb-tablet`，這讓 QEMU 模擬一個實體 USB 繪圖板。FreeBSD 內核裡的 hms 和 usbhid 驅動對這個裝置的支援非常穩，不管有沒有 3D 加速，它都能 100% 正常移動。

```bash
qemu-system-x86_64 \
  -m 8G \
  -cpu host \
  -smp 6 \
  -enable-kvm \
  -drive file=freebsd16.qcow2,if=virtio \
  -net nic,model=virtio -net user \
  -vga virtio \
  -display gtk,gl=on \
  -usb -device usb-tablet \
  -audiodev pa,id=snd0 \
  -device intel-hda \
  -device hda-duplex,audiodev=snd0
```

## 網路

User-mode Networking (SLIRP)，這模式是 QEMU 的預設值。你可以把它想像成 「QEMU 內建的一個小型 Proxy 伺服器」。

QEMU 會攔截虛擬機發出的所有 TCP/UDP 封包，然後在 Linux 宿主機（Host）上以普通使用者的身分重新發送這些請求。

因為在 Linux 裡，發送 ICMP（Ping）封包需要 Raw Socket 權限，而普通使用者啟動的 QEMU 行程沒有這個權限，所以 SLIRP 乾脆不模擬 ICMP。

TAP 模式（最推薦，最像實體機） 這是在 Linux 上實現虛擬化最標準的做法。它會在你的 Linux 裡建立一個虛擬網卡（例如 tap0），然後透過 Bridge（網橋） 把這張虛擬網卡跟你的實體網卡（例如 eth0）連在一起。 效果：FreeBSD 會從你的路由器（Router）直接拿到一個跟 Linux 主機同區網的 IP（例如 192.168.1.50）。 能力：可以被 Ping，可以從 Linux 直接 SSH 進去，甚至可以在區網內玩檔案共享。

Port Forwarding（懶人折衷法） 如果你不想搞複雜的網橋，但又想連進 FreeBSD，可以在原本的 SLIRP 模式加一個「傳送門」。 指令範例：-netdev user,id=n1,hostfwd=tcp::2222-:22 效果：你在 Linux 連線 localhost:2222，封包會被轉發到虛擬機的 22 埠。

Passthrough（硬體直通） 如果你有兩張實體網卡，可以直接把其中一張「送給」虛擬機。 效果：效能最高，但那張網卡在 Linux 宿主機上會消失，專供 FreeBSD 使用。

---

VMware 預設通常是 NAT 模式 或 Bridged (橋接) 模式。雖然聽起來跟 QEMU 的 User Mode (SLIRP) 很像，但底層實現完全不同：

VMware 的 NAT 模式：它在你的 Linux 宿主機中安裝了內核級別的驅動程式（這就是為什麼你安裝 VMware 時需要輸入密碼，還要編譯一堆 vmnet 模組）。這些驅動讓 VMware 擁有了「特權」，可以直接在 Linux 核心層級處理網路封包，模擬出一台功能完整的虛擬路由器。

QEMU 的 User Mode (SLIRP)：它是一個純粹的使用者層級 (User-space) 程式。它不觸碰內核，只靠標準的系統呼叫來傳輸資料。因為它沒有特權，所以無法偽造 ICMP (Ping) 封包。

## 桌面環境

有驅動（VirtIO GPU）：可以支援解析度自動調整、雙螢幕，以及最重要的 OpenGL 加速，這對 KDE 6 的特效至關重要。
包含在 drm-kmod 裡面

看要不要安裝 "noto-2.0"？

```bash
sudo pkg install -y xorg
sudo pw groupmod video -m [user]
sudo pkg install kde
sudo pkg install dbus # 其實不用跑已經安裝了
sudo sysrc dbus_enable="YES"
sudo sysrc net.local.stream.recvspace=65536
sudo sysrc net.local.stream.sendspace=65536
sudo pkg drm-kmod # 包含 QEMU 的 virtio_gpu.ko 驅動
# sysrc kld_list+="virtio_gpu"

### ----------------------------------------- ###

sudo pkg install plasma6-sddm-kcm # KDE 的控制模組 (KCM)，讓你可以在 KDE 的「系統設定」介面裡直接設定 SDDM 登入畫面
sudo pkg install sddm  # Simple Desktop Display Manager。雖然是獨立計畫，但它是 KDE 官方推薦的登入程式，支援 X11 與 Wayland

sudo sysrc hald_enable="YES"
sudo sysrc sddm_enable="YES"
sudo sysrc snd_driver_load="YES"
```

## Debug

進度 ISO loader prompt。

![alt text](image-2.png)

![alt text](image-1.png)

```bash
set currdev=disk0p2:
ls /boot/kernel/kernel
load /boot/kernel/kernel
boot
```

## Reference

* [FreeBSD 15.0 how to install and use in QEMU VM with KDE Plasma 6 and xrdp - October 2025 - 7b69463c](https://www.youtube.com/watch?v=SOx0pO7f8VA)
* [【心得】Linux 出專欄啦！（7）: 虛擬機介紹，都來用linux 了，用qemu (gnome boxes) 吧！](https://forum.gamer.com.tw/C.php?bsn=60030&snA=628406)
* [6.3 KDE 6 桌面环境（X11 会话）](https://book.bsdcn.org/di-6-zhang-zhuo-mian-huan-jing/di-6.3-jie-kde-6-zhuo-mian-huan-jing-x11-hui-hua)

