All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches
@ 2020-12-18 13:28 Klaus Jensen
  2020-12-18 13:28 ` [PATCH 1/8] hw/block/nvme: indicate CMB support through controller capabilities register Klaus Jensen
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

This is a resend of "hw/block/nvme: allow cmb and pmr to coexist" with some
more PMR work added (PMR RDS/WDS support).

This includes a resurrection of Andrzej's series[1] from back July.

Andrzej's main patch basically moved the the CMB from BAR 2 into an
offset in BAR 4 (located after the MSI-X table and PBA). Having an
offset on the CMB causes a bunch of calculations related to address
mapping to change.

So, since I couldn't get the patch to apply cleanly I took a stab at
implementing the suggestion I originally came up with: simply move the
MSI-X table and PBA from BAR 4 into BAR 0 (up-aligned to a 4 KiB
boundary, after the main NVMe controller registers). This way we can
keep the CMB at offset zero in its own BAR and free up BAR 4 for use by
PMR. This makes the patch simpler and does not impact any of the
existing address mapping code.

Andrzej, I would prefer an Ack from you, since I pretty much voided your
main patch.

  [1]: https://lore.kernel.org/qemu-devel/20200729220107.37758-1-andrzej.jakowski@linux.intel.com/

CC: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>

Andrzej Jakowski (1):
  hw/block/nvme: indicate CMB support through controller capabilities
    register

Klaus Jensen (6):
  hw/block/nvme: move msix table and pba to BAR 0
  hw/block/nvme: allow cmb and pmr to coexist
  hw/block/nvme: fix controller reset/shutdown logic
  hw/block/nvme: rename CAP_PMR_{SHIFT,MASK} to CAP_PMRS_{SHIFT,MASK}
  hw/block/nvme: remove redundant zeroing of PMR registers
  hw/block/nvme: disable PMR at boot up

Naveen Nagar (1):
  hw/block/nvme: add PMR RDS/WDS support

 hw/block/nvme.h      |   2 +
 include/block/nvme.h |  15 ++-
 hw/block/nvme.c      | 216 ++++++++++++++++++++++++++++++-------------
 3 files changed, 164 insertions(+), 69 deletions(-)

-- 
2.29.2



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

* [PATCH 1/8] hw/block/nvme: indicate CMB support through controller capabilities register
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
@ 2020-12-18 13:28 ` Klaus Jensen
  2020-12-18 13:28 ` [PATCH 2/8] hw/block/nvme: move msix table and pba to BAR 0 Klaus Jensen
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Maxim Levitsky, Stefan Hajnoczi,
	Klaus Jensen

From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>

This patch sets CMBS bit in controller capabilities register when user
configures NVMe driver with CMB support, so capabilites are correctly
reported to guest OS.

Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
Reviewed-by: Maxim Levitsky <mlevitsky@gmail.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 include/block/nvme.h | 10 +++++++---
 hw/block/nvme.c      |  1 +
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/include/block/nvme.h b/include/block/nvme.h
index 11ac1c2b7dfb..24f3c256a7f9 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -36,6 +36,7 @@ enum NvmeCapShift {
     CAP_MPSMIN_SHIFT   = 48,
     CAP_MPSMAX_SHIFT   = 52,
     CAP_PMR_SHIFT      = 56,
+    CAP_CMB_SHIFT      = 57,
 };
 
 enum NvmeCapMask {
@@ -49,6 +50,7 @@ enum NvmeCapMask {
     CAP_MPSMIN_MASK    = 0xf,
     CAP_MPSMAX_MASK    = 0xf,
     CAP_PMR_MASK       = 0x1,
+    CAP_CMB_MASK       = 0x1,
 };
 
 #define NVME_CAP_MQES(cap)  (((cap) >> CAP_MQES_SHIFT)   & CAP_MQES_MASK)
@@ -78,9 +80,11 @@ enum NvmeCapMask {
 #define NVME_CAP_SET_MPSMIN(cap, val) (cap |= (uint64_t)(val & CAP_MPSMIN_MASK)\
                                                            << CAP_MPSMIN_SHIFT)
 #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
-                                                            << CAP_MPSMAX_SHIFT)
-#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
-                                                            << CAP_PMR_SHIFT)
+                                                           << CAP_MPSMAX_SHIFT)
+#define NVME_CAP_SET_PMRS(cap, val)   (cap |= (uint64_t)(val & CAP_PMR_MASK)   \
+                                                           << CAP_PMR_SHIFT)
+#define NVME_CAP_SET_CMBS(cap, val)   (cap |= (uint64_t)(val & CAP_CMB_MASK)   \
+                                                           << CAP_CMB_SHIFT)
 
 enum NvmeCapCss {
     NVME_CAP_CSS_NVM        = 1 << 0,
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 28416b18a5c0..fe809195a08a 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -3046,6 +3046,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
     NVME_CAP_SET_CSS(n->bar.cap, NVME_CAP_CSS_NVM);
     NVME_CAP_SET_CSS(n->bar.cap, NVME_CAP_CSS_ADMIN_ONLY);
     NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
+    NVME_CAP_SET_CMBS(n->bar.cap, n->params.cmb_size_mb ? 1 : 0);
 
     n->bar.vs = NVME_SPEC_VER;
     n->bar.intmc = n->bar.intms = 0;
-- 
2.29.2



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

* [PATCH 2/8] hw/block/nvme: move msix table and pba to BAR 0
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
  2020-12-18 13:28 ` [PATCH 1/8] hw/block/nvme: indicate CMB support through controller capabilities register Klaus Jensen
