FreeBSD BhyveでPCI passthrough

# 1. はじめに

Bhyveのゲスト(Windows)でホストのデバイスを使いたいなと思って、PCI passthroughの設定をしてみました。
管理ソフトとしてはvm-bhyveを使っているので、それ前提で以下の説明をします。
vm-bhyveについては検索すると割と解説が見つかるので、そちらを参照してください。

ハードは去年購入したものでこの記事に書いてあるものです。
https://qiita.com/yshdsnd/items/e8ba8d417851ae56f2fc
ただし、メモリが128GBに増えてます。
FreeBSDは13.1-STABLEを使用しています。

# 2. ホスト側(ハード)の設定
PCI passthroughにはVT-dという機能が必要です。デフォルトで無効になっていることが多いので、UEFIメニューに入ってVT-dを有効にしておきます。

![IMG_2153.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373056/3584500f-cfd5-bec1-20ff-ffbf1ab05af3.jpeg)

今回は使わないですが、SR-IOVも合わせて有効にしています。

# 3. ホスト側(ソフト)の設定
まずは使いたいデバイスのIDを調べます。
pciconfでもいいのですが、vm-bhyveのvm passthruコマンドが簡単です。

<pre># vm passthru
DEVICE     BHYVE ID     READY        DESCRIPTION
hostb0     0/0/0        No           12th Gen Core Processor Host Bridge/DRAM Registers
pcib1      0/1/0        No           12th Gen Core Processor PCI Express x16 Controller
vgapci0    0/2/0        No           AlderLake-S GT1
pcib2      0/6/0        No           12th Gen Core Processor PCI Express x4 Controller
none0      0/8/0        No           12th Gen Core Processor Gaussian & Neural Accelerator
xhci0      0/20/0       No           Alder Lake-S PCH USB 3.2 Gen 2x2 XHCI Controller
none1      0/20/2       No           Alder Lake-S PCH Shared SRAM
ig4iic0    0/21/0       No           Alder Lake-S PCH Serial IO I2C Controller
none2      0/22/0       No           Alder Lake-S PCH HECI Controller
ahci0      0/23/0       No           Alder Lake-S PCH SATA Controller [AHCI Mode]
pcib3      0/28/0       No           -
pcib4      0/29/0       No           -
isab0      0/31/0       No           Z690 Chipset LPC/eSPI Controller
hdac0      0/31/3       No           Alder Lake-S HD Audio Controller
ichsmb0    0/31/4       No           Alder Lake-S PCH SMBus Controller
none3      0/31/5       No           Alder Lake-S PCH SPI Controller
ix0        1/0/0        No           Ethernet Controller 10-Gigabit X540-AT2
ix1        1/0/1        No           Ethernet Controller 10-Gigabit X540-AT2
nvme0      2/0/0        No           E18 PCIe4 NVMe Controller
none0       3/0/0       No           Killer E3000 2.5GbE Controller
xhci1       4/0/0       No           -
</pre>

→ この最期にあるNIC(Killer E3000 2.5GbE Controller)とxhci1デバイスを
  Windowsで使いたいと思います。

次に/boot/loader.confにパススルーデバイスとして予約するデバイスを記載します。

/boot/loader.conf：
<pre>
kern.geom.label.disk_ident.enable="0"
kern.geom.label.gptid.enable="0"

zfs_load="YES"
vmm_load="YES"
pptdevs="3/0/0 4/0/0"
</pre>

pptdevsに先ほどvm passthruで表示したIDを記載します。
また、ここで必ずvmmモジュールを明示的にロードしておきます。
そうしないとxhciドライバが先にデバイスを認識してしまいパススルーデバイスとして予約されなくなってしまうからです。
FreeBSDのドライバのないKiller E3000 2.5GbE Controllerだけを使いたいのであればvmmモジュールは明示的に書かなくても大丈夫です。bhyveを起動するときに自動的にロードされます。

loader.confを編集したら、OSを再起動してもう一度 vm passthru を実行します。
<pre>
# vm passthru
DEVICE     BHYVE ID     READY        DESCRIPTION
hostb0     0/0/0        No           12th Gen Core Processor Host Bridge/DRAM Registers
pcib1      0/1/0        No           12th Gen Core Processor PCI Express x16 Controller
vgapci0    0/2/0        No           AlderLake-S GT1
pcib2      0/6/0        No           12th Gen Core Processor PCI Express x4 Controller
none0      0/8/0        No           12th Gen Core Processor Gaussian & Neural Accelerator
xhci0      0/20/0       No           Alder Lake-S PCH USB 3.2 Gen 2x2 XHCI Controller
none1      0/20/2       No           Alder Lake-S PCH Shared SRAM
ig4iic0    0/21/0       No           Alder Lake-S PCH Serial IO I2C Controller
none2      0/22/0       No           Alder Lake-S PCH HECI Controller
ahci0      0/23/0       No           Alder Lake-S PCH SATA Controller [AHCI Mode]
pcib3      0/28/0       No           -
pcib4      0/29/0       No           -
isab0      0/31/0       No           Z690 Chipset LPC/eSPI Controller
hdac0      0/31/3       No           Alder Lake-S HD Audio Controller
ichsmb0    0/31/4       No           Alder Lake-S PCH SMBus Controller
none3      0/31/5       No           Alder Lake-S PCH SPI Controller
ix0        1/0/0        No           Ethernet Controller 10-Gigabit X540-AT2
ix1        1/0/1        No           Ethernet Controller 10-Gigabit X540-AT2
nvme0      2/0/0        No           E18 PCIe4 NVMe Controller
ppt0       3/0/0        Yes          Killer E3000 2.5GbE Controller
ppt1       4/0/0        Yes          -
</pre>

