Cyborg NVMe driver development environment¶
Overview¶
This guide provides instructions for configuring NVMe (Non-Volatile Memory Express) and virtio-rng (Random Number Generator) device emulation and setting up the PCI driver in Cyborg for development and testing.
The PCI driver in Cyborg enables passthrough of PCI devices (including NVMe controllers and RNG devices) to instances. This guide covers the complete setup from adding emulated devices to a development VM through verifying device discovery in Cyborg.
Prerequisites¶
Before following this guide, ensure you have:
A development VM created and configured (see Creating Development VMs for Testing)
SSH access to your development VM
Basic understanding of PCI passthrough and device management
Important
Add NVMe devices and configure vIOMMU before installing DevStack. The devices need to be present when Cyborg agent starts for proper discovery.
Scope¶
This guide covers:
Verifying QEMU NVMe device support on the host
Adding NVMe devices to an existing libvirt VM
Adding virtio-rng devices to an existing libvirt VM (optional)
Configuring the PCI driver in DevStack/Cyborg
Verifying device discovery in Cyborg
Verify NVMe Support¶
On your host system (not inside the VM), verify that QEMU supports NVMe device emulation:
$ qemu-kvm -device help | grep nvme
name "nvme", bus PCI
name "nvme-ns", bus nvme-bus
name "nvme-subsys"
If you see output similar to above, NVMe device emulation is supported.
Enable vIOMMU Support¶
Before adding NVMe devices, enable virtual IOMMU (vIOMMU) in the VM. This is required for PCI device passthrough - without it, Cyborg can discover devices but cannot bind them to instances.
Important
Enable vIOMMU before installing DevStack. Cyborg and Nova rely on IOMMU groups for device management and instance attachment.
Shutdown the VM¶
Before modifying the VM configuration, shut it down gracefully:
$ sudo virsh shutdown cyborg-devstack
Wait for the VM to shut down completely:
$ sudo virsh list --all
Id Name State
------------------------------------
- cyborg-devstack shut off
Add vIOMMU Configuration¶
Edit the VM XML configuration:
$ sudo virsh edit cyborg-devstack
Add the vIOMMU configuration inside the <devices> section, before the
closing </devices> tag:
<iommu model='intel'>
<driver intremap='on' caching_mode='on' eim='on' iotlb='on'/>
</iommu>
Save and exit (in vim: :wq).
Start the VM¶
Start the VM with vIOMMU enabled:
$ sudo virsh start cyborg-devstack
Verify vIOMMU is Working¶
SSH into the VM and verify IOMMU groups exist:
$ ssh <username>@<vm-ip-address>
$ find /sys/kernel/iommu_groups/ -type l | wc -l
15
This should return a non-zero value (typically 10-20 depending on VM configuration). If zero, vIOMMU is not working - check the XML configuration.
Add NVMe Devices to VM¶
Now that vIOMMU is enabled, you can add NVMe devices to the VM using native libvirt configuration.
The Cyborg repository includes a complete VM definition with vIOMMU and NVMe
devices at <cyborg-repo>/devstack/cyborg_vm.xml for reference.
Shutdown the VM¶
Before adding NVMe devices, shut down the VM again:
$ sudo virsh shutdown cyborg-devstack
Wait for the VM to shut down completely:
$ sudo virsh list --all
Id Name State
------------------------------------
- cyborg-devstack shut off
Create NVMe Backing Storage¶
Create a qcow2 disk image to back the emulated NVMe device:
$ sudo qemu-img create -f qcow2 /var/lib/libvirt/images/nvme-disk1.qcow2 10G
Set proper ownership:
$ sudo chown qemu:qemu /var/lib/libvirt/images/nvme-disk1.qcow2
Edit VM Configuration¶
Edit the VM XML to add NVMe device configuration:
$ sudo virsh edit cyborg-devstack
Add an NVMe controller inside the <devices> section:
<controller type='nvme' index='0'/>
Add the NVMe disk configuration inside the <devices> section, after other
disk definitions:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/nvme-disk1.qcow2'/>
<target dev='nvme0n1' bus='nvme'/>
<serial>NVME0001</serial>
</disk>
Explanation of NVMe configuration:
<controller type='nvme' index='0'/>: Creates an NVMe controller for attaching NVMe namespaces<disk type='file' device='disk'>: Defines an NVMe disk device<driver name='qemu' type='qcow2'/>: Uses QEMU with qcow2 format<source file='/var/lib/libvirt/images/nvme-disk1.qcow2'/>: Path to the backing storage<target dev='nvme0n1' bus='nvme'/>: Attach as NVMe device nvme0n1<serial>NVME0001</serial>: Serial number for the NVMe controller (required)
Save and exit the editor (in vim: :wq).
Reference: For a complete VM XML example with NVMe devices, see
<cyborg-repo>/devstack/cyborg_vm.xml.
Add RNG Device (Optional)¶
You can also add a virtio-rng (Random Number Generator) device to the VM for additional PCI device testing. This is useful for testing multiple device types with the PCI driver.
Edit the VM XML configuration:
$ sudo virsh edit cyborg-devstack
Add the RNG device configuration inside the <devices> section:
<rng model='virtio'>
<rate bytes='1024' period='1000'/>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</rng>
Explanation of RNG configuration:
<rng model='virtio'>: Creates a virtio-based RNG device<rate bytes='1024' period='1000'>: Limits entropy generation to 1024 bytes per second (optional but recommended)<backend model='random'>/dev/urandom</backend>: Uses host’s /dev/urandom as entropy source<address type='pci' ...>: Assigns a specific PCI address to the device (adjust bus/slot numbers to avoid conflicts with existing devices)
Note: The RNG device is already included in the reference VM XML at
<cyborg-repo>/devstack/cyborg_vm.xml.
Save and exit the editor (in vim: :wq).
Start the VM¶
Start the VM with the new NVMe and RNG device configuration:
$ sudo virsh start cyborg-devstack
Verify NVMe Devices in VM¶
SSH to the VM and verify that the NVMe device is visible.
Install Required Tools¶
Install PCI utilities and NVMe tools:
$ sudo apt update
$ sudo apt install -y pciutils nvme-cli
List PCI Devices¶
List all PCI devices to find the NVMe controller:
$ lspci -nn | grep -i non-volatile
00:12.0 Non-Volatile memory controller [0108]: Red Hat, Inc. QEMU NVMe Controller [1b36:0010] (rev 02)
Note the vendor ID (1b36) and product ID (0010) - you’ll need these for
the PCI driver configuration.
List NVMe Devices¶
Use nvme-cli to list NVMe devices:
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 NVME0001 QEMU NVMe Ctrl 1 10.74 GB / 10.74 GB 512 B + 0 B 1.0
Verify the device appears as /dev/nvme0n1:
$ ls -l /dev/nvme*
crw------- 1 root root 243, 0 Jan 15 10:30 /dev/nvme0
brw-rw---- 1 root disk 259, 0 Jan 15 10:30 /dev/nvme0n1
Verify RNG Device (if added)¶
If you added the virtio-rng device, verify it appears in the PCI device list:
$ lspci -nn | grep -i virtio
00:13.0 Unclassified device [00ff]: Red Hat, Inc. Virtio RNG [1af4:1044] (rev 01)
Note the vendor ID (1af4) and product ID (1044) - you’ll need these if
you want to add the RNG device to the PCI driver whitelist.
Verify the RNG device is functional:
$ cat /sys/devices/virtual/misc/hw_random/rng_available
virtio_rng.0
$ cat /sys/devices/virtual/misc/hw_random/rng_current
virtio_rng.0
Configure PCI Driver in DevStack¶
The PCI driver in Cyborg requires configuration to specify which PCI devices should be managed. This is done by adding PCI passthrough whitelist entries to the Cyborg configuration.
Update local.conf¶
Edit your DevStack local.conf file to enable the PCI driver and configure
the passthrough whitelist.
In your ~/devstack/local.conf file, add or update the following sections:
# Enable both fake and PCI drivers
# --------------------------------
CYBORG_ENABLED_DRIVERS=fake_driver,pci_driver
# Configure PCI passthrough whitelist for NVMe device
# ---------------------------------------------------
# Find device IDs with: lspci -nn | grep -i Non-Volatile
# Example: Red Hat QEMU NVMe Controller [1b36:0010]
[[post-config|$CYBORG_CONF_FILE]]
[pci]
# NVMe device passthrough (vendor_id: 1b36, product_id: 0010)
passthrough_whitelist='{"vendor_id":"1b36","product_id":"0010"}'
# To add multiple devices including virtio-rng, use a JSON array:
# passthrough_whitelist='[{"vendor_id":"1b36","product_id":"0010"},{"vendor_id":"1af4","product_id":"1044"}]'
Configuration explanation:
CYBORG_ENABLED_DRIVERS: Enables both the fake driver (for testing) and the PCI driver[[post-config|$CYBORG_CONF_FILE]]: Adds configuration tocyborg.confafter DevStack generates it[pci]: Configuration section for the PCI driverpassthrough_whitelist: JSON string specifying which PCI devices to managevendor_id: PCI vendor ID (found usinglspci -nn)product_id: PCI product ID (found usinglspci -nn)
Managing Multiple Device Types
To manage multiple device types (e.g., NVMe + RNG), specify multiple whitelist entries as a JSON array:
[[post-config|$CYBORG_CONF_FILE]]
[pci]
# Whitelist both NVMe and virtio-rng devices
passthrough_whitelist='[{"vendor_id":"1b36","product_id":"0010"},{"vendor_id":"1af4","product_id":"1044"}]'
This configuration enables:
NVMe device:
vendor_id=1b36, product_id=0010(QEMU NVMe Controller)RNG device:
vendor_id=1af4, product_id=1044(Virtio RNG)
Finding Device IDs¶
To find the vendor and product IDs for any PCI device:
$ lspci -nn
...
00:12.0 Non-Volatile memory controller [0108]: Red Hat, Inc. QEMU NVMe Controller [1b36:0010] (rev 02)
...
The format is [vendor_id:product_id], so [1b36:0010] means:
Vendor ID:
1b36(Red Hat, Inc.)Product ID:
0010(QEMU NVMe Controller)
Run DevStack¶
After updating local.conf, run DevStack to apply the configuration:
$ cd ~/devstack
$ ./stack.sh
This will take 30-60 minutes to complete. The PCI driver will be loaded and will discover the whitelisted PCI devices.
For complete DevStack setup instructions, see DevStack Setup for Development.
Verify Device Discovery¶
After DevStack completes successfully, verify that Cyborg has discovered the NVMe and other PCI devices.
Source OpenStack Credentials¶
$ source ~/devstack/openrc admin admin
List Accelerator Devices¶
$ openstack accelerator device list
+--------------------------------------+------+--------+-----------------+------------------------------------------------+
| uuid | type | vendor | hostname | std_board_info |
+--------------------------------------+------+--------+-----------------+------------------------------------------------+
| ece74dd7-c15f-4dca-b68f-f6fe189fcc1e | GPU | 1af4 | cyborg-devstack | {"product_id": "1044", "controller": null} |
| 57763ef1-47cf-46b2-9d1d-047a16daf90b | FPGA | 0xABCD | cyborg-devstack | {"device_id": "0xabcd", "class": "Fake class"} |
| 815146e7-48a3-4906-a0b5-47aee53abada | GPU | 1b36 | cyborg-devstack | {"product_id": "0010", "controller": null} |
+--------------------------------------+------+--------+-----------------+------------------------------------------------+
Expected output:
Fake FPGA device: Provided by the
fake_driverfor testingType:
FPGAVendor:
0xABCD
NVMe device: Managed by the
pci_driverType:
GPU(the PCI driver uses GPU as a generic type for PCI devices)Vendor:
1b36(Red Hat, Inc.)Product:
0010(QEMU NVMe Controller)
RNG device (if enabled in whitelist): Managed by the
pci_driverType:
GPU(the PCI driver uses GPU as a generic type for PCI devices)Vendor:
1af4(Red Hat, Inc.)Product:
1044(Virtio RNG)
Note: The PCI driver reports all managed PCI devices with type GPU -
this is expected behavior and does not indicate an error. The actual device
type can be determined from the vendor and product IDs in std_board_info.
Troubleshooting¶
Device Not Discovered¶
If the device doesn’t appear in openstack accelerator device list:
Verify the device is visible in the VM:
$ lspci -nn | grep -i non-volatile
Check that the vendor/product IDs in
local.confmatchlspcioutputVerify the PCI driver is enabled:
$ sudo grep -i "enabled_drivers" /etc/cyborg/cyborg.conf enabled_drivers = fake_driver,pci_driver
Check Cyborg agent logs:
$ sudo journalctl -u devstack@cyborg-agent | grep -i pci
Restart Cyborg services:
$ sudo systemctl restart devstack@cyborg-agent
References¶
DevStack Setup for Development - DevStack setup guide
Creating Development VMs for Testing - VM creation guide
Driver Development Guide - Driver development guide