@ 2020-12-18 13:28 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 3/8] hw/block/nvme: allow cmb and pmr to coexist Klaus Jensen
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

In the interest of supporting both CMB and PMR to be enabled on the same
device, move the MSI-X table and pending bit out of BAR 4 and into BAR
0.

This is a simplified version of the patch contributed by Andrzej
Jakowski (see [1]). Leaving the CMB at offset 0 removes the need for
changes to CMB address mapping code.

  [1]: https://lore.kernel.org/qemu-devel/20200729220107.37758-3-andrzej.jakowski@linux.intel.com/

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.h |  1 +
 hw/block/nvme.c | 24 ++++++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 574333caa3f9..b1b273ce535e 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -118,6 +118,7 @@ typedef struct NvmeFeatureVal {
 
 typedef struct NvmeCtrl {
     PCIDevice    parent_obj;
+    MemoryRegion bar0;
     MemoryRegion iomem;
     MemoryRegion ctrl_mem;
     NvmeBar      bar;
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index fe809195a08a..8a7f682cb3ab 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2952,6 +2952,8 @@ static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
 static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
 {
     uint8_t *pci_conf = pci_dev->config;
+    uint64_t bar_size, msix_table_size, msix_pba_size;
+    unsigned msix_table_offset, msix_pba_offset;
 
     pci_conf[PCI_INTERRUPT_PIN] = 1;
     pci_config_set_prog_interface(pci_conf, 0x2);
@@ -2967,11 +2969,29 @@ static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
     pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_EXPRESS);
     pcie_endpoint_cap_init(pci_dev, 0x80);
 
+    bar_size = QEMU_ALIGN_UP(n->reg_size, 4 * KiB);
+    msix_table_offset = bar_size;
+    msix_table_size = PCI_MSIX_ENTRY_SIZE * n->params.msix_qsize;
+
+    bar_size += msix_table_size;
+    bar_size = QEMU_ALIGN_UP(bar_size, 4 * KiB);
+    msix_pba_offset = bar_size;
+    msix_pba_size = QEMU_ALIGN_UP(n->params.msix_qsize, 64) / 8;
+
+    bar_size += msix_pba_size;
+    bar_size = pow2ceil(bar_size);
+
+    memory_region_init(&n->bar0, OBJECT(n), "nvme-bar0", bar_size);
     memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme",
                           n->reg_size);
+    memory_region_add_subregion(&n->bar0, 0, &n->iomem);
+
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
-                     PCI_BASE_ADDRESS_MEM_TYPE_64, &n->iomem);
-    if (msix_init_exclusive_bar(pci_dev, n->params.msix_qsize, 4, errp)) {
+                     PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0);
+
+    if (msix_init(pci_dev, n->params.msix_qsize,
+                  &n->bar0, 0, msix_table_offset,
+                  &n->bar0, 0, msix_pba_offset, 0, errp)) {
         return;
     }
 
