diff mbox

[RFC,v3,18/24] ACPI: Refactor acpi SRAT and SLIT table handling code

Message ID 1500378106-2620-19-git-send-email-vijay.kilari@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vijay Kilari July 18, 2017, 11:41 a.m. UTC
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

Move SRAT handling code which is common across
architectures is moved to new file xen/drivers/acpi/srat.c
from xen/arch/x86/srat.c file. New header file srat.h is
introduced.

Other major changes are:
- Coding style of code moved is changed.
- Moved struct pxm2node from srat.c to srat.h
- Dropped {memory,processor}_nodes_parsed from x86/srat.c
- Dropped static on node_to_pxm() and moved to beginning of the file.
- Made some static functions as non-static
- acpi_node_distance() is introduced and called from __node_distance()
- Replaced distance constants with LOCAL/REMOTE_DISTANCE defines

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
---
v3: - Moved common function declarations from asm-x86/srat.h
---
 xen/arch/x86/dom0_build.c           |   1 +
 xen/arch/x86/mm.c                   |   2 -
 xen/arch/x86/physdev.c              |   1 +
 xen/arch/x86/setup.c                |   1 +
 xen/arch/x86/smpboot.c              |   1 +
 xen/arch/x86/srat.c                 | 246 +----------------------------
 xen/arch/x86/x86_64/mm.c            |   1 +
 xen/drivers/acpi/Makefile           |   1 +
 xen/drivers/acpi/srat.c             | 298 ++++++++++++++++++++++++++++++++++++
 xen/drivers/passthrough/vtd/iommu.c |   1 +
 xen/include/acpi/srat.h             |  24 +++
 xen/include/asm-x86/numa.h          |   5 -
 12 files changed, 331 insertions(+), 251 deletions(-)

Comments

Wei Liu July 18, 2017, 3:36 p.m. UTC | #1
On Tue, Jul 18, 2017 at 05:11:40PM +0530, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> 
> Move SRAT handling code which is common across
> architectures is moved to new file xen/drivers/acpi/srat.c
> from xen/arch/x86/srat.c file. New header file srat.h is
> introduced.
> 
> Other major changes are:
> - Coding style of code moved is changed.
> - Moved struct pxm2node from srat.c to srat.h
> - Dropped {memory,processor}_nodes_parsed from x86/srat.c
> - Dropped static on node_to_pxm() and moved to beginning of the file.
> - Made some static functions as non-static
> - acpi_node_distance() is introduced and called from __node_distance()
> - Replaced distance constants with LOCAL/REMOTE_DISTANCE defines

It would be nice if you could break these into individual patches.

