From: Haozhong Zhang <haozhong.zhang@intel.com>
To: xen-devel@lists.xen.org
Cc: Konrad Rzeszutek Wilk <konrad@darnok.org>,
Dan Williams <dan.j.williams@intel.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
Jan Beulich <jbeulich@suse.com>,
Haozhong Zhang <haozhong.zhang@intel.com>
Subject: [RFC XEN PATCH v2 02/15] xen: probe pmem regions via ACPI NFIT
Date: Mon, 20 Mar 2017 08:09:36 +0800 [thread overview]
Message-ID: <20170320000949.24675-3-haozhong.zhang@intel.com> (raw)
In-Reply-To: <20170320000949.24675-1-haozhong.zhang@intel.com>
Probe the address ranges of pmem regions via ACPI NFIT and report them
to Xen hypervisor.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/acpi/boot.c | 4 ++
xen/common/Makefile | 1 +
xen/common/pmem.c | 106 ++++++++++++++++++++++++++++++++++++++++++
xen/drivers/acpi/Makefile | 2 +
xen/drivers/acpi/nfit.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++
xen/include/acpi/actbl.h | 1 +
xen/include/acpi/actbl1.h | 42 +++++++++++++++++
xen/include/xen/acpi.h | 4 ++
xen/include/xen/pmem.h | 28 +++++++++++
9 files changed, 304 insertions(+)
create mode 100644 xen/common/pmem.c
create mode 100644 xen/drivers/acpi/nfit.c
create mode 100644 xen/include/xen/pmem.h
diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c
index 33c9133812..83d73868d6 100644
--- a/xen/arch/x86/acpi/boot.c
+++ b/xen/arch/x86/acpi/boot.c
@@ -754,5 +754,9 @@ int __init acpi_boot_init(void)
acpi_table_parse(ACPI_SIG_BGRT, acpi_invalidate_bgrt);
+#ifdef CONFIG_PMEM
+ acpi_nfit_init();
+#endif
+
return 0;
}
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 0fed30bcc6..16c273b6d4 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_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..3c150cf1dd
--- /dev/null
+++ b/xen/common/pmem.c
@@ -0,0 +1,106 @@
+/*
+ * 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>
+#include <xen/spinlock.h>
+
+/*
+ * All pmem regions probed via SPA range structures of ACPI NFIT are
+ * linked in pmem_regions.
+ */
+static DEFINE_SPINLOCK(pmem_regions_lock);
+static LIST_HEAD(pmem_regions);
+
+struct pmem {
+ struct list_head link; /* link to pmem_list */
+ unsigned long smfn; /* start MFN of the whole pmem region */
+ unsigned long emfn; /* end MFN of the whole pmem region */
+};
+
+static bool check_overlap(unsigned long smfn1, unsigned long emfn1,
+ unsigned long smfn2, unsigned long emfn2)
+{
+ return smfn1 < emfn2 && smfn2 < emfn1;
+}
+
+static struct pmem *alloc_pmem_struct(unsigned long smfn, unsigned long emfn)
+{
+ struct pmem *pmem = xzalloc(struct pmem);
+
+ if ( !pmem )
+ return NULL;
+
+ pmem->smfn = smfn;
+ pmem->emfn = emfn;
+
+ return pmem;
+}
+
+static int pmem_list_add(struct list_head *list, struct pmem *entry)
+{
+ struct list_head *cur;
+ unsigned long smfn = entry->smfn, emfn = entry->emfn;
+
+ 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 -EINVAL;
+
+ if ( cur_smfn < smfn )
+ break;
+ }
+
+ list_add(&entry->link, cur);
+
+ return 0;
+}
+
+/**
+ * Register a pmem region to Xen. It's used by Xen hypervisor to collect
+ * all pmem regions can be used later.
+ *
+ * Parameters:
+ * smfn, emfn: start and end MFNs of the pmem region
+ *
+ * Return:
+ * On success, return 0. Otherwise, an error number is returned.
+ */
+int pmem_register(unsigned long smfn, unsigned long emfn)
+{
+ int rc;
+ struct pmem *pmem;
+
+ if ( smfn >= emfn )
+ return -EINVAL;
+
+ pmem = alloc_pmem_struct(smfn, emfn);
+ if ( !pmem )
+ return -ENOMEM;
+
+ spin_lock(&pmem_regions_lock);
+ rc = pmem_list_add(&pmem_regions, pmem);
+ spin_unlock(&pmem_regions_lock);
+
+ return rc;
+}
diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile
index 444b11d583..cef9d90222 100644
--- a/xen/drivers/acpi/Makefile
+++ b/xen/drivers/acpi/Makefile
@@ -9,3 +9,5 @@ obj-$(CONFIG_HAS_CPUFREQ) += pmstat.o
obj-$(CONFIG_X86) += hwregs.o
obj-$(CONFIG_X86) += reboot.o
+
+obj-$(CONFIG_PMEM) += nfit.o
diff --git a/xen/drivers/acpi/nfit.c b/xen/drivers/acpi/nfit.c
new file mode 100644
index 0000000000..ceac121dd2
--- /dev/null
+++ b/xen/drivers/acpi/nfit.c
@@ -0,0 +1,116 @@
+/*
+ * xen/drivers/acpi/nfit.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/acpi.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/pmem.h>
+
+static struct acpi_table_nfit *nfit __read_mostly = NULL;
+
+/* ACPI 6.1: GUID of a byte addressable persistent memory region */
+static const uint8_t nfit_spa_pmem_uuid[] =
+{
+ 0x79, 0xd3, 0xf0, 0x66, 0xf3, 0xb4, 0x74, 0x40,
+ 0xac, 0x43, 0x0d, 0x33, 0x18, 0xb7, 0x8c, 0xdb,
+};
+
+/**
+ * Enumerate each sub-table of NFIT.
+ *
+ * For a sub-table of type @type, @parse_cb() (if not NULL) is called
+ * to parse the sub-table. @parse_cb() returns 0 on success, and
+ * returns non-zero error code on errors.
+ *
+ * Parameters:
+ * nfit: NFIT
+ * type: the type of sub-table that will be parsed
+ * parse_cb: the function used to parse each sub-table
+ * arg: the argument passed to @parse_cb()
+ *
+ * Return:
+ * 0 on success, non-zero on failure
+ */
+static int acpi_nfit_foreach_subtable(
+ struct acpi_table_nfit *nfit, enum acpi_nfit_type type,
+ int (*parse_cb)(const struct acpi_nfit_header *, void *arg), void *arg)
+{
+ struct acpi_table_header *table = (struct acpi_table_header *)nfit;
+ struct acpi_nfit_header *hdr;
+ uint32_t hdr_offset = sizeof(*nfit);
+ int ret = 0;
+
+ while ( hdr_offset < table->length )
+ {
+ hdr = (void *)nfit + hdr_offset;
+ hdr_offset += hdr->length;
+ if ( hdr->type == type && parse_cb )
+ {
+ ret = parse_cb(hdr, arg);
+ if ( ret )
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int __init acpi_nfit_spa_probe_pmem(const struct acpi_nfit_header *hdr,
+ void *opaque)
+{
+ struct acpi_nfit_system_address *spa =
+ (struct acpi_nfit_system_address *)hdr;
+ unsigned long smfn = paddr_to_pfn(spa->address);
+ unsigned long emfn = paddr_to_pfn(spa->address + spa->length);
+ int rc;
+
+ if ( memcmp(spa->range_guid, nfit_spa_pmem_uuid, 16) )
+ return 0;
+
+ rc = pmem_register(smfn, emfn);
+ if ( rc )
+ printk(XENLOG_ERR
+ "NFIT: failed to add pmem mfns: 0x%lx - 0x%lx, err %d\n",
+ smfn, emfn, rc);
+ else
+ printk(XENLOG_INFO "NFIT: pmem mfn 0x%lx - 0x%lx\n", smfn, emfn);
+
+ /* ignore the error and continue to add the next pmem range */
+ return 0;
+}
+
+void __init acpi_nfit_init(void)
+{
+ acpi_status status;
+ acpi_physical_address nfit_addr;
+ acpi_native_uint nfit_len;
+
+ status = acpi_get_table_phys(ACPI_SIG_NFIT, 0, &nfit_addr, &nfit_len);
+ if ( ACPI_FAILURE(status) )
+ return;
+
+ map_pages_to_xen((unsigned long)__va(nfit_addr), PFN_DOWN(nfit_addr),
+ PFN_UP(nfit_addr + nfit_len) - PFN_DOWN(nfit_addr),
+ PAGE_HYPERVISOR);
+ nfit = (struct acpi_table_nfit *)__va(nfit_addr);
+
+ acpi_nfit_foreach_subtable(nfit, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
+ acpi_nfit_spa_probe_pmem, NULL);
+}
diff --git a/xen/include/acpi/actbl.h b/xen/include/acpi/actbl.h
index 3079176992..6e113b0873 100644
--- a/xen/include/acpi/actbl.h
+++ b/xen/include/acpi/actbl.h
@@ -71,6 +71,7 @@
#define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */
#define ACPI_SIG_SSDT "SSDT" /* Secondary System Description Table */
#define ACPI_RSDP_NAME "RSDP" /* Short name for RSDP, not signature */
+#define ACPI_SIG_NFIT "NFIT" /* NVDIMM Firmware Interface Table */
/*
* All tables and structures must be byte-packed to match the ACPI
diff --git a/xen/include/acpi/actbl1.h b/xen/include/acpi/actbl1.h
index e1991362dc..a59ac11325 100644
--- a/xen/include/acpi/actbl1.h
+++ b/xen/include/acpi/actbl1.h
@@ -905,6 +905,48 @@ struct acpi_msct_proximity {
/*******************************************************************************
*
+ * NFIT - NVDIMM Interface Table (ACPI 6.0+)
+ * Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_nfit {
+ struct acpi_table_header header; /* Common ACPI table header */
+ u32 reserved; /* Reserved, must be zero */
+};
+
+/* Subtable header for NFIT */
+
+struct acpi_nfit_header {
+ u16 type;
+ u16 length;
+};
+
+/* Values for subtable type in struct acpi_nfit_header */
+
+enum acpi_nfit_type {
+ ACPI_NFIT_TYPE_SYSTEM_ADDRESS = 0,
+};
+
+/*
+ * NFIT Subtables
+ */
+
+/* type 0: System Physical Address Range Structure */
+struct acpi_nfit_system_address {
+ struct acpi_nfit_header header;
+ u16 range_index;
+ u16 flags;
+ u32 reserved; /* Reseved, must be zero */
+ u32 proximity_domain;
+ u8 range_guid[16];
+ u64 address;
+ u64 length;
+ u64 memory_mapping;
+};
+
+/*******************************************************************************
+ *
* SBST - Smart Battery Specification Table
* Version 1
*
diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h
index 30ec0eec5f..8edb9a275e 100644
--- a/xen/include/xen/acpi.h
+++ b/xen/include/xen/acpi.h
@@ -180,4 +180,8 @@ void acpi_reboot(void);
void acpi_dmar_zap(void);
void acpi_dmar_reinstate(void);
+#ifdef CONFIG_PMEM
+void acpi_nfit_init(void);
+#endif /* CONFIG_PMEM */
+
#endif /*_LINUX_ACPI_H*/
diff --git a/xen/include/xen/pmem.h b/xen/include/xen/pmem.h
new file mode 100644
index 0000000000..1144e86f98
--- /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_PMEM
+
+#include <xen/types.h>
+
+int pmem_register(unsigned long smfn, unsigned long emfn);
+
+#endif /* CONFIG_PMEM */
+#endif /* __XEN_PMEM_H__ */
--
2.12.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2017-03-20 0:09 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-20 0:09 [RFC XEN PATCH v2 00/15] Add vNVDIMM support to HVM domains Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 01/15] xen/common: add Kconfig item for pmem support Haozhong Zhang
2017-03-20 0:09 ` Haozhong Zhang [this message]
2017-03-20 0:09 ` [RFC XEN PATCH v2 03/15] xen/x86: allow customizing locations of extended frametable & M2P Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 04/15] xen/x86: add XEN_SYSCTL_nvdimm_pmem_setup to setup host pmem Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 05/15] xen/x86: add XENMEM_populate_pmem_map to map host pmem pages to HVM domain Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 06/15] tools: reserve guest memory for ACPI from device model Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 07/15] tools/libacpi: expose the minimum alignment used by mem_ops.alloc Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 08/15] tools/libacpi: add callback acpi_ctxt.p2v to get a pointer from physical address Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 09/15] tools/libacpi: add callbacks to access XenStore Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 10/15] tools/libacpi: add a simple AML builder Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 11/15] tools/libacpi: load ACPI built by the device model Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 12/15] tools/libxl: build qemu options from xl vNVDIMM configs Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 13/15] tools/libxl: add support to map host pmem device to guests Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 14/15] tools/libxl: initiate pmem mapping via qmp callback Haozhong Zhang
2017-03-20 0:09 ` [RFC XEN PATCH v2 15/15] tools/misc: add xen-ndctl Haozhong Zhang
2017-03-30 4:11 ` Dan Williams
2017-03-30 7:58 ` Haozhong Zhang
2017-04-01 11:55 ` Konrad Rzeszutek Wilk
2017-03-30 4:20 ` [RFC XEN PATCH v2 00/15] Add vNVDIMM support to HVM domains Dan Williams
2017-03-30 8:21 ` Haozhong Zhang
2017-03-30 16:01 ` Dan Williams
2017-04-01 11:54 ` Konrad Rzeszutek Wilk
2017-04-01 15:45 ` Dan Williams
2017-04-04 17:00 ` Konrad Rzeszutek Wilk
2017-04-04 17:16 ` Dan Williams
2017-04-04 17:34 ` Konrad Rzeszutek Wilk
2017-04-04 17:59 ` Dan Williams
2017-04-04 18:05 ` Konrad Rzeszutek Wilk
2017-04-04 18:59 ` Dan Williams
2017-04-11 17:48 ` Konrad Rzeszutek Wilk
2017-04-01 12:24 ` Konrad Rzeszutek Wilk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170320000949.24675-3-haozhong.zhang@intel.com \
--to=haozhong.zhang@intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=dan.j.williams@intel.com \
--cc=jbeulich@suse.com \
--cc=konrad@darnok.org \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).