Skip to content

USB device passthrough for bhyve

nainapatrascu edited this page Sep 3, 2022 · 21 revisions

General

The USB device passthrough feature implementation can be found in freebsd-src repo, the bhyve_usb_passthrough branch:

git clone https://github.com/FreeBSD-UPB/freebsd-src.git
cd freebsd-src
git checkout projects/bhyve_usb_passthrough

In order to build the entire project, follow the steps:

make cleanworld
make buildworld
make buildkernel
make installkernel
shutdown now
make installworld

If you want to build only the world, without a clean up:

make buildworld -DNO_CLEAN -j4
make installworld
reboot

The implementation of the USB device passthrough mechanism is mainly located in bhyve directory:

cd freebsd-src/usr.sbin/bhyve/

When changing only the content of the usr.sbin/bhyve/ directory, you should only build this component:

make clean
make -j4
make install

Starting a virtual machine in bhyve with USB passthrough

Details about attaching a USB device to a virtual machine and booting the guest over bhyve can be found here.

Implementation details

As previously stated, the implementation of the feature is located in bhyve directory. The file pci_xhci.c contains the main changes for shaping the USB device passthrough functionality. It uses the USB Port Mapper located in usb_pmapper.c to map the USB device to the ports of the virtual machine. The USB Port Mapper uses the API from the libusb library to directly interface with the USB device.

The source code for the libusb library can be found at path freebsd-src/lib/libusb/. When changing this component (for adding prints, for example), we should build the world:

make buildworld -DNO_CLEAN -j4
make installworld
reboot

The USB device passthrough implementation can be split in several stages:

  1. Parsing and recognizing the attached USB device

    When attaching a device to a slot of the virtual machine (-s 30,xhci,bus=1,devaddr=2), as described in the previous section, the slot option is parsed by the pci_xhci component (see pci_xhci.c#L3764).

  2. Discovery and initialization (enumeration process)

    In order to initialize the USB device, the xHCI emulator needs to effectuate the enumeration process. The xHCI then executes an internal scan to discover the attached devices and to compare these to the ones specified in the start command of the virtual machine. The xHCI shall determine the port that generated the attachment event and set different registers related to the state of this port (see usb_pmapper.c#L1273).

  3. Attachment to the VM

    The USB device and the xHCI emulator execute an exchange of messages in the form of control transfers in order to obtain information about the device and to configure it. The messages are encapsulated in the form of a usb_xfer and they have different sizes and format based on the transfer type (see pci_xhci.c#L1057). The pci_xhci_handle_transfer (pci_xhci.c#L2330) function manages all transfer types and compose the xfer_block accordingly.

    The attachment of the USB device to the virtual machine is complete when the guest offers an address to the USB device in order to identify it and the ports of the USB device are mapped to the virtual ports of the guest (see pci_xhci.c#L1459).

    Note: the implementation for the USB tablet is separated through the flag tablet set in the pci_xhci_softc structure in the beginning phase of parsing the slot option.

  4. Utilization (reading from / writing to the USB device)

    As stated before, the transfers from the xHCI emulator to the USB device are composed in the pci_xhci_handle_transfer and they are sent to the physical device through the API defined in the usp_pmapper.c#L922, which uses the libusb API to interact with the device. The same USB Port Mapper is utilized to receive the transfers from the USB device and to process them (usb_pmapper.c#L167).

Further work

  • Detach mechanism

As described in Working with virtual machines in bhyve for USB passthrough, the detach mechanism is not implemented at the moment. When powering off the guest machine, it is required to reboot the FreeBSD host in order to completely detach the USB device from the guest and to be able to use it again.

  • Recover tablet functionality

USB tablet implementation is common with the USB device passthrough mechanism, and the USB mouse functionality may have some issues resulted from the development process.

  • USB passthrough for multiple devices at the same time

Resources