[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] hw/nvme: allow to pass a memory backend object for the CMB
From: |
Wertenbroek Rick |
Subject: |
[PATCH] hw/nvme: allow to pass a memory backend object for the CMB |
Date: |
Sat, 16 Apr 2022 09:16:31 +0000 |
Adds the optional -cmbdev= option that takes a QEMU memory backend
-object to be used to for the CMB (Controller Memory Buffer).
This option takes precedence over cmb_size_mb= if both used.
(The size will be deduced from the memory backend option).
Signed-off-by: Rick Wertenbroek <rick.wertenbroek@heig-vd.ch>
---
hw/nvme/ctrl.c | 65 ++++++++++++++++++++++++++++++++++++++------------
hw/nvme/nvme.h | 9 +++----
2 files changed, 55 insertions(+), 19 deletions(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 03760ddeae..9bcc7d6db0 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -29,6 +29,7 @@
* -device nvme-subsys,id=<subsys_id>,nqn=<nqn_id>
* -device nvme,serial=<serial>,id=<bus_name>, \
* cmb_size_mb=<cmb_size_mb[optional]>, \
+ * [cmbdev=<mem_backend_id>,] \
* [pmrdev=<mem_backend_file_id>,] \
* max_ioqpairs=<N[optional]>, \
* aerl=<N[optional]>,aer_max_queued=<N[optional]>, \
@@ -44,6 +45,11 @@
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now. By default, the
* device will use the "v1.4 CMB scheme" - use the `legacy-cmb` parameter to
* always enable the CMBLOC and CMBSZ registers (v1.3 behavior).
+ * Enabling cmb emulation can also be achieved by pointing to a memory-backend
+ * For example:
+ * -object memory-backend-ram,id=<mem_id>,size=<size> \
+ * -device nvme,...,cmbdev=<mem_id>
+ * cmbdev= will take precedence over cmb_size_mb= when both provided.
*
* Enabling pmr emulation can be achieved by pointing to memory-backend-file.
* For example:
@@ -341,16 +347,26 @@ static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr)
return false;
}
- lo = n->params.legacy_cmb ? n->cmb.mem.addr : n->cmb.cba;
- hi = lo + int128_get64(n->cmb.mem.size);
+ if (n->cmb.dev) {
+ lo = n->params.legacy_cmb ?
host_memory_backend_get_memory(n->cmb.dev)->addr : n->cmb.cba;
+ hi = lo +
int128_get64(host_memory_backend_get_memory(n->cmb.dev)->size);
+ } else {
+ lo = n->params.legacy_cmb ? n->cmb.mem.addr : n->cmb.cba;
+ hi = lo + int128_get64(n->cmb.mem.size);
+ }
return addr >= lo && addr < hi;
}
static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr)
{
- hwaddr base = n->params.legacy_cmb ? n->cmb.mem.addr : n->cmb.cba;
- return &n->cmb.buf[addr - base];
+ if (n->cmb.dev) {
+ hwaddr base = n->params.legacy_cmb ?
host_memory_backend_get_memory(n->cmb.dev)->addr : n->cmb.cba;
+ return memory_region_get_ram_ptr(&n->cmb.dev->mr) + (addr - base);
+ } else {
+ hwaddr base = n->params.legacy_cmb ? n->cmb.mem.addr : n->cmb.cba;
+ return &n->cmb.buf[addr - base];
+ }
}
static bool nvme_addr_is_pmr(NvmeCtrl *n, hwaddr addr)
@@ -6584,16 +6600,33 @@ static void nvme_init_state(NvmeCtrl *n)
static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev)
{
- uint64_t cmb_size = n->params.cmb_size_mb * MiB;
+ uint64_t cmb_size;
uint64_t cap = ldq_le_p(&n->bar.cap);
- n->cmb.buf = g_malloc0(cmb_size);
- memory_region_init_io(&n->cmb.mem, OBJECT(n), &nvme_cmb_ops, n,
- "nvme-cmb", cmb_size);
- pci_register_bar(pci_dev, NVME_CMB_BIR,
- PCI_BASE_ADDRESS_SPACE_MEMORY |
- PCI_BASE_ADDRESS_MEM_TYPE_64 |
- PCI_BASE_ADDRESS_MEM_PREFETCH, &n->cmb.mem);
+ if (n->cmb.dev) {
+ if (n->params.cmb_size_mb) {
+ warn_report("Option cmb_size_mb is ignored when a cmbdev is
provided");
+ }
+ n->params.cmb_size_mb = n->cmb.dev->size / MiB;
+ cmb_size = n->cmb.dev->size;
+
+ MemoryRegion *mr = host_memory_backend_get_memory(n->cmb.dev);
+ assert(mr);
+
+ pci_register_bar(pci_dev, NVME_CMB_BIR,
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64 |
+ PCI_BASE_ADDRESS_MEM_PREFETCH, mr);
+ } else {
+ cmb_size = n->params.cmb_size_mb * MiB;
+ n->cmb.buf = g_malloc0(cmb_size);
+ memory_region_init_io(&n->cmb.mem, OBJECT(n), &nvme_cmb_ops, n,
+ "nvme-cmb", cmb_size);
+ pci_register_bar(pci_dev, NVME_CMB_BIR,
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64 |
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->cmb.mem);
+ }
NVME_CAP_SET_CMBS(cap, 1);
stq_le_p(&n->bar.cap, cap);
@@ -6678,7 +6711,7 @@ static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev,
Error **errp)
}
}
- if (n->params.cmb_size_mb) {
+ if (n->params.cmb_size_mb || n->cmb.dev) {
nvme_init_cmb(n, pci_dev);
}
@@ -6793,7 +6826,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice
*pci_dev)
NVME_CAP_SET_CSS(cap, NVME_CAP_CSS_CSI_SUPP);
NVME_CAP_SET_CSS(cap, NVME_CAP_CSS_ADMIN_ONLY);
NVME_CAP_SET_MPSMAX(cap, 4);
- NVME_CAP_SET_CMBS(cap, n->params.cmb_size_mb ? 1 : 0);
+ NVME_CAP_SET_CMBS(cap, (n->params.cmb_size_mb || n->cmb.dev) ? 1 : 0);
NVME_CAP_SET_PMRS(cap, n->pmr.dev ? 1 : 0);
stq_le_p(&n->bar.cap, cap);
@@ -6893,7 +6926,7 @@ static void nvme_exit(PCIDevice *pci_dev)
g_free(n->sq);
g_free(n->aer_reqs);
- if (n->params.cmb_size_mb) {
+ if (!n->cmb.dev && n->params.cmb_size_mb) {
g_free(n->cmb.buf);
}
@@ -6908,6 +6941,8 @@ static Property nvme_props[] = {
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf),
DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmr.dev, TYPE_MEMORY_BACKEND,
HostMemoryBackend *),
+ DEFINE_PROP_LINK("cmbdev", NvmeCtrl, cmb.dev, TYPE_MEMORY_BACKEND,
+ HostMemoryBackend *),
DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys, TYPE_NVME_SUBSYS,
NvmeSubsystem *),
DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial),
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 739c8b8f79..63747cf967 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -434,10 +434,11 @@ typedef struct NvmeCtrl {
uint8_t smart_critical_warning;
struct {
- MemoryRegion mem;
- uint8_t *buf;
- bool cmse;
- hwaddr cba;
+ MemoryRegion mem;
+ HostMemoryBackend *dev;
+ uint8_t *buf;
+ bool cmse;
+ hwaddr cba;
} cmb;
struct {
--
2.24.3 (Apple Git-128)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] hw/nvme: allow to pass a memory backend object for the CMB,
Wertenbroek Rick <=