デバイスをドメインUにパススルーする

HVMなWindowsをゲストとしてインストールできたのはいんだけども、DirectXが使えない。
デバイスをみてみたら、グラフィックコントローラがエミュレートされていた。
理由は

# enable stdvga, default = 0 (use cirrus logic device model)
stdvga=1

ってわけなんで、0にしてみた。
んなんだけどどうもそれだけじゃだめなようだ。

で、設定ファイルを眺めていたら、pciデバイスをHVMドメインにパススルーする設定が見つかったので、設定してみた。
で、ゲストドメインを起動しようとしたんだけど、怒られた。

Error: Fail to assign device(1:0.0): maybe VT-d is not enabled, or the device is not exist, or it has already been assigned to other domain

とりあえず、VT-dってなにか調べてみた。
どうやらIntel Virtualization Technology for Directed I/Oとかいうやつらしい。
詳しい話はこの記事でもみてもらうとして、PCIデバイスなんかをHVMなゲストドメインにダイレクトにあつかってもらうためには、この技術が必要なようだ。

で、この技術ってのはチップセットレベルの話になるので、チップセットがサポートしていないと有効化できない。
で、調べてみたら、どうやらQ35, Q45, X38, X48とかのチップセットじゃないとサポートしていない模様。
うちのP45なんですけど。。。

まあ、でも、この技術を使うとXenのHVMなドメイン0でダイレクトにPCI, PCI-e等のデバイスにアクセスすることができるらしい。
つまり、おそらくXenで仮想化したHVMなWindows上でネイティブに(近い形で)デバイスを操作することができるはずだ。
近い形、というのは、間にVT-dがはさまれるから。
パフォーマンスに関してはネイティブと比較してもおそらくほとんどかわらないはず。
VT-dがうんこじゃなければ。

ということで、今はできないが、やり方を将来のために記述しておく。
参考はXen WikiのVTdHowTo

ドメイン0のカーネルについて
    CONFIG_XEN_PCIDEV_BACKENDが静的に組み込まれているか、モジュールとして組み込まれている必要がある。
    ためしにDebianの2.6.26-2のxen用カーネルはどうなってるかみてみたら、静的に組み込まれているようだ。
    組み込まれてないならモジュールでも静的でもいいんで組み込んでコンパイルしましょう。

# grep CONFIG_XEN_PCIDEV_BACKEND config-2.6.26-2-xen-amd64
CONFIG_XEN_PCIDEV_BACKEND=y
CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set

    HVMなドメインを作成する時にはqemu-dmだとかqemu-xenだとかっていうデバイスモデルが使われるけど、
    それをビルドするときにlibpciのヘッダとか開発用パッケージがないとパススルーサポートを持たないようにビルドされる。
    パススルーサポートを持っていないのにパススルーを行おうとすると、以下のように怒られる。
ERROR (XendDomainInfo:581) Device model didn't tell the vslots for PCI device
    パススルーしたいデバイスはpcibackendにバインドされる必要がある。
    静的に組み込まれている場合は以下のようにしてドメイン0のカーネルパラメータとして指定することでできる。
title Xen-Linux (2.6.18-xen)
        root (hd0,0)
        kernel /boot/xen.gz
        module /boot/vmlinuz-2.6.18.8-xen root=LABEL=/ ro pciback.hide=(01:00.0)(00:02.0)
        module /boot/initrd-2.6.18-xen.img
    あるいは、Xenのドメインが立ち上がる前に(つまりxend起動前だと思われる)、PCIバックエンドにバインドするようなスクリプトを記述しておく。
    たいていDebianだと/etc/init.dにスクリプトを書いて、/etc/rcX.dに起動順に合わせたシンボリックリンクを張る。
    この辺はまあ本題ではないのであまり触れない。
    とりあえずman update-rc.dすれば解決するはず。
   BDF=0000:05:02.0
   # Unbind a PCI network card from its network driver
   echo -n $BDF > /sys/bus/pci/drivers/3c905/unbind
   # And now bind it to the PCI Backend
   echo -n $BDF > /sys/bus/pci/drivers/pciback/new_slot
   echo -n $BDF > /sys/bus/pci/drivers/pciback/bind
    この方法はPCIバックエンドドライバが静的に組み込まれている場合でも、モジュールとして組み込まれている場合でも使える。
    で、次にモジュールとして組み込まれている場合にのみ使える方法。
    modprobe.confに以下のように書く。
 # hide (0000:05:02.0)
 options pciback hide=(0000:05:02.0)
    ようするに、モジュールをロードするときにバックエンドにバインドするデバイスを指定する。
    ただし、その場合は対象のデバイスに対するドライバがすでにロードされてドメイン0で利用されていたりしないこと。
    競合するドライバがたとえばskgeである場合、最初にpcibackドライバにバインドさせるように、以下のように加えておくこともできる。
 install skge /sbin/modprobe pciback ; /sbin/modprobe --first-time --ignore-install skge
    パススルー可能なデバイスは
        xm pci-list-assignable-devices
    で確認することができる。
    これはXen 3.3かららしい。

    Xen 3.4ではパススルーされたデバイスをHVMなゲストドメイン側のどの仮想スロットに割り当てるかの指定が出きるようになった。
    以下の例では、01:00.0はそのままだけど、00:02.0はスロット7に割り当てる。
pci = [ '01:00.0', '00:02.0@7' ]
    xm pci-listを使うことでHVMゲストドメインにパススルーされているPCIデバイスを表示することができる。
    xm pci-attachおよびxm pci-detachによって、稼働中のHVMゲストドメインにPCIデバイスのホットプラグ及びホットアンプラグができる。
[root@vt-vtd ~]# xm pci-list HVMDomainVtd
VSlt domain   bus   slot   func
0x6  0x0      0x01  0x00   0x0
0x7  0x0      0x00  0x02   0x0

[root@vt-vtd ~]# xm pci-attach HVMDomainVtd 0:2:0.0 7

[root@vt-vtd ~]# xm pci-detach HVMDomainVtd 0:2:0.0
    Xen 3.4.0までは、VT-dパススルーのためにHVMゲストのスロット6, 7をリザーブしている。
    逆に言えば、こういうことだ。
  • 二つのデバイスのみアタッチできる
  • アタッチされたデバイスはスロット6か7のどっちかにアタッチされる
  • スロット6, 7はIOEMUデバイスには使えない
    3.4.0ではこのリザーブシステムをなくして自由に使えるようになっている。
    HVMドメインは一つのPCIバスを持ち、32のスロットを持つ。

    アサインされたデバイスに対してMSI/MSI-Xを有効にする方法は、3.3.0以前と以降で異なる。

3.3.0より前
kernel xen.gz msi_irq_enable=1

3.3.0以降
kernel xen.gz msi=1

    PCIデバイスは8個までのファンクションを持ち得る。
    一つだけのものはシングルファンクション、二つ以上のものをマルチファンクションデバイスという。
    よくあるマルチファンクションデバイスはUSBだ。
    以下の例では0,1,7の三つのファンクションを持っている。
[root@vt-vtd ~]# lspci -s 00:1a
00:1a.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 02)
00:1a.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 02)
00:1a.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 02)
    Xen 3.4.0およびそれまでのVT-dをサポートしたXenでは、HVMドメインでのVT-dパススルーはシングルファンクションデバイスに限られる。
    マルチファンクションデバイスをパススルーした場合、HVMドメインではそのデバイスの物理ファンクションナンバーに関わらず、ファンクションナンバーは0と認識される。

Physical (dom0)

Virtual (HVM Domain)

Single-Function

00:02.0

00.06.0
Multi-Function 00:1a.1 00.07.0


とりあえずここまでだけど、USBデバイスのパススルーはまだ先になるってことですね。
でも、マルチファンクションデバイスのサポートにはすでに取りかかっているらしい。
期待、とおもいきや、そもそもママンがVT-d対応してない。。。

あああああああああああああああああああああ。orz

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>