Add a `model` parameter, readable with nvme-cli. This allows
impersonating other disk manufacturers or hypervisors, similar
to the the -smbios option.

Signed-off-by: Avi Kivity <[email protected]>
---

Disclosure: prepared with AI assistance. I believe it to be of good
quality.

 docs/system/devices/nvme.rst | 8 ++++++++
 hw/nvme/ctrl.c               | 4 +++-
 hw/nvme/nvme.h               | 1 +
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst
index 6509b35fcb..1d4dd66d65 100644
--- a/docs/system/devices/nvme.rst
+++ b/docs/system/devices/nvme.rst
@@ -58,10 +58,18 @@ parameters.
   sits on top of NVMe. It describes additional commands and NVMe behaviors
   specific for the Datacenter. When this option is ``on`` OCP features such as
   the SMART / Health information extended log become available in the
   controller. We emulate version 5 of this log page.
 
+``model`` (default: ``QEMU NVMe Ctrl``)
+  Set the model name reported in the Identify Controller data structure (field
+  ``MN``). The value is visible to the guest as
+  ``/sys/class/nvme/<name>/model``. This is useful for emulating specific
+  NVMe devices; for example, setting ``model=Amazon Elastic Block Store``
+  allows guest software to distinguish emulated EBS volumes from instance
+  storage.
+
 Additional Namespaces
 ---------------------
 
 In the simplest possible invocation sketched above, the device only support a
 single namespace with the namespace identifier ``1``. To support multiple
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index cc4593cd42..2d1fb7a209 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -9092,11 +9092,12 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
     memcpy(n->cse.iocs.zoned, nvme_cse_iocs_zoned_default,
            sizeof(n->cse.iocs.zoned));
 
     id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));
     id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));
-    strpadcpy((char *)id->mn, sizeof(id->mn), "QEMU NVMe Ctrl", ' ');
+    strpadcpy((char *)id->mn, sizeof(id->mn),
+              n->params.model ? n->params.model : "QEMU NVMe Ctrl", ' ');
     strpadcpy((char *)id->fr, sizeof(id->fr), QEMU_VERSION, ' ');
     strpadcpy((char *)id->sn, sizeof(id->sn), n->params.serial, ' ');
 
     id->cntlid = cpu_to_le16(n->cntlid);
 
@@ -9372,10 +9373,11 @@ static const Property nvme_props[] = {
     DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmr.dev, TYPE_MEMORY_BACKEND,
                      HostMemoryBackend *),
     DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys, TYPE_NVME_SUBSYS,
                      NvmeSubsystem *),
     DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial),
+    DEFINE_PROP_STRING("model", NvmeCtrl, params.model),
     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),
     DEFINE_PROP_UINT16("msix_qsize", NvmeCtrl, params.msix_qsize, 65),
     DEFINE_PROP_UINT8("aerl", NvmeCtrl, params.aerl, 3),
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index d66f7dc82d..ebf1fcfdcd 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -540,10 +540,11 @@ typedef struct NvmeCQueue {
 #define NVME(obj) \
         OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
 
 typedef struct NvmeParams {
     char     *serial;
+    char     *model;
     uint32_t num_queues; /* deprecated since 5.1 */
     uint32_t max_ioqpairs;
     uint16_t msix_qsize;
     uint16_t mqes;
     uint32_t cmb_size_mb;
-- 
2.53.0


Reply via email to