All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB
@ 2022-04-19  7:20 Wertenbroek Rick
  2022-06-03 20:43 ` Klaus Jensen
  0 siblings, 1 reply; 4+ messages in thread
From: Wertenbroek Rick @ 2022-04-19  7:20 UTC (permalink / raw)
  To: qemu-block; +Cc: Keith Busch, Klaus Jensen, qemu-devel

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)



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB
  2022-04-19  7:20 [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB Wertenbroek Rick
@ 2022-06-03 20:43 ` Klaus Jensen
  2022-06-07 11:40   ` Wertenbroek Rick
  0 siblings, 1 reply; 4+ messages in thread
From: Klaus Jensen @ 2022-06-03 20:43 UTC (permalink / raw)
  To: Wertenbroek Rick; +Cc: qemu-block, qemu-devel, Keith Busch

[-- Attachment #1: Type: text/plain, Size: 942 bytes --]

On Apr 19 07:20, Wertenbroek Rick wrote:
> 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(-)
> 

This all looks reasonable enought and straight-forward. But I can't seem
to apply the patch for some reason. git is complaining about 'patch
format detection failed.' and trying to apply manually with patch I'm
getting a 'patch: **** malformed patch at line 55: }'.

Can you try to recreate the patch? Or if you can just put it in a git
repo somewhere, then I can cherry-pick it from there.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB
  2022-06-03 20:43 ` Klaus Jensen
@ 2022-06-07 11:40   ` Wertenbroek Rick
  2022-06-07 12:01     ` Wertenbroek Rick
  0 siblings, 1 reply; 4+ messages in thread
From: Wertenbroek Rick @ 2022-06-07 11:40 UTC (permalink / raw)
  To: Klaus Jensen; +Cc: qemu-block, qemu-devel, Keith Busch

Hello,
Sorry about that, I had the same issue with the patch for some reason, I think it is the git send email that
messed up the patch (couldn’t directly send via smtp so I created a draft via IMAP before sending).
Anyway, below is the patch, it was created on the master branch (commit 81c7ed41a1b33031f3e4fe24191a998a492044b8).
I copy pasted the contents (plain text) of the .patch and could apply it.
Let me know if this doesn’t work and I’ll fork the QEMU git and make the patch available there.

From 79b622edbf3032751250822007ef11b2d7de31e2 Mon Sep 17 00:00:00 2001
Message-Id: <79b622edbf3032751250822007ef11b2d7de31e2.1648820166.git.rick.wertenbroek@heig-vd.ch>
From: Rick Wertenbroek <rick.wertenbroek@heig-vd.ch>
Date: Fri, 1 Apr 2022 15:05:07 +0200
Subject: [PATCH] hw/nvme: allow to pass a memory backend object for the CMB

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)

> On 3 Jun 2022, at 22:43, Klaus Jensen <its@irrelevant.dk> wrote:
> 
> On Apr 19 07:20, Wertenbroek Rick wrote:
>> 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(-)
>> 
> 
> This all looks reasonable enought and straight-forward. But I can't seem
> to apply the patch for some reason. git is complaining about 'patch
> format detection failed.' and trying to apply manually with patch I'm
> getting a 'patch: **** malformed patch at line 55: }'.
> 
> Can you try to recreate the patch? Or if you can just put it in a git
> repo somewhere, then I can cherry-pick it from there.


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB
  2022-06-07 11:40   ` Wertenbroek Rick
@ 2022-06-07 12:01     ` Wertenbroek Rick
  0 siblings, 0 replies; 4+ messages in thread
From: Wertenbroek Rick @ 2022-06-07 12:01 UTC (permalink / raw)
  To: Klaus Jensen; +Cc: qemu-block, qemu-devel, Keith Busch

Hi,
So it seems the patch is messed up, I forked QEMU applied the patch to the current master.
Here it is : https://gitlab.com/rwe-reds/qemu/-/tree/master

I rebuilt QEMU to check that everything builds and runs.
Sorry for the inconvenience, I don’t know why the patch gets corrupted…

Best regards.
Rick

On 7 Jun 2022, at 13:40, Rick Wertenbroek <rick.wertenbroek@heig-vd.ch<mailto:rick.wertenbroek@heig-vd.ch>> wrote:

Hello,
Sorry about that, I had the same issue with the patch for some reason, I think it is the git send email that
messed up the patch (couldn’t directly send via smtp so I created a draft via IMAP before sending).
Anyway, below is the patch, it was created on the master branch (commit 81c7ed41a1b33031f3e4fe24191a998a492044b8).
I copy pasted the contents (plain text) of the .patch and could apply it.
Let me know if this doesn’t work and I’ll fork the QEMU git and make the patch available there.

From 79b622edbf3032751250822007ef11b2d7de31e2 Mon Sep 17 00:00:00 2001
Message-Id: <79b622edbf3032751250822007ef11b2d7de31e2.1648820166.git.rick.wertenbroek@heig-vd.ch<mailto:79b622edbf3032751250822007ef11b2d7de31e2.1648820166.git.rick.wertenbroek@heig-vd.ch>>
From: Rick Wertenbroek <rick.wertenbroek@heig-vd.ch<mailto:rick.wertenbroek@heig-vd.ch>>
Date: Fri, 1 Apr 2022 15:05:07 +0200
Subject: [PATCH] hw/nvme: allow to pass a memory backend object for the CMB

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<mailto: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)

On 3 Jun 2022, at 22:43, Klaus Jensen <its@irrelevant.dk<mailto:its@irrelevant.dk>> wrote:

On Apr 19 07:20, Wertenbroek Rick wrote:
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<mailto:rick.wertenbroek@heig-vd.ch>>
---
hw/nvme/ctrl.c | 65 ++++++++++++++++++++++++++++++++++++++------------
hw/nvme/nvme.h |  9 +++----
2 files changed, 55 insertions(+), 19 deletions(-)


This all looks reasonable enought and straight-forward. But I can't seem
to apply the patch for some reason. git is complaining about 'patch
format detection failed.' and trying to apply manually with patch I'm
getting a 'patch: **** malformed patch at line 55: }'.

Can you try to recreate the patch? Or if you can just put it in a git
repo somewhere, then I can cherry-pick it from there.



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-06-07 12:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-19  7:20 [PATCH v2] hw/nvme: allow to pass a memory backend object for the CMB Wertenbroek Rick
2022-06-03 20:43 ` Klaus Jensen
2022-06-07 11:40   ` Wertenbroek Rick
2022-06-07 12:01     ` Wertenbroek Rick

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.