[...]
> +
> +/*
> + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
> + * up the NUMA heuristics which wants the local node to have a smaller
> + * distance than the others.
> + * Do some quick checks here and only use the SLIT if it passes.
> + */
> +static int __init slit_valid(struct acpi_table_slit *slit)
> +{
> +    int i, j;

unsigned int
Vijay Kilari July 19, 2017, 6:33 a.m. UTC | #2
On Tue, Jul 18, 2017 at 9:06 PM, Wei Liu <wei.liu2@citrix.com> wrote:
> On Tue, Jul 18, 2017 at 05:11:40PM +0530, vijay.kilari@gmail.com wrote:
>> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>>
>> Move SRAT handling code which is common across
>> architectures is moved to new file xen/drivers/acpi/srat.c
>> from xen/arch/x86/srat.c file. New header file srat.h is
>> introduced.
>>
>> Other major changes are:
>> - Coding style of code moved is changed.
>> - Moved struct pxm2node from srat.c to srat.h
>> - Dropped {memory,processor}_nodes_parsed from x86/srat.c
>> - Dropped static on node_to_pxm() and moved to beginning of the file.
>> - Made some static functions as non-static
>> - acpi_node_distance() is introduced and called from __node_distance()
>> - Replaced distance constants with LOCAL/REMOTE_DISTANCE defines
>
> It would be nice if you could break these into individual patches.

Ok. I will split.

>
> [...]
>> +
>> +/*
>> + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
>> + * up the NUMA heuristics which wants the local node to have a smaller
>> + * distance than the others.
>> + * Do some quick checks here and only use the SLIT if it passes.
>> + */
>> +static int __init slit_valid(struct acpi_table_slit *slit)
>> +{
>> +    int i, j;
>
> unsigned int

ok
>
diff mbox

Patch

diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index 0c125e6..04127e7 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -11,6 +11,7 @@ 
 #include <xen/sched.h>
 #include <xen/sched-if.h>
 #include <xen/softirq.h>
+#include <acpi/srat.h>
 
 #include <asm/dom0_build.h>
 #include <asm/hpet.h>
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 19f672d..5497621 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -135,8 +135,6 @@  l1_pgentry_t __section(".bss.page_aligned") __aligned(PAGE_SIZE)
 #define PTE_UPDATE_WITH_CMPXCHG
 #endif
 
-paddr_t __read_mostly mem_hotplug;
-
 /* Private domain structs for DOMID_XEN and DOMID_IO. */
 struct domain *dom_xen, *dom_io, *dom_cow;
 
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 0eb4097..a73a954 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -8,6 +8,7 @@ 
 #include <xen/guest_access.h>
 #include <xen/iocap.h>
 #include <xen/serial.h>
+#include <acpi/srat.h>
 #include <asm/current.h>
 #include <asm/io_apic.h>
 #include <asm/msi.h>
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index db5df69..b957b96 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -27,6 +27,7 @@ 
 #include <xen/tmem_xen.h>
 #include <xen/virtual_region.h>
 #include <xen/watchdog.h>
+#include <acpi/srat.h>
 #include <public/version.h>
 #include <compat/platform.h>
 #include <compat/xen.h>
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 168c9d4..ff4c7e1 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -33,6 +33,7 @@ 
 #include <xen/serial.h>
 #include <xen/numa.h>
 #include <xen/cpu.h>
+#include <acpi/srat.h>
 #include <asm/current.h>
 #include <asm/mc146818rtc.h>
 #include <asm/desc.h>
diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c
index be2634a..d5caccf 100644
--- a/xen/arch/x86/srat.c
+++ b/xen/arch/x86/srat.c
@@ -18,92 +18,10 @@ 
 #include <xen/acpi.h>
 #include <xen/numa.h>
 #include <xen/pfn.h>
+#include <acpi/srat.h>
 #include <asm/e820.h>
 #include <asm/page.h>
 
-static struct acpi_table_slit *__read_mostly acpi_slit;
-
-struct pxm2node {
-	unsigned int pxm;
-	nodeid_t node;
-};
-static struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] =
-	{ [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} };
-
-static unsigned int node_to_pxm(nodeid_t n);
-
-static __initdata DECLARE_BITMAP(memblk_hotplug, NR_NODE_MEMBLKS);
-
-static inline bool node_found(unsigned int idx, unsigned int pxm)
-{
-	return ((pxm2node[idx].pxm == pxm) &&
-		(pxm2node[idx].node != NUMA_NO_NODE));
-}
-
-static void reset_pxm2node(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(pxm2node); i++)
-		pxm2node[i].node = NUMA_NO_NODE;
-}
-
-nodeid_t pxm_to_node(unsigned int pxm)
-{
-	unsigned int i;
-
-	if ((pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm))
-		return pxm2node[pxm].node;
-
-	for (i = 0; i < ARRAY_SIZE(pxm2node); i++)
-		if (node_found(i, pxm))
-			return pxm2node[i].node;
-
-	return NUMA_NO_NODE;
-}
-
-nodeid_t acpi_setup_node(unsigned int pxm)
-{
-	nodeid_t node;
-	unsigned int idx;
-	static bool warned;
-	static unsigned int nodes_found;
-
-	BUILD_BUG_ON(MAX_NUMNODES >= NUMA_NO_NODE);
-
-	if (pxm < ARRAY_SIZE(pxm2node)) {
-		if (node_found(pxm, pxm))
-			return pxm2node[pxm].node;
-
-		/* Try to maintain indexing of pxm2node by pxm */
-		if (pxm2node[pxm].node == NUMA_NO_NODE) {
-			idx = pxm;
-			goto finish;
-		}
-	}
-
-	for (idx = 0; idx < ARRAY_SIZE(pxm2node); idx++)
-		if (pxm2node[idx].node == NUMA_NO_NODE)
-			goto finish;
-
-	if (!warned) {
-		printk(KERN_WARNING "SRAT: Too many proximity domains (%#x)\n",
-		       pxm);
-		warned = true;
-	}
-
-	return NUMA_NO_NODE;
-
- finish:
-	node = nodes_found++;
-	if (node >= MAX_NUMNODES)
-		return NUMA_NO_NODE;
-	pxm2node[idx].pxm = pxm;
-	pxm2node[idx].node = node;
-
-	return node;
-}
-
 void __init numa_failed(void)
 {
 	int i;
@@ -115,48 +33,6 @@  void __init numa_failed(void)
 	mem_hotplug = 0;
 }
 
-/*
- * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
- * up the NUMA heuristics which wants the local node to have a smaller
- * distance than the others.
- * Do some quick checks here and only use the SLIT if it passes.
- */
-static int __init slit_valid(struct acpi_table_slit *slit)
-{
-	int i, j;
-	int d = slit->locality_count;
-	for (i = 0; i < d; i++) {
-		for (j = 0; j < d; j++)  {
-			uint8_t val = slit->entry[d*i + j];
-			if (i == j) {
-				if (val != 10)
-					return 0;
-			} else if (val <= 10)
-				return 0;
-		}
-	}
-	return 1;
-}
-
-/* Callback for SLIT parsing */
-void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
-{
-	unsigned long mfn;
-	if (!slit_valid(slit)) {
-		printk(KERN_INFO "ACPI: SLIT table looks invalid. "
-		       "Not used.\n");
-		return;
-	}
-	mfn = alloc_boot_pages(PFN_UP(slit->header.length), 1);
-	if (!mfn) {
-		printk(KERN_ERR "ACPI: Unable to allocate memory for "
-		       "saving ACPI SLIT numa information.\n");
-		return;
-	}
-	acpi_slit = mfn_to_virt(mfn);
-	memcpy(acpi_slit, slit, slit->header.length);
-}
-
 /* Callback for Proximity Domain -> x2APIC mapping */
 void __init
 acpi_numa_x2apic_affinity_init(const struct acpi_srat_x2apic_cpu_affinity *pa)
@@ -224,100 +100,6 @@  acpi_numa_processor_affinity_init(const struct acpi_srat_cpu_affinity *pa)
 	       pxm, pa->apic_id, node);
 }
 
-/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
-void __init
-acpi_numa_memory_affinity_init(const struct acpi_srat_mem_affinity *ma)
-{
-	paddr_t start, end;
-	unsigned int pxm;
-	nodeid_t node;
-	int i;
-	struct node *memblk;
-
-	if (srat_disabled())
-		return;
-	if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) {
-		numa_failed();
-		return;
-	}
-	if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
-		return;
-
-	if (get_num_node_memblks() >= NR_NODE_MEMBLKS)
-	{
-		dprintk(XENLOG_WARNING,
-                "Too many numa entry, try bigger NR_NODE_MEMBLKS \n");
-		numa_failed();
-		return;
-	}
-
-	start = ma->base_address;
-	end = start + ma->length;
-	pxm = ma->proximity_domain;
-	if (srat_rev < 2)
-		pxm &= 0xff;
-	node = acpi_setup_node(pxm);
-	if (node == NUMA_NO_NODE) {
-		numa_failed();
-		return;
-	}
-	/* It is fine to add this area to the nodes data it will be used later*/
-	i = conflicting_memblks(start, end);
-	if (i < 0)
-		/* everything fine */;
-	else if (get_memblk_nodeid(i) == node) {
-		bool mismatch = !(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) !=
-		                !test_bit(i, memblk_hotplug);
-
-		memblk = get_node_memblk_range(i);
-
-		printk("%sSRAT: PXM %u (%"PRIx64"-%"PRIx64") overlaps with itself (%"PRIx64"-%"PRIx64")\n",
-		       mismatch ? KERN_ERR : KERN_WARNING, pxm, start, end,
-		       memblk->start, memblk->end);
-		if (mismatch) {
-			numa_failed();
-			return;
-		}
-	} else {
-		memblk = get_node_memblk_range(i);
-
-		printk(KERN_ERR
-		       "SRAT: PXM %u (%"PRIx64"-%"PRIx64") overlaps with PXM %u (%"PRIx64"-%"PRIx64")\n",
-		       pxm, start, end, node_to_pxm(get_memblk_nodeid(i)),
-		       memblk->start, memblk->end);
-		numa_failed();
-		return;
-	}
-	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
-		struct node *nd = get_numa_node(node);
-
-		if (!node_test_and_set(node, memory_nodes_parsed)) {
-			nd->start = start;
-			nd->end = end;
-		} else {
-			if (start < nd->start)
-				nd->start = start;
-			if (nd->end < end)
-				nd->end = end;
-		}
-	}
-	printk(KERN_INFO "SRAT: Node %u PXM %u %"PRIx64"-%"PRIx64"%s\n",
-	       node, pxm, start, end,
-	       ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE ? " (hotplug)" : "");
-
-	if (numa_add_memblk(node, start, ma->length)) {
-		printk(KERN_ERR "SRAT: node-id %u out of range\n", node);
-		numa_failed();
-		return;
-	}
-
-	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
-		__set_bit(get_num_node_memblks(), memblk_hotplug);
-		if (end > mem_hotplug)
-			mem_hotplug = end;
-	}
-}
-
 /* Sanity check to catch more bad SRATs (they are amazingly common).
    Make sure the PXMs cover all memory. */
 bool __init arch_sanitize_nodes_memory(void)