-- 
2.29.2



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

* [PATCH 3/8] hw/block/nvme: allow cmb and pmr to coexist
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
  2020-12-18 13:28 ` [PATCH 1/8] hw/block/nvme: indicate CMB support through controller capabilities register Klaus Jensen
  2020-12-18 13:28 ` [PATCH 2/8] hw/block/nvme: move msix table and pba to BAR 0 Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 4/8] hw/block/nvme: fix controller reset/shutdown logic Klaus Jensen
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

With BAR 4 now free to use, allow PMR and CMB to be enabled
simultaneously.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 8a7f682cb3ab..69f2fe4bd4ff 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -28,14 +28,13 @@
  * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
  * offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
  *
- * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
- * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
- * both provided.
  * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
  * For example:
  * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
  *  size=<size> .... -device nvme,...,pmrdev=<mem_id>
  *
+ * The PMR will use BAR 4/5 exclusively.
+ *
  *
  * nvme device parameters
  * ~~~~~~~~~~~~~~~~~~~~~~
@@ -76,7 +75,7 @@
 #define NVME_DB_SIZE  4
 #define NVME_SPEC_VER 0x00010300
 #define NVME_CMB_BIR 2
-#define NVME_PMR_BIR 2
+#define NVME_PMR_BIR 4
 #define NVME_TEMPERATURE 0x143
 #define NVME_TEMPERATURE_WARNING 0x157
 #define NVME_TEMPERATURE_CRITICAL 0x175
@@ -2812,7 +2811,7 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
         return;
     }
 
-    if (!n->params.cmb_size_mb && n->pmrdev) {
+    if (n->pmrdev) {
         if (host_memory_backend_is_mapped(n->pmrdev)) {
             error_setg(errp, "can't use already busy memdev: %s",
                        object_get_canonical_path_component(OBJECT(n->pmrdev)));
@@ -2902,9 +2901,6 @@ static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev)
 
 static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
 {
-    /* Controller Capabilities register */
-    NVME_CAP_SET_PMRS(n->bar.cap, 1);
-
     /* PMR Capabities register */
     n->bar.pmrcap = 0;
     NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
@@ -2997,7 +2993,9 @@ static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
 
     if (n->params.cmb_size_mb) {
         nvme_init_cmb(n, pci_dev);
-    } else if (n->pmrdev) {
+    }
+
+    if (n->pmrdev) {
         nvme_init_pmr(n, pci_dev);
     }
 }
@@ -3067,6 +3065,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
     NVME_CAP_SET_CSS(n->bar.cap, NVME_CAP_CSS_ADMIN_ONLY);
     NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
     NVME_CAP_SET_CMBS(n->bar.cap, n->params.cmb_size_mb ? 1 : 0);
+    NVME_CAP_SET_PMRS(n->bar.cap, n->pmrdev ? 1 : 0);
 
     n->bar.vs = NVME_SPEC_VER;
     n->bar.intmc = n->bar.intms = 0;
-- 
2.29.2



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

* [PATCH 4/8] hw/block/nvme: fix controller reset/shutdown logic
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
                   ` (2 preceding siblings ...)
  2020-12-18 13:29 ` [PATCH 3/8] hw/block/nvme: allow cmb and pmr to coexist Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 5/8] hw/block/nvme: rename CAP_PMR_{SHIFT, MASK} to CAP_PMRS_{SHIFT, MASK} Klaus Jensen
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

Differentiate between Controller Level Reset (i.e. CC.EN transitions
from 1 to 0) and Controller Shutdown (i.e. host sets CC.SHN to 01b or
10b). Prior to this patch the controller would perform the equivalent of
a Controller Level Reset when the host set CC.SHN to 01b or 10b. This
erroneously entails clearing CC.

For a Shutdown, it is the host that *should* delete any I/O queues.
Setting CC.EN to 0 is not part of the Shutdown procedure and it is
specifically recommended that the host does NOT do this. The host should
also stop issuing new I/O commands and allow any outstanding ones to
complete before setting CC.SHN. The only guarantee the controller must
give is that it is safe to power off the controller when CSTS.SHST
indicates that shutdown processing is complete. Do so by issuing flushes
for the attached namespaces and the PMR (if in use) and set CSTS.SHST to
10b. Specifically do not care about draining since the host *should* not
have left any outstanding commands around. If it did, behavior is
undefined.

On the other hand, a Controller Level Reset is not about being safe for
shutdown - so only drain here, do not explicitly flush.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.c | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 69f2fe4bd4ff..96c9f9be3dc4 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2262,7 +2262,26 @@ static void nvme_process_sq(void *opaque)
     }
 }
 
