Add a user-configurable 'vid' parameter to allow overriding the default
PCI vendor ID. This enables testing of vendor-specific quirks in guest
operating systems.

The parameter accepts a 16-bit hexadecimal value and defaults to Red Hat
vendor ID (0x1b36). It is mutually exclusive with the 'use-intel-id' flag
to prevent conflicting configurations.

Suggested-by: Maurizio Lombardi <[email protected]>
Suggested-by: John Meneghini <[email protected]>
Signed-off-by: Utkarsh Singh <[email protected]>
---
 docs/system/devices/nvme.rst | 8 +++++++-
 hw/nvme/ctrl.c               | 8 +++++++-
 hw/nvme/nvme.h               | 1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst
index 98a4401043..0c0c861579 100644
--- a/docs/system/devices/nvme.rst
+++ b/docs/system/devices/nvme.rst
@@ -51,7 +51,7 @@ parameters.
 ``use-intel-id`` (default: ``off``)
   Since QEMU 5.2, the device uses a QEMU allocated "Red Hat" PCI Device and
   Vendor ID. Set this to ``on`` to revert to the unallocated Intel ID
-  previously used.
+  previously used. This parameter is mutually exclusive with ``vid``.
 
 ``ocp`` (default: ``off``)
   The Open Compute Project defines the Datacenter NVMe SSD Specification that
@@ -65,6 +65,12 @@ parameters.
   to more closely impersonate a particular device type. The model name
   can be a maximum of 40 characters in length.
 
+``vid`` (default: ``0x1b36`` for Red Hat)
+  Override the default PCI vendor ID. This can be used when needing to
+  more closely impersonate a particular device type or test vendor-specific
+  quirks. The vendor ID must be a 16-bit hexadecimal value. This parameter
+  is mutually exclusive with ``use-intel-id``.
+
 ``firmware-version`` (default: current QEMU version number)
   Override the default reported firmware version, which can be used when
   needing to more closely impersonate a particular device type. The version
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 815f39173c..2e57fd3585 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -8610,6 +8610,11 @@ static bool nvme_check_params(NvmeCtrl *n, Error **errp)
         return false;
     }
 
+    if (params->use_intel_id && params->vid != PCI_VENDOR_ID_REDHAT) {
+        error_setg(errp, "use_intel_id and vid are mutually exclusive");
+        return false;
+    }
+
     if (params->model &&
         strlen(params->model) > NVME_ID_CTRL_MN_MAX_LEN) {
         error_setg(errp, "'model' parameter '%s' can be at most '%d' 
characters",
@@ -8976,7 +8981,7 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice 
*pci_dev, Error **errp)
         pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
         pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_NVME);
     } else {
-        pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REDHAT);
+        pci_config_set_vendor_id(pci_conf, n->params.vid);
         pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REDHAT_NVME);
     }
 
@@ -9401,6 +9406,7 @@ static const Property nvme_props[] = {
     DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial),
     DEFINE_PROP_STRING("model", NvmeCtrl, params.model),
     DEFINE_PROP_STRING("firmware-version", NvmeCtrl, params.firmware_version),
+    DEFINE_PROP_UINT16("vid", NvmeCtrl, params.vid, PCI_VENDOR_ID_REDHAT),
     DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, params.cmb_size_mb, 0),
     DEFINE_PROP_UINT32("num_queues", NvmeCtrl, params.num_queues, 0),
     DEFINE_PROP_UINT32("max_ioqpairs", NvmeCtrl, params.max_ioqpairs, 64),
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 5ef3ebee29..25d46ae8d0 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -544,6 +544,7 @@ typedef struct NvmeParams {
     char     *serial;
     char     *model;
     char     *firmware_version;
+    uint16_t vid;
     uint32_t num_queues; /* deprecated since 5.1 */
     uint32_t max_ioqpairs;
     uint16_t msix_qsize;
-- 
2.54.0


Reply via email to