[vfio-users] How to spoof device (sub)class ID for passthrough devices?

Alex Williamson alex.williamson at redhat.com
Sat Feb 9 17:02:11 UTC 2019


On Sat, 9 Feb 2019 14:38:35 +0100
Björn Ruytenberg <bjorn at bjornweb.nl> wrote:

> Hi,
> 
> I am looking for a way to spoof the PCI Device (sub)class ID for
> passthrough devices. The following returns a nice list of options (on
> QEMU 2.11.1), but I can't seem to find one that does just that:
> 
> $ qemu-system-x86_64 -device vfio-pci,? 2>&1 | grep "x-*"
> vfio-pci.x-pci-sub-device-id=uint32
> vfio-pci.x-no-kvm-msi=bool
> vfio-pci.x-pcie-lnksta-dllla=bool (on/off)
> vfio-pci.x-igd-opregion=bool (on/off)
> vfio-pci.x-vga=bool (on/off)
> vfio-pci.x-pci-vendor-id=uint32
> vfio-pci.x-req=bool (on/off)
> vfio-pci.x-igd-gms=uint32
> vfio-pci.x-no-kvm-intx=bool
> vfio-pci.x-pci-device-id=uint32
> vfio-pci.host=str (Address (bus/device/function) of the host device,
> example: 04:10.0)
> vfio-pci.x-no-kvm-msix=bool
> vfio-pci.x-intx-mmap-timeout-ms=uint32
> vfio-pci.bootindex=int32
> vfio-pci.x-pcie-extcap-init=bool (on/off)
> vfio-pci.addr=int32 (Slot and optional function number, example: 06.0 or 06)
> vfio-pci.x-pci-sub-vendor-id=uint32
> vfio-pci.x-nv-gpudirect-clique=uint4 (NVIDIA GPUDirect Clique ID (0 - 15))
> vfio-pci.x-no-mmap=bool
> 
> 
> Is it possible to spoof PCI device class ID? Otherwise, any pointers
> where it can be patched (if possible) will be much appreciated!

Nobody has had a use for this yet, so it doesn't exist.  I think the
below accomplishes it (compile tested only).  It's meant to allow
specifying the entire class code register, so you'll need to specify
the base class and programming interface even if you only want to
change the sub-class.  For instance, to change a VGA device to a 3D
controller you'd specify:

  x-pci-class-code=0x030200

Let us know if it works.  I'd also be curious to understand your use
case to know if this is something we want upstream, ie. is this an
experiment or does it result in something useful?  Thanks,

Alex

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index dd12f363915d..63c4cbc09a26 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2966,6 +2966,17 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
                                               vdev->sub_device_id);
     }
 
+    if (vdev->class_code != ~0) {
+        if (vdev->class_code & ~0xffffffU) {
+            error_setg(errp, "invalid PCI class code provided");
+            goto error;
+        }
+        vfio_add_emulated_long(vdev, PCI_REVISION_ID,
+                               vdev->class_code << 8, ~0xff);
+        trace_vfio_pci_emulated_class_code(vdev->vbasedev.name,
+                                           vdev->class_code);
+    }
+
     /* QEMU can change multi-function devices to single function, or reverse */
     vdev->emulated_config_bits[PCI_HEADER_TYPE] =
                                               PCI_HEADER_TYPE_MULTI_FUNCTION;
@@ -3208,6 +3219,7 @@ static Property vfio_pci_dev_properties[] = {
                        sub_vendor_id, PCI_ANY_ID),
     DEFINE_PROP_UINT32("x-pci-sub-device-id", VFIOPCIDevice,
                        sub_device_id, PCI_ANY_ID),
+    DEFINE_PROP_UINT32("x-pci-class-code", VFIOPCIDevice, class_code, ~0),
     DEFINE_PROP_UINT32("x-igd-gms", VFIOPCIDevice, igd_gms, 0),
     DEFINE_PROP_UNSIGNED_NODEFAULT("x-nv-gpudirect-clique", VFIOPCIDevice,
                                    nv_gpudirect_clique,
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index b1ae4c07549a..900880e9dc9b 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -140,6 +140,7 @@ typedef struct VFIOPCIDevice {
     uint32_t device_id;
     uint32_t sub_vendor_id;
     uint32_t sub_device_id;
+    uint32_t class_code;
     uint32_t features;
 #define VFIO_FEATURE_ENABLE_VGA_BIT 0
 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index f41ca96160bf..809406b860d4 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -48,6 +48,7 @@ vfio_pci_emulated_vendor_id(const char *name, uint16_t val) "%s 0x%04x"
 vfio_pci_emulated_device_id(const char *name, uint16_t val) "%s 0x%04x"
 vfio_pci_emulated_sub_vendor_id(const char *name, uint16_t val) "%s 0x%04x"
 vfio_pci_emulated_sub_device_id(const char *name, uint16_t val) "%s 0x%04x"
+vfio_pci_emulated_class_code(const char *name, uint32_t val) "%s 0x%06x"
 
 # hw/vfio/pci-quirks.c
 vfio_quirk_rom_blacklisted(const char *name, uint16_t vid, uint16_t did) "%s %04x:%04x"




More information about the vfio-users mailing list