-static void nvme_clear_ctrl(NvmeCtrl *n)
+static void nvme_ctrl_shutdown(NvmeCtrl *n)
+{
+    NvmeNamespace *ns;
+    int i;
+
+    if (n->pmrdev) {
+        memory_region_msync(&n->pmrdev->mr, 0, n->pmrdev->size);
+    }
+
+    for (i = 1; i <= n->num_namespaces; i++) {
+        ns = nvme_ns(n, i);
+        if (!ns) {
+            continue;
+        }
+
+        nvme_ns_flush(ns);
+    }
+}
+
+static void nvme_ctrl_reset(NvmeCtrl *n)
 {
     NvmeNamespace *ns;
     int i;
@@ -2297,15 +2316,6 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
     n->outstanding_aers = 0;
     n->qs_created = false;
 
-    for (i = 1; i <= n->num_namespaces; i++) {
-        ns = nvme_ns(n, i);
-        if (!ns) {
-            continue;
-        }
-
-        nvme_ns_flush(ns);
-    }
-
     n->bar.cc = 0;
 }
 
@@ -2473,12 +2483,12 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
             }
         } else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) {
             trace_pci_nvme_mmio_stopped();
-            nvme_clear_ctrl(n);
+            nvme_ctrl_reset(n);
             n->bar.csts &= ~NVME_CSTS_READY;
         }
         if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) {
             trace_pci_nvme_mmio_shutdown_set();
-            nvme_clear_ctrl(n);
+            nvme_ctrl_shutdown(n);
             n->bar.cc = data;
             n->bar.csts |= NVME_CSTS_SHST_COMPLETE;
         } else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) {
@@ -3110,7 +3120,8 @@ static void nvme_exit(PCIDevice *pci_dev)
 {
     NvmeCtrl *n = NVME(pci_dev);
 
-    nvme_clear_ctrl(n);
+    nvme_ctrl_reset(n);
+
     g_free(n->cq);
     g_free(n->sq);
     g_free(n->aer_reqs);
-- 
2.29.2



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

* [PATCH 5/8] hw/block/nvme: rename CAP_PMR_{SHIFT, MASK} to CAP_PMRS_{SHIFT, MASK}
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
                   ` (3 preceding siblings ...)
  2020-12-18 13:29 ` [PATCH 4/8] hw/block/nvme: fix controller reset/shutdown logic Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 6/8] hw/block/nvme: remove redundant zeroing of PMR registers Klaus Jensen
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

Use the correct field name.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 include/block/nvme.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/block/nvme.h b/include/block/nvme.h
index 24f3c256a7f9..686e2541a587 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -35,7 +35,7 @@ enum NvmeCapShift {
     CAP_CSS_SHIFT      = 37,
     CAP_MPSMIN_SHIFT   = 48,
     CAP_MPSMAX_SHIFT   = 52,
-    CAP_PMR_SHIFT      = 56,
+    CAP_PMRS_SHIFT     = 56,
     CAP_CMB_SHIFT      = 57,
 };
 
@@ -49,7 +49,7 @@ enum NvmeCapMask {
     CAP_CSS_MASK       = 0xff,
     CAP_MPSMIN_MASK    = 0xf,
     CAP_MPSMAX_MASK    = 0xf,
-    CAP_PMR_MASK       = 0x1,
+    CAP_PMRS_MASK      = 0x1,
     CAP_CMB_MASK       = 0x1,
 };
 
@@ -81,8 +81,8 @@ enum NvmeCapMask {
                                                            << CAP_MPSMIN_SHIFT)
 #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
                                                            << CAP_MPSMAX_SHIFT)