指定したデバイスが、ppt0, ppt1となってpassthroughデバイスとして登録されました。

# 4. ゲストの起動設定
vm-bhyveの設定ファイルにpassthruデバイスを登録します。
windowsという名前でゲストを作成済みなので、
vm config windows で設定ファイルを編集します。
<pre>
loader="uefi"
graphics="yes"
xhci_mouse="yes"
cpu=4
cpu_sockets=1
cpu_cores=4
cpu_threads=1
memory=16G
ahci_device_limit="8"
network0_type="virtio-net"
network0_switch="lan0"

disk0_type="ahci-hd"
disk0_name="disk0"
disk0_dev="sparse-zvol"

graphics_port=5902
graphics_res="1920x1080"

# windows expects the host to expose localtime by default, not UTC
utctime="no"

# JP keyboard
bhyve_options="-K jp"
uuid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
network0_mac="58:9c:fc:xx:xx:xx"

passthru0="3/0/0"
passthru1="4/0/0"
</pre>

passthruX="BUS/SLOT/FUNC"
の形で記載します。vm passthruで表示されているものをそのまま記載すればOKです。
passthruとは関係ないですが、最近の-STABLEにVNC経由で繋いだときのキーボードマップを指定するオプション(-K)が追加されたので、日本語キーボード経由で使っても、記号がうまく入力できないということがなくなりました。bhyve_optionsにそのオプションを指定しています。

# 5. ゲストを起動してみる

ここまで来たら起動するだけです。
 \# vm start windows

Windowsのデバイスマネージャで追加されていることを確認します。
必要ならドライバをインストールします。

無事認識されればこの通り。
ASMedia USB 3.1 eXtensible Host Controller の方がパススルーしたデバイスで、その下のIntelのxhciコントローラはBhyveの仮想デバイスです。
さらにその下のKiller E3100Gもパススルーしたデバイスです。

![スクリーンショット 2022-12-16 190045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373056/95619590-f66e-8023-88b3-4e35373460b7.png)

# 6. しかし問題が...

Windows側でドライバをインストールして再起動したらbhyveプロセスが異常終了してしまいました。何度起動してもだめ。
ログをみると、status 4 で終了しています。

ログでは以下の様になっていました。

<pre>12月 16 19:13:17: bhyve exited with status 0
12月 16 19:13:17: restarting
12月 16 19:13:17:  [bhyve options: -c 4,sockets=1,cores=4,threads=1 -m 16G -Hwl bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd -K jp -U 0e7bf333-96b9-11ea-bb29-e8611f133073 -S]
12月 16 19:13:17:  [bhyve devices: -s 0,hostbridge -s 31,lpc -s 4:0,ahci,hd:/dev/zvol/zroot/data/vm/windows/disk0 -s 5:0,virtio-net,tap4,mac=58:9c:fc:06:57:ac -s 6:0,passthru,3/0/0 -s 7:0,passthru,4/0/0 -s 8:0,fbuf,tcp=0.0.0.0:5902,w=1920,h=1080 -s 9:0,xhci,tablet]
12月 16 19:13:17:  [bhyve console: -l com1,/dev/nmdm-windows.1A]
12月 16 19:13:17: starting bhyve (run 2)
12月 16 19:13:18: bhyve exited with status 4
12月 16 19:13:18: destroying network device tap4
12月 16 19:13:18: stopped
</pre>

設定ファイルからpassthruを削除すると問題なく起動します。
また、ホストを再起動してから起動するとうまくいきます。
ただし、ゲストを再起動するとまた起動できなくなってしまいました。

passthroughデバイスを再度初期化しないといけないのに何かしら問題があってできていないからかなと思いますが、解決できず。ゲスト再起動するたびにホストの再起動が必要とか、ゲストの意味ないので困りました...解決策を知っている人がいれば教えて頂きたいです。

__※2023/1/27 追記__

13-STABLEのソースツリーでbhyveコマンドとkernelのvmm関連に大幅な変更があったため、もしやと思って最新の13-STABLEにアップデートしてみたところ、無事ゲストがリブートできるようになりました。これで思いっきり使い倒せます。