On 5/24/25 23:31, Tomita Moeko wrote: > Introduce x-pci-class-code option to allow users to override PCI class > code of a device, similar to the existing x-pci-vendor-id option. Only > the lower 24 bits of this option are used, though a uint32 is used here > for determining whether the value is valid and set by user. > > This is mainly intended for IGD devices that expose themselves either > as VGA controller (primary display) or Display controller (non-primary > display). The UEFI GOP driver depends on the device reporting a VGA > controller class code (0x030000). > > Signed-off-by: Tomita Moeko <tomitamo...@gmail.com> > --- > hw/vfio/pci.c | 17 +++++++++++++++++ > hw/vfio/pci.h | 1 + > hw/vfio/trace-events | 1 + > 3 files changed, 19 insertions(+) > > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c > index a1bfdfe375..879347a54e 100644 > --- a/hw/vfio/pci.c > +++ b/hw/vfio/pci.c > @@ -3062,6 +3062,21 @@ static bool vfio_pci_config_setup(VFIOPCIDevice *vdev, > Error **errp) > vdev->sub_device_id); > } > > + /* > + * Class code is a 24-bit value at config space 0x09. Allow overriding it > + * with any 24-bit value. > + */ > + if (vdev->class_code != PCI_ANY_ID) { > + if (vdev->class_code > 0xffffff) { > + error_setg(errp, "invalid PCI class code provided"); > + return false; > + } > + /* Higher 24 bits of PCI_CLASS_REVISION are class code */ > + vfio_add_emulated_long(vdev, PCI_CLASS_REVISION, > + vdev->class_code << 8, ~0xff); > + trace_vfio_pci_emulated_class_code(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; > @@ -3482,6 +3497,8 @@ static const 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, PCI_ANY_ID), > 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 5ce0fb916f..587eb8cc9a 100644 > --- a/hw/vfio/pci.h > +++ b/hw/vfio/pci.h > @@ -156,6 +156,7 @@ 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 e90ec9bff8..d0b006aa29 100644 > --- a/hw/vfio/trace-events > +++ b/hw/vfio/trace-events > @@ -46,6 +46,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, uint16_t val) "%s 0x%06x" ^^^^^^^^ Sorry there is a mistake, it should be `uint32_t` here...
> # pci-quirks.c > vfio_quirk_rom_in_denylist(const char *name, uint16_t vid, uint16_t did) "%s > %04x:%04x"