-#define NVME_CAP_SET_PMRS(cap, val)   (cap |= (uint64_t)(val & CAP_PMR_MASK)   \
-                                                           << CAP_PMR_SHIFT)
+#define NVME_CAP_SET_PMRS(cap, val)   (cap |= (uint64_t)(val & CAP_PMRS_MASK)  \
+                                                           << CAP_PMRS_SHIFT)
 #define NVME_CAP_SET_CMBS(cap, val)   (cap |= (uint64_t)(val & CAP_CMB_MASK)   \
                                                            << CAP_CMB_SHIFT)
 
-- 
2.29.2



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

* [PATCH 6/8] hw/block/nvme: remove redundant zeroing of PMR registers
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
                   ` (4 preceding siblings ...)
  2020-12-18 13:29 ` [PATCH 5/8] hw/block/nvme: rename CAP_PMR_{SHIFT, MASK} to CAP_PMRS_{SHIFT, MASK} Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 7/8] hw/block/nvme: disable PMR at boot up Klaus Jensen
  2020-12-18 13:29 ` [PATCH 8/8] hw/block/nvme: add PMR RDS/WDS support Klaus Jensen
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

The controller registers are initially zero. Remove the redundant
zeroing.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.c | 35 -----------------------------------
 1 file changed, 35 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 96c9f9be3dc4..58e86bba0316 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2911,43 +2911,8 @@ static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev)
 
 static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
 {
-    /* PMR Capabities register */
-    n->bar.pmrcap = 0;
-    NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
-    NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
     NVME_PMRCAP_SET_BIR(n->bar.pmrcap, NVME_PMR_BIR);
-    NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
-    /* Turn on bit 1 support */
     NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
-    NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
-    NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
-
-    /* PMR Control register */
-    n->bar.pmrctl = 0;
-    NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
-
-    /* PMR Status register */
-    n->bar.pmrsts = 0;
-    NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
-    NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
-    NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
-    NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
-
-    /* PMR Elasticity Buffer Size register */
-    n->bar.pmrebs = 0;
-    NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
-    NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
-    NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
-
-    /* PMR Sustained Write Throughput register */
-    n->bar.pmrswtp = 0;
-    NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
-    NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
-
-    /* PMR Memory Space Control register */
-    n->bar.pmrmsc = 0;
-    NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
-    NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
 
     pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
                      PCI_BASE_ADDRESS_SPACE_MEMORY |
-- 
2.29.2



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

* [PATCH 7/8] hw/block/nvme: disable PMR at boot up
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
                   ` (5 preceding siblings ...)
  2020-12-18 13:29 ` [PATCH 6/8] hw/block/nvme: remove redundant zeroing of PMR registers Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  2020-12-18 13:29 ` [PATCH 8/8] hw/block/nvme: add PMR RDS/WDS support Klaus Jensen
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Max Reitz,
	Keith Busch, Andrzej Jakowski, Stefan Hajnoczi, Klaus Jensen

From: Klaus Jensen <k.jensen@samsung.com>

The PMR should not be enabled at boot up. Disable the PMR MemoryRegion
initially and implement MMIO for PMRCTL, allowing the host to enable the
PMR explicitly.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 58e86bba0316..c04d6e69e4df 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2549,8 +2549,16 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
         NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrcap_readonly,
                        "invalid write to PMRCAP register, ignored");
         return;
-    case 0xE04: /* TODO PMRCTL */
-        break;
+    case 0xE04: /* PMRCTL */
+        n->bar.pmrctl = data;
+        if (NVME_PMRCTL_EN(data)) {
+            memory_region_set_enabled(&n->pmrdev->mr, true);
+            n->bar.pmrsts = 0;
+        } else {
+            memory_region_set_enabled(&n->pmrdev->mr, false);
+            NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 1);
+        }
+        return;
     case 0xE08: /* PMRSTS */
         NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrsts_readonly,
                        "invalid write to PMRSTS register, ignored");
@@ -2918,6 +2926,8 @@ static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
                      PCI_BASE_ADDRESS_SPACE_MEMORY |
                      PCI_BASE_ADDRESS_MEM_TYPE_64 |
                      PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
+
+    memory_region_set_enabled(&n->pmrdev->mr, false);
 }
 
 static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
-- 
2.29.2



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

* [PATCH 8/8] hw/block/nvme: add PMR RDS/WDS support
  2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
                   ` (6 preceding siblings ...)
  2020-12-18 13:29 ` [PATCH 7/8] hw/block/nvme: disable PMR at boot up Klaus Jensen
