Commit 3c810c50 authored by Dave Hansen's avatar Dave Hansen Committed by Linus Torvalds

[PATCH] x86: abstract discontigmem setup

memory_present() is how each arch/subarch will tell sparsemem and discontigmem
where all of its memory is.  This is what triggers sparse to go out and create
its mappings for the memory, as well as allocate the mem_map[].

By: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: default avatarDave Hansen <haveblue@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f7e3b0c7
...@@ -777,6 +777,16 @@ config HAVE_ARCH_BOOTMEM_NODE ...@@ -777,6 +777,16 @@ config HAVE_ARCH_BOOTMEM_NODE
depends on NUMA depends on NUMA
default y default y
config HAVE_MEMORY_PRESENT
bool
depends on DISCONTIGMEM
default y
config NEED_NODE_MEMMAP_SIZE
bool
depends on DISCONTIGMEM
default y
config HIGHPTE config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem" bool "Allocate 3rd-level pagetables from highmem"
depends on HIGHMEM4G || HIGHMEM64G depends on HIGHMEM4G || HIGHMEM64G
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <asm/numaq.h> #include <asm/numaq.h>
/* These are needed before the pgdat's are created */ /* These are needed before the pgdat's are created */
extern long node_start_pfn[], node_end_pfn[]; extern long node_start_pfn[], node_end_pfn[], node_remap_size[];
#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
...@@ -59,6 +59,12 @@ static void __init smp_dump_qct(void) ...@@ -59,6 +59,12 @@ static void __init smp_dump_qct(void)
eq->hi_shrd_mem_start - eq->priv_mem_size); eq->hi_shrd_mem_start - eq->priv_mem_size);
node_end_pfn[node] = MB_TO_PAGES( node_end_pfn[node] = MB_TO_PAGES(
eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
memory_present(node,
node_start_pfn[node], node_end_pfn[node]);
node_remap_size[node] = node_memmap_size_bytes(node,
node_start_pfn[node],
node_end_pfn[node]);
} }
} }
} }
......
...@@ -58,7 +58,7 @@ static int num_memory_chunks; /* total number of memory chunks */ ...@@ -58,7 +58,7 @@ static int num_memory_chunks; /* total number of memory chunks */
static int zholes_size_init; static int zholes_size_init;
static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES]; static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
extern unsigned long node_start_pfn[], node_end_pfn[]; extern unsigned long node_start_pfn[], node_end_pfn[], node_remap_size[];
extern void * boot_ioremap(unsigned long, unsigned long); extern void * boot_ioremap(unsigned long, unsigned long);
...@@ -286,6 +286,13 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) ...@@ -286,6 +286,13 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
} }
} }
} }
for_each_online_node(nid) {
unsigned long start = node_start_pfn[nid];
unsigned long end = node_end_pfn[nid];
memory_present(nid, start, end);
node_remap_size[nid] = node_memmap_size_bytes(nid, start, end);
}
return 1; return 1;
out_fail: out_fail:
return 0; return 0;
......
...@@ -60,6 +60,32 @@ bootmem_data_t node0_bdata; ...@@ -60,6 +60,32 @@ bootmem_data_t node0_bdata;
*/ */
s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
void memory_present(int nid, unsigned long start, unsigned long end)
{
unsigned long pfn;
printk(KERN_INFO "Node: %d, start_pfn: %ld, end_pfn: %ld\n",
nid, start, end);
printk(KERN_DEBUG " Setting physnode_map array to node %d for pfns:\n", nid);
printk(KERN_DEBUG " ");
for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
printk("%ld ", pfn);
}
printk("\n");
}
unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
unsigned long end_pfn)
{
unsigned long nr_pages = end_pfn - start_pfn;
if (!nr_pages)
return 0;
return (nr_pages + 1) * sizeof(struct page);
}
unsigned long node_start_pfn[MAX_NUMNODES]; unsigned long node_start_pfn[MAX_NUMNODES];
unsigned long node_end_pfn[MAX_NUMNODES]; unsigned long node_end_pfn[MAX_NUMNODES];
...@@ -171,9 +197,9 @@ static unsigned long calculate_numa_remap_pages(void) ...@@ -171,9 +197,9 @@ static unsigned long calculate_numa_remap_pages(void)
if (node_end_pfn[nid] > max_pfn) if (node_end_pfn[nid] > max_pfn)
node_end_pfn[nid] = max_pfn; node_end_pfn[nid] = max_pfn;
/* calculate the size of the mem_map needed in bytes */ /* ensure the remap includes space for the pgdat. */
size = (node_end_pfn[nid] - node_start_pfn[nid] + 1) size = node_remap_size[nid] + sizeof(pg_data_t);
* sizeof(struct page) + sizeof(pg_data_t);
/* convert size to large (pmd size) pages, rounding up */ /* convert size to large (pmd size) pages, rounding up */
size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES; size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
/* now the roundup is correct, convert to PAGE_SIZE pages */ /* now the roundup is correct, convert to PAGE_SIZE pages */
...@@ -198,7 +224,7 @@ unsigned long __init setup_memory(void) ...@@ -198,7 +224,7 @@ unsigned long __init setup_memory(void)
{ {
int nid; int nid;
unsigned long system_start_pfn, system_max_low_pfn; unsigned long system_start_pfn, system_max_low_pfn;
unsigned long reserve_pages, pfn; unsigned long reserve_pages;
/* /*
* When mapping a NUMA machine we allocate the node_mem_map arrays * When mapping a NUMA machine we allocate the node_mem_map arrays
...@@ -207,23 +233,9 @@ unsigned long __init setup_memory(void) ...@@ -207,23 +233,9 @@ unsigned long __init setup_memory(void)
* this space and use it to adjust the boundry between ZONE_NORMAL * this space and use it to adjust the boundry between ZONE_NORMAL
* and ZONE_HIGHMEM. * and ZONE_HIGHMEM.
*/ */
find_max_pfn();
get_memcfg_numa(); get_memcfg_numa();
/* Fill in the physnode_map */
for_each_online_node(nid) {
printk("Node: %d, start_pfn: %ld, end_pfn: %ld\n",
nid, node_start_pfn[nid], node_end_pfn[nid]);
printk(" Setting physnode_map array to node %d for pfns:\n ",
nid);
for (pfn = node_start_pfn[nid]; pfn < node_end_pfn[nid];
pfn += PAGES_PER_ELEMENT) {
physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
printk("%ld ", pfn);
}
printk("\n");
}
find_max_pfn();
reserve_pages = calculate_numa_remap_pages(); reserve_pages = calculate_numa_remap_pages();
/* partially used pages are not usable - thus round upwards */ /* partially used pages are not usable - thus round upwards */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/numa.h> #include <linux/numa.h>
#include <linux/init.h>
#include <asm/atomic.h> #include <asm/atomic.h>
/* Free memory management - zoned buddy allocator. */ /* Free memory management - zoned buddy allocator. */
...@@ -278,6 +279,16 @@ void wakeup_kswapd(struct zone *zone, int order); ...@@ -278,6 +279,16 @@ void wakeup_kswapd(struct zone *zone, int order);
int zone_watermark_ok(struct zone *z, int order, unsigned long mark, int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int alloc_type, int can_try_harder, int gfp_high); int alloc_type, int can_try_harder, int gfp_high);
#ifdef CONFIG_HAVE_MEMORY_PRESENT
void memory_present(int nid, unsigned long start, unsigned long end);
#else
static inline void memory_present(int nid, unsigned long start, unsigned long end) {}
#endif
#ifdef CONFIG_NEED_NODE_MEMMAP_SIZE
unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
#endif
/* /*
* zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc. * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment