[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC XEN PATCH v4 07/41] xen/pmem: register valid PMEM regions to Xen hypervisor



Register valid PMEM regions probed via NFIT to Xen hypervisor. No
frametable and M2P table are created for those PMEM regions at this
stage.

Signed-off-by: Haozhong Zhang <haozhong.zhang@xxxxxxxxx>
---
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: George Dunlap <George.Dunlap@xxxxxxxxxxxxx>
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Cc: Tim Deegan <tim@xxxxxxx>
Cc: Wei Liu <wei.liu2@xxxxxxxxxx>

Changes in v4:
  * Simplify return paths of pmem_list_add().
---
 xen/common/Makefile     |   1 +
 xen/common/pmem.c       | 122 ++++++++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/acpi/nfit.c |  12 ++++-
 xen/include/xen/pmem.h  |  28 +++++++++++
 4 files changed, 162 insertions(+), 1 deletion(-)
 create mode 100644 xen/common/pmem.c
 create mode 100644 xen/include/xen/pmem.h

diff --git a/xen/common/Makefile b/xen/common/Makefile
index 66cc2c8995..57fa4601b8 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -29,6 +29,7 @@ obj-y += notifier.o
 obj-y += page_alloc.o
 obj-$(CONFIG_HAS_PDX) += pdx.o
 obj-$(CONFIG_PERF_COUNTERS) += perfc.o
+obj-${CONFIG_NVDIMM_PMEM} += pmem.o
 obj-y += preempt.o
 obj-y += random.o
 obj-y += rangeset.o
diff --git a/xen/common/pmem.c b/xen/common/pmem.c
new file mode 100644
index 0000000000..aa0a1d166d
--- /dev/null
+++ b/xen/common/pmem.c
@@ -0,0 +1,122 @@
+/*
+ * xen/common/pmem.c
+ *
+ * Copyright (C) 2017, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/errno.h>
+#include <xen/list.h>
+#include <xen/pmem.h>
+
+/*
+ * All PMEM regions presenting in NFIT SPA range structures are linked
+ * in this list.
+ */
+static LIST_HEAD(pmem_raw_regions);
+static unsigned int nr_raw_regions;
+
+struct pmem {
+    struct list_head link; /* link to one of PMEM region list */
+    unsigned long smfn;    /* start MFN of the PMEM region */
+    unsigned long emfn;    /* end MFN of the PMEM region */
+
+    union {
+        struct {
+            unsigned int pxm; /* proximity domain of the PMEM region */
+        } raw;
+    } u;
+};
+
+static bool check_overlap(unsigned long smfn1, unsigned long emfn1,
+                          unsigned long smfn2, unsigned long emfn2)
+{
+    return (smfn1 >= smfn2 && smfn1 < emfn2) ||
+           (emfn1 > smfn2 && emfn1 <= emfn2);
+}
+
+/**
+ * Add a PMEM region to a list. All PMEM regions in the list are
+ * sorted in the ascending order of the start address. A PMEM region,
+ * whose range is overlapped with anyone in the list, cannot be added
+ * to the list.
+ *
+ * Parameters:
+ *  list:       the list to which a new PMEM region will be added
+ *  smfn, emfn: the range of the new PMEM region
+ *  entry:      return the new entry added to the list
+ *
+ * Return:
+ *  On success, return 0 and the new entry added to the list is
+ *  returned via @entry. Otherwise, return an error number and the
+ *  value of @entry is undefined.
+ */
+static int pmem_list_add(struct list_head *list,
+                         unsigned long smfn, unsigned long emfn,
+                         struct pmem **entry)
+{
+    struct list_head *cur;
+    struct pmem *new_pmem;
+
+    list_for_each_prev(cur, list)
+    {
+        struct pmem *cur_pmem = list_entry(cur, struct pmem, link);
+        unsigned long cur_smfn = cur_pmem->smfn;
+        unsigned long cur_emfn = cur_pmem->emfn;
+
+        if ( check_overlap(smfn, emfn, cur_smfn, cur_emfn) )
+            return -EEXIST;
+
+        if ( cur_smfn < smfn )
+            break;
+    }
+
+    new_pmem = xzalloc(struct pmem);
+    if ( !new_pmem )
+        return -ENOMEM;
+
+    new_pmem->smfn = smfn;
+    new_pmem->emfn = emfn;
+    list_add(&new_pmem->link, cur);
+    if ( entry )
+        *entry = new_pmem;
+
+    return 0;
+}
+
+/**
+ * Register a pmem region to Xen.
+ *
+ * Parameters:
+ *  smfn, emfn: start and end MFNs of the pmem region
+ *  pxm:        the proximity domain of the pmem region
+ *
+ * Return:
+ *  On success, return 0. Otherwise, an error number is returned.
+ */
+int pmem_register(unsigned long smfn, unsigned long emfn, unsigned int pxm)
+{
+    int rc;
+    struct pmem *pmem;
+
+    if ( smfn >= emfn )
+        return -EINVAL;
+
+    rc = pmem_list_add(&pmem_raw_regions, smfn, emfn, &pmem);
+    if ( !rc )
+        pmem->u.raw.pxm = pxm;
+    nr_raw_regions++;
+
+    return rc;
+}
diff --git a/xen/drivers/acpi/nfit.c b/xen/drivers/acpi/nfit.c
index 0a44983aad..6f85d4d911 100644
--- a/xen/drivers/acpi/nfit.c
+++ b/xen/drivers/acpi/nfit.c
@@ -20,6 +20,7 @@
 #include <xen/init.h>
 #include <xen/mm.h>
 #include <xen/pfn.h>
+#include <xen/pmem.h>
 
 /*
  * GUID of a byte addressable persistent memory region
@@ -153,6 +154,7 @@ static void __init acpi_nfit_register_pmem(struct 
acpi_nfit_desc *desc)
     struct acpi_nfit_system_address *spa;
     unsigned long smfn, emfn;
     bool failed;
+    int rc;
 
     list_for_each_entry(spa_desc, &desc->spa_list, link)
     {
@@ -188,7 +190,15 @@ static void __init acpi_nfit_register_pmem(struct 
acpi_nfit_desc *desc)
             continue;
         }
 
-        printk(XENLOG_INFO "NFIT: PMEM MFNs 0x%lx - 0x%lx\n", smfn, emfn);
+        rc = pmem_register(smfn, emfn, spa->proximity_domain);
+        if ( !rc )
+            printk(XENLOG_INFO
+                   "NFIT: PMEM MFNs 0x%lx - 0x%lx on PXM %u registered\n",
+                   smfn, emfn, spa->proximity_domain);
+        else
+            printk(XENLOG_ERR
+                   "NFIT: failed to register PMEM MFNs 0x%lx - 0x%lx on PXM 
%u, err %d\n",
+                   smfn, emfn, spa->proximity_domain, rc);
     }
 }
 
diff --git a/xen/include/xen/pmem.h b/xen/include/xen/pmem.h
new file mode 100644
index 0000000000..41cb9bb04f
--- /dev/null
+++ b/xen/include/xen/pmem.h
@@ -0,0 +1,28 @@
+/*
+ * xen/include/xen/pmem.h
+ *
+ * Copyright (C) 2017, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XEN_PMEM_H__
+#define __XEN_PMEM_H__
+#ifdef CONFIG_NVDIMM_PMEM
+
+#include <xen/types.h>
+
+int pmem_register(unsigned long smfn, unsigned long emfn, unsigned int pxm);
+
+#endif /* CONFIG_NVDIMM_PMEM */
+#endif /* __XEN_PMEM_H__ */
-- 
2.15.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.