LoginSignup
0

More than 5 years have passed since last update.

BitVisorでPCIデバイスのIDを変える

Posted at

BitVisorを書き換えて、仮想マシン上のPCIデバイスのIDを変える方法を紹介します。仮想マシンのデバイスといってもBitVisorなので実マシンのデバイスなのですが、IDを変えるといっても物理的なデバイスに何かやるわけではなく、para-passthrough device driverを実装して、IDだけを変えてやります。

実装方法

PCIデバイス用のpara-passthrough device driverはdriver/ディレクトリー以下にいくつもの実装例が含まれていますので、それを参考にすると簡単に実装できます。

基本的には、pci_register_driver()関数を呼び出す初期化関数を実装してPCI_DRIVER_INITマクロで同関数が呼び出されるようにすることと、pci_register_driver()関数に渡すstruct pci_driver構造体の準備、および、同構造体の関数ポインターが指す関数等を実装すればOKです。

pci_register_driver()関数で登録が済んだドライバーは、以下の記事にあるようにマッチングが成立すればnewポインターが指す関数が呼び出され、その後のPCI configuration spaceのアクセスでconfig_readおよびconfig_writeポインターが指す関数が呼び出されるようになります。これらの関数でPCI configuration spaceに含まれるデバイスIDなどを変更して見せることも可能になります。

BitVisorのvmm.driver.pciの指定の仕方
http://qiita.com/hdk_2/items/f906c352f44a2afa6ad9

ベースアドレスレジスターが指すI/O空間へのアクセスなどを横取りするには、さらにフックの登録等が必要になります。しかし、今回はデバイスのIDを変更するだけなので、ドライバーの登録だけで十分です。

実装例

以下に実装例を差分で示します。(タブは無いので気にしなくて大丈夫です。)

diff --git a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -18,3 +18,4 @@ objs-$(CONFIG_LOG_TO_IEEE1394) += ieee13
 objs-$(CONFIG_VGA_INTEL_DRIVER) += vga_intel.o
 objs-$(CONFIG_TTY_X540) += x540.o
 objs-$(CONFIG_PCI_MONITOR) += pci_monitor.o
+objs-1 += fakeid.o
diff --git a/drivers/fakeid.c b/drivers/fakeid.c
new file mode 100644
--- /dev/null
+++ b/drivers/fakeid.c
@@ -0,0 +1,17 @@
+#include <core.h>
+#include <core/strtol.h>
+#include "pci.h"
+static int config_read (struct pci_device *dev, u8 iosize, u16 offset,
+  union mem *data) { char *s = dev->driver_options[0], *t;
+  if (s && offset < 4) { union { u8 b[1]; u16 w[6]; } a; memset (&a, 0,
+  sizeof a); a.w[0] = strtol (s, &t, 16); if (s != t && *t++ == ':') {
+  a.w[1] = strtol (t, &s, 16); if (t != s) { memcpy (data, &a.b[offset],
+  iosize); return CORE_IO_RET_DONE; } } } return CORE_IO_RET_DEFAULT; }
+static int config_write (struct pci_device *dev, u8 iosize, u16 offset,
+  union mem *data) { return CORE_IO_RET_DEFAULT; }
+static void new (struct pci_device *dev) { }
+static struct pci_driver fakeid_driver = { .driver_options = "id",
+  .name = "fakeid", .longname = "fakeid", .device = "id=:", .new = new,
+  .config_read = config_read, .config_write = config_write };
+static void fakeid_init (void) { pci_register_driver (&fakeid_driver); }
+PCI_DRIVER_INIT (fakeid_init);

このfakeidドライバーは、IDの読み取りに対して、オプションidにvendor:device形式で16進数で指定されたIDを返すようにするものです。このようにわずか17行の簡単なプログラムで実現できます。

実行例

以下の記事では/proc/cpuinfoのvendor_idのところをAMDに見えるようにしましたが、これではPCIデバイスにまだIntelのデバイスがいくつも見えてしまいます。

BitVisorでCPUID命令の挙動を変える
http://qiita.com/hdk_2/items/9cc8312e1b4948c51dc6

例えば、iMac Mid-2014ではAHCIコントローラーとして以下のようにIntelのものが見えています。

$ lspci -s 1f.2 -nn
00:1f.2 SATA controller [0106]: Intel Corporation 8 Series SATA Controller 1 [AHCI mode] [8086:9c03] (rev 04)

これでは似非AMDファンなMacユーザーの皆様は不満だと思いますので、これを変えてみましょう。fakeidを組み込んだBitVisorのvmm.driver.pciに、以下のように設定するだけです。

vmm.driver.pci=id=8086:9c03, driver=fakeid, id=1022:7801

これで、ベンダーIDとデバイスIDを変えることができます。結果は以下の通りです。どう見てもAMDです。

$ lspci -s 1f.2 -nn
00:1f.2 SATA controller [0106]: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] [1022:7801] (rev 04)

もちろんmacOS上でも確認できます。BitVisorなしの場合、以下のようにIntelと出ています。

20161209-2.png

これが、BitVisorで上のIDを見せた場合は以下のようにGenericになります。

20161209.png

えっ、メモリーコントローラーやVGA互換コントローラーなど、他にもIntelのものがいっぱい見えているだろって? えっと、そうなんですけど、特にIntel Integrated Graphics Controllerを使っている場合、VRAMがRAMの一部から確保されるためだと思いますが、メモリーコントローラーのIDなどもデバイスドライバーの動作に影響するらしいので、そのへんのIDを変えてしまうと (VGA互換コントローラーのIDを変えなくても) 画面が映らなくなってしまうかも知れないです。興味があれば試してみてください。SATAコントローラーやUSBコントローラーなどは標準規格になっていますのでIDを変えてもトラブルは起きにくいと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0