Discovering and connecting VirtIO devices

Several methods are available for connecting a device driver in a guest to its external service.

A device driver running in a guest can use one of the following methods to connect to a VirtIO vdev:

The method you use will depend on how your guest is configured, and how easy or difficult you want to make changing the device location. For example, in a production system direct memory mapping (where you write in your configurations the locations in memory of your devices) may be acceptable or even preferable, but you may require a more flexible approach during your project's development phase.

Note: See the QNX SDP Utilities Reference for more information about drivers such as devb-ahci and devb-virtio and their options.

PCI discovery

The PCI discovery method is most common in guests designed for x86 platforms, but it can also be used by guests on ARM platforms. PCI hardware isn't required to support this discovery mechanism, because in a hypervisor guest PCI is completely virtual.

The following illustrates how PCI mapping can be used to enable a driver in a guest to discover and connect to a VirtiO device. The example uses the virtio-blk vdev, but could also be used for other VirtIO vdevs such as virto-console or virtio-net.

Using virtio-blk as our example, and a QNX guest (QNX Neutrino OS or QNX OS for Safety guest):

  1. In the hypervisor host, start the driver for the AHCI SATA interfaces (devb-ahci).
  2. Configure the VM hosting the guest to map the location of the AHCI SATA driver (located at /dev/hd1t178) through VirtIO to the guest; for example:

    vdev virtio-blk
            hostdev /dev/hd1t178
            name virtio-blk_qvm178

    See vdev virtio-blk for more information about configuring this vdev in the VM.

  3. Start the QNX guest.
  4. In the guest, run pci-server (see pci-server in the Utilities Reference); for example:

    pci-server –bus-scan-limit=8
  5. In the QNX guest, use pci-tool to query the PCI device (see pci-tool in the Utilities Reference); for example:

    [x86 guest QNX 7.0]% pci-tool -v
     
    B000:D00:F00 @ idx 0
            vid/did: 1c05/0002
                    BlackBerry QNX, n/a QVM PCI host bridge
            class/subclass/reg: 06/00/00
                    Host-to-PCI Bridge Device
     
    B000:D01:F00 @ idx 1
            vid/did: 1af4/1042
                    <vendor id - unknown>, <device id - unknown>
            class/subclass/reg: 01/80/00
                    Other Mass Storage Controller
     
    B000:D02:F00 @ idx 2
            vid/did: 1af4/1041
                    <vendor id - unknown>, <device id - unknown>
            class/subclass/reg: 02/80/00
                    Other Network Controller
     
    B000:D03:F00 @ idx 3
            vid/did: 1c05/0001
                    BlackBerry QNX, n/a QVM guest shared memory factory
            class/subclass/reg: 05/80/00
                    Other Memory Controller
     
    B000:D04:F00 @ idx 4
            vid/did: 1af4/1043
                    <vendor id - unknown>, <device id - unknown>
            class/subclass/reg: 07/80/00
                    Other Simple Communications Controller

    Note that the disk controller appears with a vid/did (vendor ID/device ID) of 1af4/1042; this is the VirtIO standard reference for a mass storage device. Other devices such as memory devices or network devices will also show up as PCI devices.

    In a Linux guest, you can use lspci. You may see the vendor/device as 1c05/0042; this is the BlackBerry VirtIO vendor ID. The Linux kernel module understands that this is a block device.

  6. In the QNX guest, start the VirtIO driver for block devices (devb-virtio). The driver will scan the PCI space to find the device with the 1af4/1042 vendor ID/device ID, and mount it as a block volume; for example: devb-virtio will create /dev/hd0 in the guest.

  7. If the block volume is already formatted as a QNX6 power-safe filesystem, you can mount it; for example:

    mount -tqnx6 /dev/hd0 /mydisk

Direct memory mapping

The following illustrates how a device can be mapped in the host, then the mapping passed on to a driver in a guest. The example uses the virtio-blk vdev, but could also be used for other VirtIO vdevs such as virto-console or virtio-net.

Using virtio-blk as our example, and a QNX guest (QNX Neutrino OS or QNX OS for Safety guest):

  1. In the hypervisor host, start the driver for the appropriate interfaces (e.g., devb-ahci).
  2. Configure the VM with the path of the host file to use for the contents of the device (see vdev virtio-blk in the Virtual Device Reference chapter).

    Use a location in guest-physical memory that isn't used by any other driver in the guest, and an interrupt that isn't used by any other driver or service in the guest. In this example we use 0x1c0d0000 and 41:

    vdev virtio-blk
            loc 0x1c0d0000
            intr gic:41
            hostdev /dev/hd1t178
            name virtio-blk_qvm178
  3. Start the QNX guest. No PCI server is needed.
  4. Start the VirtIO block device driver (devb-virtio) in the guest, using the driver's startup options to map in the memory and interrupt you specified in the virtio-blk vdev configuration; in our example the options would be as follows:

    devb-virtio virtio smem=0x1c0d0000,irq=41

The devb-virtio driver in the guest should now find the device in the host through the VirtIO device.

Note:

You can use FDTs to expand direct mapping to support dynamic discovery of devices. For example, on an ARM platform you could use entries in the FDT to provide the guest with information about virtual devices.

For more information about using FDT in a QNX hypervisor system, see ACPI tables and FDTs in the Configuration chapter.