Thursday, January 18, 2018

iohyve / bhyve USB controller passthrough goodness

I used to have a Windows machine that was dedicated to running software for our printer since the open-source software wouldn't scan and print correctly. Thanks to iohyve and a $20 PCI USB card, I was able to eliminate this machine and replace it with a slimmed down virtual machine.

Here are some tips and steps to get it working:
  • Only PCI devices that support MSI (message signaled interrupts) will work. You can figure all of this out with the command:

    pciconf -lvc

    In my case, I get:

    xhci1@pci0:3:0:0:        class=0x0c0330 card=0x12421b21 chip=0x12421b21 rev=0x00 hdr=0x00
        vendor     = 'ASMedia Technology Inc.'
        device     = 'ASM1142 USB 3.1 Host Controller'
        class      = serial bus
        subclass   = USB
        cap 05[50] = MSI supports 8 messages, 64 bit
        cap 11[68] = MSI-X supports 8 messages
                     Table in map 0x10[0x2000], PBA in map 0x10[0x2080]
        cap 01[78] = powerspec 3  supports D0 D3  current D0
        cap 10[80] = PCI-Express 2 endpoint max data 128(512) NS
                     link x2(x2) speed 5.0(5.0) ASPM disabled(L0s/L1)
        ecap 0002[100] = VC 1 max VC0
        ecap 0001[200] = AER 1 0 fatal 0 non-fatal 0 corrected
        ecap 0019[280] = PCIe Sec 1 lane errors 0
        ecap 0018[300] = LTR 1
  • bhyve expects that PCI devices that will be passed through must be associated with the ppt driver. Rebooting your machine is not required. In the above example, the device is associated with the xhci driver. To associate it with the ppt driver:

    devctl detach pci3:0:0
    devctl set driver pci3:0:0 ppt

    If you execute pciconf -lvc again, you'll now notice:

    ppt1@pci0:3:0:0:        class=0x0c0330 card=0x12421b21 chip=0x12421b21 rev=0x00 hdr=0x00
  • In modern bhyve, you must supply the -S argument to bhyve in order to get PCI passthrough working. Note that -u is provided to make Windows like my UTC clock:

    iohyve set vm_name_here bargs = "-H -w -S -u"
  • Create the mapping for the PCI device in question:

    iohyve set vm_name_here pcidev:1=passthru,3/0/0
  • Limit or completely disable network access to your virtual server!

No comments: