@@ -13,6 +13,7 @@
#include <xen/init.h>
#include <xen/device_tree.h>
#include <xen/libfdt/libfdt.h>
+#include <xen/efi.h>
#include <xsm/xsm.h>
#include <asm/setup.h>
@@ -146,6 +147,9 @@ static void __init process_memory_node(const void *fdt, int node,
const __be32 *cell;
paddr_t start, size;
u32 reg_cells = address_cells + size_cells;
+#ifdef CONFIG_NUMA
+ uint32_t nid;
+#endif
if ( address_cells < 1 || size_cells < 1 )
{
@@ -154,24 +158,36 @@ static void __init process_memory_node(const void *fdt, int node,
return;
}
+#ifdef CONFIG_NUMA
+ nid = device_tree_get_u32(fdt, node, "numa-node-id", NR_NODE_MEMBLKS);
+#endif
prop = fdt_get_property(fdt, node, "reg", NULL);
if ( !prop )
{
printk("fdt: node `%s': missing `reg' property\n", name);
+#ifdef CONFIG_NUMA
+ numa_failed();
+#endif
return;
}
cell = (const __be32 *)prop->data;
banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
- for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ )
+ for ( i = 0; i < banks; i++ )
{
device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
if ( !size )
continue;
- bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start;
- bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size;
- bootinfo.mem.nr_banks++;
+ if ( !efi_enabled(EFI_BOOT) && bootinfo.mem.nr_banks < NR_MEM_BANKS )
+ {
+ bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start;
+ bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size;
+ bootinfo.mem.nr_banks++;
+ }
+#ifdef CONFIG_NUMA
+ dt_numa_process_memory_node(nid, start, size);
+#endif
}
}
@@ -194,33 +194,8 @@ EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
int status;
u32 fdt_val32;
u64 fdt_val64;
- int prev;
int num_rsv;
- /*
- * Delete any memory nodes present. The EFI memory map is the only
- * memory description provided to Xen.
- */
- prev = 0;
- for (;;)
- {
- const char *type;
- int len;
-
- node = fdt_next_node(fdt, prev, NULL);
- if ( node < 0 )
- break;
-
- type = fdt_getprop(fdt, node, "device_type", &len);
- if ( type && strncmp(type, "memory", len) == 0 )
- {
- fdt_del_node(fdt, node);
- continue;
- }
-
- prev = node;
- }
-
/*
* Delete all memory reserve map entries. When booting via UEFI,
* kernel will use the UEFI memory map to find reserved regions.
@@ -25,6 +25,7 @@
#include <asm/setup.h>
extern nodemask_t processor_nodes_parsed;
+extern nodemask_t memory_nodes_parsed;
/*
* Even though we connect cpus to numa domains later in SMP
@@ -59,6 +60,38 @@ static int __init dt_numa_scan_cpu_node(const void *fdt, int node,
return 0;
}
+void __init dt_numa_process_memory_node(uint32_t nid, paddr_t start,
+ paddr_t size)
+{
+ struct node *nd;
+ int i;
+
+ i = conflicting_memblks(start, start + size);
+ if ( i < 0 )
+ {
+ if ( numa_add_memblk(nid, start, size) )
+ {
+ printk(XENLOG_WARNING "DT: NUMA: node-id %u overflow \n", nid);
+ numa_failed();
+ return;
+ }
+ }
+ else
+ {
+ nd = get_node_memblk_range(i);
+ printk(XENLOG_ERR
+ "NUMA DT: node %u (%"PRIx64"-%"PRIx64") overlaps with %d (%"PRIx64"-%"PRIx64")\n",
+ nid, start, start + size, i, nd->start, nd->end);
+
+ numa_failed();
+ return;
+ }
+
+ node_set(nid, memory_nodes_parsed);
+
+ return;
+}
+
int __init dt_numa_init(void)
{
int ret;
@@ -23,6 +23,12 @@
#include <asm/acpi.h>
extern nodemask_t processor_nodes_parsed;
+static bool_t dt_numa = 1;
+
+void numa_failed(void)
+{
+ dt_numa = 0;
+}
void __init numa_init(void)
{
@@ -32,6 +38,9 @@ void __init numa_init(void)
if ( is_numa_off() )
goto no_numa;
+ if ( !dt_numa )
+ goto no_numa;
+
ret = dt_numa_init();
if ( ret )
printk(XENLOG_WARNING "DT NUMA init failed\n");
@@ -6,6 +6,8 @@ typedef uint8_t nodeid_t;
/* Limit number of NUMA nodes supported to 4 */
#define NODES_SHIFT 2
+extern void dt_numa_process_memory_node(uint32_t nid,paddr_t start,
+ paddr_t size);
#ifdef CONFIG_NUMA
extern void numa_init(void);
extern int dt_numa_init(void);