docs/system/devices/nvme.rst | 18 +++++++--- hw/core/machine.c | 4 ++- hw/nvme/ctrl.c | 83 +++++++++++--------------------------------- hw/nvme/nvme.h | 11 +++--- 4 files changed, 43 insertions(+), 73 deletions(-)
From: Jesper Wendel Devantier <j.devantier@samsung.com>
Introduce properties to set PCI device and vendor IDs and
PCI subsystem- and subsystem vendor IDs.
Additionally, make IEEE.OUI configurable through a property.
This replaces the old 'use-intel-id' property, which changed some
of these values and streamlines the code to use these properties
instead of branching on use-intel-id.
The documentation for the NVMe device and the compatibility flags
for QEMU 5.1 (and lower) machines are updated to reflect this
change.
Signed-off-by: Jesper Wendel Devantier <foss@defmacro.it>
---
This is based on V4 of the patch series by Saif Abrar which
adds additional properties for specifying PCI vendor- and
device IDs and PCI subsystem [vendor] IDs and the ability
to specify the IEEE OUI (Organizationally Unique ID) value.
(See link below).
Chiefly, this patch goes a step further, simplifying the
code by removing the old use-intel-id property since these
new properties collectively can achieve the same.
Original Series:
https://lore.kernel.org/qemu-devel/20251127120322.2997269-1-saif.abrar@linux.vnet.ibm.com/
Tested-by: Jesper Wendel Devantier <foss@defmacro.it>
---
docs/system/devices/nvme.rst | 18 +++++++---
hw/core/machine.c | 4 ++-
hw/nvme/ctrl.c | 83 +++++++++++---------------------------------
hw/nvme/nvme.h | 11 +++---
4 files changed, 43 insertions(+), 73 deletions(-)
diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst
index 6509b35fcb4e42d59f04e678d709f83af06f95af..c5f90cb1b409a62fc49433ca5e3e9c1afea4b065 100644
--- a/docs/system/devices/nvme.rst
+++ b/docs/system/devices/nvme.rst
@@ -48,10 +48,20 @@ parameters.
``mdts=UINT8`` (default: ``7``)
Set the Maximum Data Transfer Size of the device.
-``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.
+``pci.vid`` (default: ``0x1b36``, Red Hat)
+ Since QEMU 5.2, the device uses a QEMU allocated "Red Hat" PCI vendor ID.
+ Set this to ``0x8086`` to revert to the unallocated Intel ID.
+ This is one of the parameters replacing the ``use-intel-id`` parameter.
+
+``pci.did`` (default: ``0x0010``, Red Hat)
+ Since QEMU 5.2, the device uses a QEMU allocated "Red Hat" PCI device ID.
+ Set this to ``0x5845`` to revert to the unallocated Intel ID.
+ This is one of the parameters replacing the ``use-intel-id`` parameter.
+
+``ieee.oui`` (default: ``0x525400``, Red Hat)
+ Since QEMU 5.2, the device uses a QEMU allocated "Red Hat" Organization
+ Unique Id (OUI). Set this to ``0xb30200`` to revert to the Intel OUI.
+ This is one of the parameters replacing the ``use-intel-id`` parameter.
``ocp`` (default: ``off``)
The Open Compute Project defines the Datacenter NVMe SSD Specification that
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 06e0c9a179bb3e6e140d54cb9687caaa59ee0e61..51ebfd8215eb8824191649ca7289a9b5cb3af90c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -165,7 +165,9 @@ GlobalProperty hw_compat_5_1[] = {
{ "vhost-user-scsi", "num_queues", "1"},
{ "virtio-blk-device", "num-queues", "1"},
{ "virtio-scsi-device", "num_queues", "1"},
- { "nvme", "use-intel-id", "on"},
+ { "nvme", "pci.did", "0x5845"},
+ { "nvme", "pci.vid", "0x8086"},
+ { "nvme", "ieee.oui", "0x0002b3"},
{ "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */
{ "pl011", "migrate-clk", "off" },
{ "virtio-pci", "x-ats-page-aligned", "off"},
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index c66524c78cde4e3176d754a006a476dc56156cb5..a815c0cd74f64e04ecc88280d3be73ebb618de45 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -8876,10 +8876,7 @@ out:
static bool nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset,
Error **errp)
{
- uint16_t vf_dev_id = n->params.use_intel_id ?
- PCI_DEVICE_ID_INTEL_NVME :
- (n->params.id_device ?
- n->params.id_device : PCI_DEVICE_ID_REDHAT_NVME);
+ uint16_t vf_dev_id = n->params.pci.did;
NvmePriCtrlCap *cap = &n->pri_ctrl_cap;
uint64_t bar_size = nvme_mbar_size(le16_to_cpu(cap->vqfrsm),
@@ -8952,27 +8949,11 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
pci_conf[PCI_INTERRUPT_PIN] = pci_is_vf(pci_dev) ? 0 : 1;
pci_config_set_prog_interface(pci_conf, 0x2);
- if (n->params.use_intel_id) {
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_NVME);
- } else {
- uint16_t id_vendor = n->params.id_vendor ?
- n->params.id_vendor : PCI_VENDOR_ID_REDHAT;
- pci_config_set_vendor_id(pci_conf, id_vendor);
-
- uint16_t id_device = n->params.id_device ?
- n->params.id_device : PCI_DEVICE_ID_REDHAT_NVME;
- pci_config_set_device_id(pci_conf, id_device);
-
- if (n->params.id_subsys_vendor) {
- pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID,
- n->params.id_subsys_vendor);
- }
+ pci_config_set_vendor_id(pci_conf, n->params.pci.vid);
+ pci_config_set_device_id(pci_conf, n->params.pci.did);
- if (n->params.id_subsys) {
- pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, n->params.id_subsys);
- }
- }
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, n->params.pci.ssvid);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, n->params.pci.ssid);
pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_EXPRESS);
nvme_add_pm_capability(pci_dev, 0x60);
@@ -9103,6 +9084,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
NvmeSecCtrlEntry *sctrl = nvme_sctrl(n);
uint32_t ctratt = le32_to_cpu(id->ctratt);
uint16_t oacs;
+ uint32_t ieee_oui;
memcpy(n->cse.acs, nvme_cse_acs_default, sizeof(n->cse.acs));
memcpy(n->cse.iocs.nvm, nvme_cse_iocs_nvm_default, sizeof(n->cse.iocs.nvm));
@@ -9127,19 +9109,10 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
id->rab = 6;
- if (n->params.use_intel_id) {
- id->ieee[0] = 0xb3;
- id->ieee[1] = 0x02;
- id->ieee[2] = 0x00;
- } else if (n->params.ieee_oui) {
- id->ieee[0] = extract32(n->params.ieee_oui, 0, 8);
- id->ieee[1] = extract32(n->params.ieee_oui, 8, 8);
- id->ieee[2] = extract32(n->params.ieee_oui, 16, 8);
- } else {
- id->ieee[0] = 0x00;
- id->ieee[1] = 0x54;
- id->ieee[2] = 0x52;
- }
+ ieee_oui = cpu_to_le32(n->params.ieee_oui);
+ id->ieee[0] = extract32(ieee_oui, 0, 8);
+ id->ieee[1] = extract32(ieee_oui, 8, 8);
+ id->ieee[2] = extract32(ieee_oui, 16, 8);
id->mdts = n->params.mdts;
id->ver = cpu_to_le32(NVME_SPEC_VER);
@@ -9388,24 +9361,6 @@ static void nvme_exit(PCIDevice *pci_dev)
memory_region_del_subregion(&n->bar0, &n->iomem);
}
-static void nvme_prop_ieee_set(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- Property *prop = opaque;
- uint32_t *val = object_field_prop_ptr(obj, prop);
- if (!visit_type_uint32(v, name, val, errp)) {
- return;
- }
-}
-
-static const PropertyInfo nvme_prop_ieee = {
- .type = "uint32",
- .description = "IEEE OUI: Identify Controller bytes 75:73\
- in LE format. (e.g. ieee_oui=0xABCDEF => Byte[73]=0xEF, Byte[74]=0xCD,\
- Byte[75]=0xAB)",
- .set = nvme_prop_ieee_set,
-};
-
static const Property nvme_props[] = {
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf),
DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmr.dev, TYPE_MEMORY_BACKEND,
@@ -9421,7 +9376,6 @@ static const Property nvme_props[] = {
DEFINE_PROP_UINT32("aer_max_queued", NvmeCtrl, params.aer_max_queued, 64),
DEFINE_PROP_UINT8("mdts", NvmeCtrl, params.mdts, 7),
DEFINE_PROP_UINT8("vsl", NvmeCtrl, params.vsl, 7),
- DEFINE_PROP_BOOL("use-intel-id", NvmeCtrl, params.use_intel_id, false),
DEFINE_PROP_BOOL("legacy-cmb", NvmeCtrl, params.legacy_cmb, false),
DEFINE_PROP_BOOL("ioeventfd", NvmeCtrl, params.ioeventfd, false),
DEFINE_PROP_BOOL("dbcs", NvmeCtrl, params.dbcs, true),
@@ -9448,13 +9402,16 @@ static const Property nvme_props[] = {
DEFINE_PROP_UINT16("atomic.awun", NvmeCtrl, params.atomic_awun, 0),
DEFINE_PROP_UINT16("atomic.awupf", NvmeCtrl, params.atomic_awupf, 0),
DEFINE_PROP_BOOL("ocp", NvmeCtrl, params.ocp, false),
- DEFINE_PROP_UINT16("id_vendor", NvmeCtrl, params.id_vendor, 0),
- DEFINE_PROP_UINT16("id_device", NvmeCtrl, params.id_device, 0),
- DEFINE_PROP_UINT16("id_subsys_vendor", NvmeCtrl,
- params.id_subsys_vendor, 0),
- DEFINE_PROP_UINT16("id_subsys", NvmeCtrl, params.id_subsys, 0),
- DEFINE_PROP("ieee_oui", NvmeCtrl, params.ieee_oui, nvme_prop_ieee,
- uint32_t),
+ DEFINE_PROP_UINT16("pci.vid", NvmeCtrl,
+ params.pci.vid, PCI_VENDOR_ID_REDHAT),
+ DEFINE_PROP_UINT16("pci.ssvid", NvmeCtrl,
+ params.pci.ssvid, PCI_VENDOR_ID_REDHAT_QUMRANET),
+ DEFINE_PROP_UINT16("pci.did", NvmeCtrl,
+ params.pci.did, PCI_DEVICE_ID_REDHAT_NVME),
+ DEFINE_PROP_UINT16("pci.ssid", NvmeCtrl,
+ params.pci.ssid, PCI_SUBDEVICE_ID_QEMU),
+ DEFINE_PROP_UINT32("ieee.oui", NvmeCtrl,
+ params.ieee_oui, 0x525400),
};
static void nvme_get_smart_warning(Object *obj, Visitor *v, const char *name,
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index be49acaec6b5e99fbd079790732fdf4c9c46a631..ceae62979a1208045534665b18a5446f0f9b2c9b 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -550,7 +550,6 @@ typedef struct NvmeParams {
uint32_t aer_max_queued;
uint8_t mdts;
uint8_t vsl;
- bool use_intel_id;
uint8_t zasl;
bool auto_transition_zones;
bool legacy_cmb;
@@ -572,10 +571,12 @@ typedef struct NvmeParams {
uint16_t atomic_awupf;
bool atomic_dn;
- uint16_t id_vendor;
- uint16_t id_device;
- uint16_t id_subsys_vendor;
- uint16_t id_subsys;
+ struct {
+ uint16_t vid;
+ uint16_t ssvid;
+ uint16_t did;
+ uint16_t ssid;
+ } pci;
uint32_t ieee_oui;
} NvmeParams;
---
base-commit: 39eacce671c1908bc3afcd5a65da0491fe1290e6
change-id: 20251219-q-saif-pci-oui-props-8895da978ba2
Best regards,
--
Jesper Wendel Devantier <j.devantier@samsung.com>
© 2016 - 2026 Red Hat, Inc.