@ 2020-12-18 13:29 ` Klaus Jensen
  7 siblings, 0 replies; 9+ messages in thread
From: Klaus Jensen @ 2020-12-18 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Kevin Wolf, qemu-block, Klaus Jensen, Naveen Nagar,
	Max Reitz, Keith Busch, Andrzej Jakowski, Stefan Hajnoczi,
	Klaus Jensen

From: Naveen Nagar <naveen.n1@samsung.com>

Add support for the PMRMSCL and PMRMSCU MMIO registers. This allows
adding RDS/WDS support for PMR as well.

Signed-off-by: Naveen Nagar <naveen.n1@samsung.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/block/nvme.h      |  1 +
 include/block/nvme.h |  1 +
 hw/block/nvme.c      | 88 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index b1b273ce535e..0dc119dedc00 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -142,6 +142,7 @@ typedef struct NvmeCtrl {
     uint64_t    timestamp_set_qemu_clock_ms;    /* QEMU clock time */
     uint64_t    starttime_ms;
     uint16_t    temperature;
+    bool        pmr_cmse;
 
     HostMemoryBackend *pmrdev;
 
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 686e2541a587..ed645b6cb4f2 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -62,6 +62,7 @@ enum NvmeCapMask {
 #define NVME_CAP_CSS(cap)   (((cap) >> CAP_CSS_SHIFT)    & CAP_CSS_MASK)
 #define NVME_CAP_MPSMIN(cap)(((cap) >> CAP_MPSMIN_SHIFT) & CAP_MPSMIN_MASK)
 #define NVME_CAP_MPSMAX(cap)(((cap) >> CAP_MPSMAX_SHIFT) & CAP_MPSMAX_MASK)
+#define NVME_CAP_PMRS(cap)  (((cap) >> CAP_PMRS_SHIFT)   & CAP_PMRS_MASK)
 
 #define NVME_CAP_SET_MQES(cap, val)   (cap |= (uint64_t)(val & CAP_MQES_MASK)  \
                                                            << CAP_MQES_SHIFT)
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index c04d6e69e4df..055b9c69bafb 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -142,6 +142,31 @@ static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr)
     return &n->cmbuf[addr - n->ctrl_mem.addr];
 }
 
+static inline bool nvme_addr_is_pmr(NvmeCtrl *n, hwaddr addr)
+{
+    hwaddr hi, low;
+
+    if (!n->pmrdev || !n->pmrdev->mr.enabled) {
+        return false;
+    }
+
+    low = NVME_PMRMSC_CBA(n->bar.pmrmsc) << PMRMSC_CBA_SHIFT;
+    hi  = low + int128_get64(n->pmrdev->mr.size);
+
+    return addr >= low && addr < hi;
+}
+
+static inline void *nvme_addr_to_pmr(NvmeCtrl *n, hwaddr addr)
+{
+    hwaddr cba;
+
+    assert(nvme_addr_is_pmr(n, addr));
+
+    cba = NVME_PMRMSC_CBA(n->bar.pmrmsc) << PMRMSC_CBA_SHIFT;
+
+    return memory_region_get_ram_ptr(&n->pmrdev->mr) + (addr - cba);
+}
+
 static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
 {
     hwaddr hi = addr + size - 1;
@@ -154,6 +179,11 @@ static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
         return 0;
     }
 
+    if (nvme_addr_is_pmr(n, addr) && nvme_addr_is_pmr(n, hi)) {
+        memcpy(buf, nvme_addr_to_pmr(n, addr), size);
+        return 0;
+    }
+
     return pci_dma_read(&n->parent_obj, addr, buf, size);
 }
 
@@ -275,6 +305,22 @@ static uint16_t nvme_map_addr_cmb(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr,
     return NVME_SUCCESS;
 }
 
+static uint16_t nvme_map_addr_pmr(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr,
+    size_t len)
+{
+    if (!len) {
+        return NVME_SUCCESS;
+    }
+
+    if (!nvme_addr_is_pmr(n, addr) || !nvme_addr_is_pmr(n, addr + len - 1)) {
+        return NVME_DATA_TRAS_ERROR;
+    }
+
+    qemu_iovec_add(iov, nvme_addr_to_pmr(n, addr), len);
+
+    return NVME_SUCCESS;
+}
+
 static uint16_t nvme_map_addr(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov,
                               hwaddr addr, size_t len)
 {
@@ -297,6 +343,19 @@ static uint16_t nvme_map_addr(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov,
 
         return nvme_map_addr_cmb(n, iov, addr, len);
     }
+    if (nvme_addr_is_pmr(n, addr)) {
+        if (qsg && qsg->sg) {
+            return NVME_INVALID_FIELD | NVME_DNR;
+        }
+
+        assert(iov);
+
+        if (!iov->iov) {
+            qemu_iovec_init(iov, 1);
+        }
+
+        return nvme_map_addr_pmr(n, iov, addr, len);
+    }
 
     if (iov && iov->iov) {
         return NVME_INVALID_USE_OF_CMB | NVME_DNR;
@@ -328,7 +387,7 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2,
 
     trace_pci_nvme_map_prp(trans_len, len, prp1, prp2, num_prps);
 
-    if (nvme_addr_is_cmb(n, prp1)) {
+    if (nvme_addr_is_cmb(n, prp1) || (nvme_addr_is_pmr(n, prp1))) {
         qemu_iovec_init(iov, num_prps);
     } else {
         pci_dma_sglist_init(qsg, &n->parent_obj, num_prps);
@@ -2571,8 +2630,28 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
         NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrswtp_readonly,
                        "invalid write to PMRSWTP register, ignored");
         return;
-    case 0xE14: /* TODO PMRMSC */
-        break;
+    case 0xE14: /* PMRMSCL */
+        if (!NVME_CAP_PMRS(n->bar.cap)) {
+            return;
+        }
+
+        n->bar.pmrmsc |= data & 0xffffffff;
+
+        if (NVME_PMRMSC_CMSE(n->bar.pmrmsc)) {
+            hwaddr cba = NVME_PMRMSC_CBA(n->bar.pmrmsc) << PMRMSC_CBA_SHIFT;
+            if (cba + int128_get64(n->pmrdev->mr.size) < cba) {
+                NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 1);
+            }
+        }
+
+        return;
+    case 0xE18: /* PMRMSCU */
+        if (!NVME_CAP_PMRS(n->bar.cap)) {
+            return;
+        }
+
+        n->bar.pmrmsc |= data << 32;
+        return;
     default:
         NVME_GUEST_ERR(pci_nvme_ub_mmiowr_invalid,
                        "invalid MMIO write,"
@@ -2919,8 +2998,11 @@ static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev)
 
 static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
 {
+    NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 1);
+    NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 1);
     NVME_PMRCAP_SET_BIR(n->bar.pmrcap, NVME_PMR_BIR);
     NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
+    NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 1);
 
     pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
                      PCI_BASE_ADDRESS_SPACE_MEMORY |
-- 
2.29.2



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

end of thread, other threads:[~2020-12-18 13:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-18 13:28 [PATCH 0/8] hw/block/nvme: misc cmb/pmr patches Klaus Jensen
2020-12-18 13:28 ` [PATCH 1/8] hw/block/nvme: indicate CMB support through controller capabilities register Klaus Jensen
2020-12-18 13:28 ` [PATCH 2/8] hw/block/nvme: move msix table and pba to BAR 0 Klaus Jensen
2020-12-18 13:29 ` [PATCH 3/8] hw/block/nvme: allow cmb and pmr to coexist Klaus Jensen
2020-12-18 13:29 ` [PATCH 4/8] hw/block/nvme: fix controller reset/shutdown logic Klaus Jensen
2020-12-18 13:29 ` [PATCH 5/8] hw/block/nvme: rename CAP_PMR_{SHIFT, MASK} to CAP_PMRS_{SHIFT, MASK} Klaus Jensen
2020-12-18 13:29 ` [PATCH 6/8] hw/block/nvme: remove redundant zeroing of PMR registers Klaus Jensen
2020-12-18 13:29 ` [PATCH 7/8] hw/block/nvme: disable PMR at boot up Klaus Jensen
2020-12-18 13:29 ` [PATCH 8/8] hw/block/nvme: add PMR RDS/WDS support Klaus Jensen

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.