@@ -417,33 +199,9 @@  void __init srat_parse_regions(paddr_t addr)
 	pfn_pdx_hole_setup(mask >> PAGE_SHIFT);
 }
 
-static unsigned int node_to_pxm(nodeid_t n)
-{
-	unsigned int i;
-
-	if ((n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n))
-		return pxm2node[n].pxm;
-	for (i = 0; i < ARRAY_SIZE(pxm2node); i++)
-		if (pxm2node[i].node == n)
-			return pxm2node[i].pxm;
-	return 0;
-}
-
 uint8_t __node_distance(nodeid_t a, nodeid_t b)
 {
-	unsigned int index;
-	uint8_t slit_val;
-
-	if (!acpi_slit)
-		return a == b ? 10 : 20;
-	index = acpi_slit->locality_count * node_to_pxm(a);
-	slit_val = acpi_slit->entry[index + node_to_pxm(b)];
-
-	/* ACPI defines 0xff as an unreachable node and 0-9 are undefined */
-	if ((slit_val == 0xff) || (slit_val <= 9))
-		return NUMA_NO_DISTANCE;
-	else
-		return slit_val;
+	return acpi_node_distance(a, b);
 }
 
 EXPORT_SYMBOL(__node_distance);
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index a4ffa1f..b6e8eaf 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -27,6 +27,7 @@  asm(".file \"" __FILE__ "\"");
 #include <xen/guest_access.h>
 #include <xen/hypercall.h>
 #include <xen/mem_access.h>
+#include <acpi/srat.h>
 #include <asm/current.h>
 #include <asm/asm_defns.h>
 #include <asm/page.h>
diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile
index 444b11d..69edc26 100644
--- a/xen/drivers/acpi/Makefile
+++ b/xen/drivers/acpi/Makefile
@@ -4,6 +4,7 @@  subdir-$(CONFIG_X86) += apei
 
 obj-bin-y += tables.init.o
 obj-$(CONFIG_NUMA) += numa.o
+obj-$(CONFIG_NUMA) += srat.o
 obj-y += osl.o
 obj-$(CONFIG_HAS_CPUFREQ) += pmstat.o
 
