@@ -70,9 +70,74 @@ void numa_failed(void)
init_cpu_to_node();
}
+int __init arch_sanitize_nodes_memory(void)
+{
+ nodemask_t mem_nodes_parsed;
+ int bank, nodeid;
+ struct node *nd;
+ paddr_t start, size, end;
+
+ nodes_clear(mem_nodes_parsed);
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ {
+ start = bootinfo.mem.bank[bank].start;
+ size = bootinfo.mem.bank[bank].size;
+ end = start + size;
+
+ nodeid = get_mem_nodeid(start, end);
+ if ( nodeid >= NUMA_NO_NODE )
+ {
+ printk(XENLOG_WARNING
+ "NUMA: node for mem bank start 0x%lx - 0x%lx not found\n",
+ start, end);
+
+ return 0;
+ }
+
+ nd = get_numa_node(nodeid);
+ if ( !node_test_and_set(nodeid, mem_nodes_parsed) )
+ {
+ nd->start = start;
+ nd->end = end;
+ }
+ else
+ {
+ if ( start < nd->start )
+ nd->start = start;
+ if ( nd->end < end )
+ nd->end = end;
+ }
+ }
+
+ return 1;
+}
+
+static bool_t __init numa_initmem_init(paddr_t ram_start, paddr_t ram_end)
+{
+ int i;
+ struct node *nd;
+ /*
+ * In arch_sanitize_nodes_memory() we update nodes[] with properly.
+ * Hence we reset the nodes[] before calling numa_scan_nodes().
+ */
+ for ( i = 0; i < MAX_NUMNODES; i++ )
+ {
+ nd = get_numa_node(i);
+ nd->start = 0;
+ nd->end = 0;
+ }
+
+ if ( !numa_scan_nodes(ram_start, ram_end) )
+ return 0;
+
+ return 1;
+}
+
void __init numa_init(void)
{
- int ret = 0;
+ int ret = 0, bank;
+ paddr_t ram_start = ~0;
+ paddr_t ram_end = 0;
nodes_clear(processor_nodes_parsed);
init_cpu_to_node();
@@ -87,6 +152,18 @@ void __init numa_init(void)
if ( ret )
printk(XENLOG_WARNING "DT NUMA init failed\n");
+ for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ {
+ paddr_t bank_start = bootinfo.mem.bank[bank].start;
+ paddr_t bank_end = bank_start + bootinfo.mem.bank[bank].size;
+
+ ram_start = min(ram_start, bank_start);
+ ram_end = max(ram_end, bank_end);
+ }
+
+ if ( !ret )
+ ret = numa_initmem_init(ram_start, ram_end);
+
no_numa:
return;
}
@@ -84,6 +84,20 @@ nodeid_t get_memblk_nodeid(int id)
return memblk_nodeid[id];
}
+int __init get_mem_nodeid(paddr_t start, paddr_t end)
+{
+ unsigned int i;
+
+ for ( i = 0; i < get_num_node_memblks(); i++ )
+ {
+ if ( start >= node_memblk_range[i].start &&
+ end <= node_memblk_range[i].end )
+ return memblk_nodeid[i];
+ }
+
+ return -EINVAL;
+}
+
nodeid_t *get_memblk_nodeid_map(void)
{
return &memblk_nodeid[0];
@@ -1,6 +1,8 @@
#ifndef __ARCH_ARM_NUMA_H
#define __ARCH_ARM_NUMA_H
+#include <xen/mm.h>
+
typedef uint8_t nodeid_t;
/* Limit number of NUMA nodes supported to 4 */
@@ -28,6 +30,23 @@ extern uint8_t *memnodemap;
#define node_to_first_cpu(node) (__ffs(node_to_cpumask[node]))
#define node_to_cpumask(node) (node_to_cpumask[node])
+static inline __attribute__((pure)) nodeid_t phys_to_nid(paddr_t addr)
+{
+ return memnodemap[paddr_to_pdx(addr) >> memnode_shift];
+}
+
+struct node_data {
+ unsigned long node_start_pfn;
+ unsigned long node_spanned_pages;
+};
+
+extern struct node_data node_data[];
+#define NODE_DATA(nid) (&(node_data[nid]))
+
+#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
+#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages)
+#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
+
#else
static inline void numa_init(void)
{
@@ -38,6 +38,7 @@ extern nodeid_t *get_memblk_nodeid_map(void);
extern struct node *get_node_memblk_range(int memblk);
extern struct node *get_memblk(int memblk);
extern int numa_add_memblk(nodeid_t nodeid, paddr_t start, uint64_t size);
+extern int get_mem_nodeid(paddr_t start, paddr_t end);
extern int get_num_node_memblks(void);
extern int arch_sanitize_nodes_memory(void);
extern void numa_failed(void);