diff --git a/xen/drivers/acpi/srat.c b/xen/drivers/acpi/srat.c
new file mode 100644
index 0000000..19b1647
--- /dev/null
+++ b/xen/drivers/acpi/srat.c
@@ -0,0 +1,298 @@ 
+/*
+ * ACPI 3.0 based NUMA setup
+ * Copyright 2004 Andi Kleen, SuSE Labs.
+ *
+ * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
+ *
+ * Called from acpi_numa_init while reading the SRAT and SLIT tables.
+ * Assumes all memory regions belonging to a single proximity domain
+ * are in one chunk. Holes between them will be included in the node.
+ *
+ * Adapted for Xen: Ryan Harper <ryanh@us.ibm.com>
+ */
+
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/inttypes.h>
+#include <xen/nodemask.h>
+#include <xen/acpi.h>
+#include <xen/numa.h>
+#include <xen/pfn.h>
+#include <acpi/srat.h>
+#include <asm/page.h>
+#include <asm/acpi.h>
+
+paddr_t __read_mostly mem_hotplug;
+static struct acpi_table_slit *__read_mostly acpi_slit;
+static struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] =
+    { [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} };
+
+static __initdata DECLARE_BITMAP(memblk_hotplug, NR_NODE_MEMBLKS);
+
+static inline bool node_found(unsigned int idx, unsigned int pxm)
+{
+    return ((pxm2node[idx].pxm == pxm) &&
+            (pxm2node[idx].node != NUMA_NO_NODE));
+}
+
+void reset_pxm2node(void)
+{
+    unsigned int i;
+
+    for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ )
+        pxm2node[i].node = NUMA_NO_NODE;
+}
+
+unsigned int node_to_pxm(nodeid_t n)
+{
+    unsigned int i;
+
+    if ( (n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n) )
+        return pxm2node[n].pxm;
+
+    for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ )
+        if ( pxm2node[i].node == n )
+            return pxm2node[i].pxm;
+
+    return 0;
+}
+
+nodeid_t pxm_to_node(unsigned int pxm)
+{
+    unsigned int i;
+
+    if ( (pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm) )
+        return pxm2node[pxm].node;
+
+    for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ )
+        if ( node_found(i, pxm) )
+            return pxm2node[i].node;
+
+    return NUMA_NO_NODE;
+}
+
+nodeid_t acpi_setup_node(unsigned int pxm)
+{
+    nodeid_t node;
+    unsigned int idx;
+    static bool warned;
+    static unsigned int nodes_found;
+
+    BUILD_BUG_ON(MAX_NUMNODES >= NUMA_NO_NODE);
+
+    if ( pxm < ARRAY_SIZE(pxm2node) )
+    {
+        if ( node_found(pxm, pxm) )
+            return pxm2node[pxm].node;
+
+        /* Try to maintain indexing of pxm2node by pxm */
+        if ( pxm2node[pxm].node == NUMA_NO_NODE )
+        {
+            idx = pxm;
+            goto finish;
+        }
+    }
+
+    for ( idx = 0; idx < ARRAY_SIZE(pxm2node); idx++ )
+        if ( pxm2node[idx].node == NUMA_NO_NODE )
+            goto finish;
+
+    if ( !warned )
+    {
+        printk(KERN_WARNING "SRAT: Too many proximity domains (%#x)\n", pxm);
+        warned = true;
+    }
+
+    return NUMA_NO_NODE;
+
+ finish:
+    node = nodes_found++;
+    if ( node >= MAX_NUMNODES )
+        return NUMA_NO_NODE;
+    pxm2node[idx].pxm = pxm;
+    pxm2node[idx].node = node;
+
+    return node;
+}
+
+/*
+ * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
+ * up the NUMA heuristics which wants the local node to have a smaller
+ * distance than the others.
+ * Do some quick checks here and only use the SLIT if it passes.
+ */
+static int __init slit_valid(struct acpi_table_slit *slit)
+{
+    int i, j;
+    int d = slit->locality_count;
+
+    for ( i = 0; i < d; i++ )
+    {
+        for ( j = 0; j < d; j++ )
+        {
+            uint8_t val = slit->entry[d*i + j];
+
+            if ( i == j )
+            {
+                if ( val != LOCAL_DISTANCE )
+                    return 0;
+            } else if ( val <= LOCAL_DISTANCE )
+                return 0;
+        }
+    }
+
+    return 1;
+}
+
+/* Callback for SLIT parsing */
+void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
+{
+    unsigned long mfn;
+
+    if ( !slit_valid(slit) )
+    {
+        printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+        return;
+    }
+    mfn = alloc_boot_pages(PFN_UP(slit->header.length), 1);
+    if ( !mfn )
+    {
+        printk(KERN_ERR "ACPI: Unable to allocate memory for "
+               "saving ACPI SLIT numa information.\n");
+        return;
+    }
+    acpi_slit = mfn_to_virt(mfn);
+    memcpy(acpi_slit, slit, slit->header.length);
+}
+
+/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
+void __init
+acpi_numa_memory_affinity_init(const struct acpi_srat_mem_affinity *ma)
+{
+    paddr_t start, end;
+    unsigned int pxm;
+    nodeid_t node;
+    int i;
+    struct node *memblk;
+
+    if ( srat_disabled() )
+        return;
+    if ( ma->header.length != sizeof(struct acpi_srat_mem_affinity) )
+    {
+        numa_failed();
+        return;
+    }
+    if ( !(ma->flags & ACPI_SRAT_MEM_ENABLED) )
+        return;
+
+    if ( get_num_node_memblks() >= NR_NODE_MEMBLKS )
+    {
+        dprintk(XENLOG_WARNING,
+                "Too many numa entry, try bigger NR_NODE_MEMBLKS \n");
+        numa_failed();
+        return;
+    }
+
+    start = ma->base_address;
+    end = start + ma->length;
+    pxm = ma->proximity_domain;
+    if ( srat_rev < 2 )
+        pxm &= 0xff;
+    node = acpi_setup_node(pxm);
+    if ( node == NUMA_NO_NODE )
+    {
+        numa_failed();
+        return;
+    }
+    /* It is fine to add this area to the nodes data it will be used later*/
+    i = conflicting_memblks(start, end);
+    if ( i < 0 )
+        /* everything fine */;
+    else if ( get_memblk_nodeid(i) == node )
+    {
+        bool mismatch = !(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) !=
+                        !test_bit(i, memblk_hotplug);
+
+        memblk = get_node_memblk_range(i);
+
+        printk("%sSRAT: PXM %u (%"PRIx64"-%"PRIx64") overlaps with itself (%"PRIx64"-%"PRIx64")\n",
+               mismatch ? KERN_ERR : KERN_WARNING, pxm, start, end,
+               memblk->start, memblk->end);
+        if ( mismatch )
+        {
+            numa_failed();
+            return;
+        }
+    }
+    else
+    {
+        memblk = get_node_memblk_range(i);
+
+        printk(KERN_ERR
+               "SRAT: PXM %u (%"PRIx64"-%"PRIx64") overlaps with PXM %u (%"PRIx64"-%"PRIx64")\n",
+               pxm, start, end, node_to_pxm(get_memblk_nodeid(i)),
+               memblk->start, memblk->end);
+        numa_failed();
+        return;
+    }
+    if ( !(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) )
+    {
+        struct node *nd = get_numa_node(node);
+
+        if ( !node_test_and_set(node, memory_nodes_parsed) )
+        {
+            nd->start = start;
+            nd->end = end;
+        }
+        else
+        {
+            if ( start < nd->start )
+                nd->start = start;
+            if ( nd->end < end )
+                nd->end = end;
+        }
+    }
+    printk(KERN_INFO "SRAT: Node %u PXM %u %"PRIx64"-%"PRIx64"%s\n",
+           node, pxm, start, end,
+           ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE ? " (hotplug)" : "");
+
+    if ( numa_add_memblk(node, start, ma->length) )
+    {
+        printk(KERN_ERR "SRAT: node-id %u out of range\n", node);
+        numa_failed();
+        return;
+    }
+
+    if ( ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE )
+    {
+        __set_bit(get_num_node_memblks(), memblk_hotplug);
+        if ( end > mem_hotplug )
+            mem_hotplug = end;
+    }
+}
+
+uint8_t acpi_node_distance(nodeid_t a, nodeid_t b)
+{
+    unsigned int index;
+    uint8_t slit_val;
+
+    if ( !acpi_slit )
+        return a == b ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+    index = acpi_slit->locality_count * node_to_pxm(a);
+    slit_val = acpi_slit->entry[index + node_to_pxm(b)];
+
+    /* ACPI defines 0xff as an unreachable node and 0-9 are undefined */
+    if ( (slit_val == 0xff) || (slit_val <= 9) )
+        return NUMA_NO_DISTANCE;
+    else
+        return slit_val;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 19328f6..27317dd 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -30,6 +30,7 @@ 
 #include <xen/pci.h>
 #include <xen/pci_regs.h>
 #include <xen/keyhandler.h>
+#include <acpi/srat.h>
 #include <asm/msi.h>
 #include <asm/irq.h>
 #include <asm/hvm/vmx/vmx.h>
diff --git a/xen/include/acpi/srat.h b/xen/include/acpi/srat.h
new file mode 100644
index 0000000..f19b822
--- /dev/null
+++ b/xen/include/acpi/srat.h
@@ -0,0 +1,24 @@ 
+#ifndef __XEN_SRAT_H__
+#define __XEN_SRAT_H__
+
+extern int srat_rev;
+struct pxm2node {
+    unsigned int pxm;
+    nodeid_t node;
+};
+
+nodeid_t pxm_to_node(unsigned pxm);
+nodeid_t acpi_setup_node(unsigned pxm);
+unsigned int node_to_pxm(nodeid_t n);
+uint8_t acpi_node_distance(nodeid_t a, nodeid_t b);
+void reset_pxm2node(void);
+#endif /* __XEN_SRAT_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/numa.h b/xen/include/asm-x86/numa.h
index fc4747f..4d266c2 100644
--- a/xen/include/asm-x86/numa.h
+++ b/xen/include/asm-x86/numa.h
@@ -5,13 +5,8 @@ 
 
 typedef uint8_t nodeid_t;
 
-extern int srat_rev;
-
-extern nodeid_t pxm_to_node(unsigned int pxm);
-
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
-extern nodeid_t acpi_setup_node(unsigned int pxm);
 extern void srat_detect_node(int cpu);
 
 extern nodeid_t apicid_to_node[];