2008-01-30 12:32:36 +00:00
|
|
|
/*
|
2010-10-29 15:14:30 +00:00
|
|
|
* AMD NUMA support.
|
2005-04-16 22:20:36 +00:00
|
|
|
* Discover the memory map and associated nodes.
|
2008-01-30 12:32:36 +00:00
|
|
|
*
|
2010-10-29 15:14:30 +00:00
|
|
|
* This version reads it directly from the AMD northbridge.
|
2008-01-30 12:32:36 +00:00
|
|
|
*
|
2005-04-16 22:20:36 +00:00
|
|
|
* Copyright 2002,2003 Andi Kleen, SuSE Labs.
|
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/nodemask.h>
|
2010-08-25 20:39:17 +00:00
|
|
|
#include <linux/memblock.h>
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <asm/io.h>
|
|
|
|
#include <linux/pci_ids.h>
|
2008-02-19 11:21:06 +00:00
|
|
|
#include <linux/acpi.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <asm/types.h>
|
|
|
|
#include <asm/mmzone.h>
|
|
|
|
#include <asm/proto.h>
|
|
|
|
#include <asm/e820.h>
|
|
|
|
#include <asm/pci-direct.h>
|
|
|
|
#include <asm/numa.h>
|
2008-02-19 11:21:06 +00:00
|
|
|
#include <asm/mpspec.h>
|
|
|
|
#include <asm/apic.h>
|
2010-09-17 16:03:43 +00:00
|
|
|
#include <asm/amd_nb.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-09-25 22:20:00 +00:00
|
|
|
static struct bootnode __initdata nodes[8];
|
2010-12-23 01:23:51 +00:00
|
|
|
static unsigned char __initdata nodeids[8];
|
2009-09-25 22:20:00 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
static __init int find_northbridge(void)
|
|
|
|
{
|
2008-01-30 12:32:36 +00:00
|
|
|
int num;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
for (num = 0; num < 32; num++) {
|
2005-04-16 22:20:36 +00:00
|
|
|
u32 header;
|
2008-01-30 12:32:36 +00:00
|
|
|
|
|
|
|
header = read_pci_config(0, num, 0, 0x00);
|
2008-01-30 12:34:12 +00:00
|
|
|
if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16)) &&
|
|
|
|
header != (PCI_VENDOR_ID_AMD | (0x1200<<16)) &&
|
|
|
|
header != (PCI_VENDOR_ID_AMD | (0x1300<<16)))
|
2008-01-30 12:32:36 +00:00
|
|
|
continue;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
header = read_pci_config(0, num, 1, 0x00);
|
2008-01-30 12:34:12 +00:00
|
|
|
if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16)) &&
|
|
|
|
header != (PCI_VENDOR_ID_AMD | (0x1201<<16)) &&
|
|
|
|
header != (PCI_VENDOR_ID_AMD | (0x1301<<16)))
|
2008-01-30 12:32:36 +00:00
|
|
|
continue;
|
|
|
|
return num;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-02-16 11:13:06 +00:00
|
|
|
return -ENOENT;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2008-02-19 11:21:06 +00:00
|
|
|
static __init void early_get_boot_cpu_id(void)
|
|
|
|
{
|
|
|
|
/*
|
2010-07-21 17:03:58 +00:00
|
|
|
* need to get the APIC ID of the BSP so can use that to
|
2010-10-29 15:14:30 +00:00
|
|
|
* create apicid_to_node in amd_scan_nodes()
|
2008-02-19 11:21:06 +00:00
|
|
|
*/
|
2008-06-19 19:15:01 +00:00
|
|
|
#ifdef CONFIG_X86_MPPARSE
|
2008-02-19 11:21:06 +00:00
|
|
|
/*
|
|
|
|
* get boot-time SMP configuration:
|
|
|
|
*/
|
|
|
|
if (smp_found_config)
|
|
|
|
early_get_smp_config();
|
2008-06-19 19:15:01 +00:00
|
|
|
#endif
|
2009-09-25 22:20:00 +00:00
|
|
|
}
|
|
|
|
|
2011-02-16 11:13:06 +00:00
|
|
|
int __init amd_numa_init(void)
|
2009-09-25 22:20:00 +00:00
|
|
|
{
|
2011-02-16 11:13:06 +00:00
|
|
|
unsigned long start = PFN_PHYS(0);
|
|
|
|
unsigned long end = PFN_PHYS(max_pfn);
|
2009-09-25 22:20:00 +00:00
|
|
|
unsigned numnodes;
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned long prevbase;
|
2011-02-16 11:13:07 +00:00
|
|
|
int i, j, nb;
|
2008-05-12 13:43:35 +00:00
|
|
|
u32 nodeid, reg;
|
2011-02-16 11:13:07 +00:00
|
|
|
unsigned int bits, cores, apicid_base;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-09-26 08:52:41 +00:00
|
|
|
if (!early_pci_allowed())
|
2011-02-16 11:13:06 +00:00
|
|
|
return -EINVAL;
|
2006-09-26 08:52:41 +00:00
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
nb = find_northbridge();
|
|
|
|
if (nb < 0)
|
2005-04-16 22:20:36 +00:00
|
|
|
return nb;
|
|
|
|
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Scanning NUMA topology in Northbridge %d\n", nb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
reg = read_pci_config(0, nb, 0, 0x60);
|
2005-04-16 22:20:36 +00:00
|
|
|
numnodes = ((reg >> 4) & 0xF) + 1;
|
2007-05-02 17:27:21 +00:00
|
|
|
if (numnodes <= 1)
|
2011-02-16 11:13:06 +00:00
|
|
|
return -ENOENT;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-09-25 22:20:00 +00:00
|
|
|
pr_info("Number of physical nodes %d\n", numnodes);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
prevbase = 0;
|
2008-01-30 12:32:36 +00:00
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
unsigned long base, limit;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
base = read_pci_config(0, nb, 1, 0x40 + i*8);
|
|
|
|
limit = read_pci_config(0, nb, 1, 0x44 + i*8);
|
|
|
|
|
2010-12-23 01:23:51 +00:00
|
|
|
nodeids[i] = nodeid = limit & 7;
|
2008-01-30 12:32:36 +00:00
|
|
|
if ((base & 3) == 0) {
|
2005-04-16 22:20:36 +00:00
|
|
|
if (i < numnodes)
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Skipping disabled node %d\n", i);
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
if (nodeid >= numnodes) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Ignoring excess node %d (%lx:%lx)\n", nodeid,
|
|
|
|
base, limit);
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
if (!limit) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Skipping node entry %d (base %lx)\n",
|
|
|
|
i, base);
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((base >> 8) & 3 || (limit >> 8) & 3) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_err("Node %d using interleaving mode %lx/%lx\n",
|
|
|
|
nodeid, (base >> 8) & 3, (limit >> 8) & 3);
|
2011-02-16 11:13:06 +00:00
|
|
|
return -EINVAL;
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|
2011-02-16 11:13:07 +00:00
|
|
|
if (node_isset(nodeid, mem_nodes_parsed)) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Node %d already present, skipping\n",
|
|
|
|
nodeid);
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-01-30 12:32:36 +00:00
|
|
|
limit >>= 16;
|
|
|
|
limit <<= 24;
|
2005-04-16 22:20:36 +00:00
|
|
|
limit |= (1<<24)-1;
|
2005-11-05 16:25:54 +00:00
|
|
|
limit++;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-09-25 22:20:00 +00:00
|
|
|
if (limit > end)
|
|
|
|
limit = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (limit <= base)
|
2008-01-30 12:32:36 +00:00
|
|
|
continue;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
base >>= 16;
|
2008-01-30 12:32:36 +00:00
|
|
|
base <<= 24;
|
|
|
|
|
|
|
|
if (base < start)
|
|
|
|
base = start;
|
|
|
|
if (limit > end)
|
|
|
|
limit = end;
|
|
|
|
if (limit == base) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_err("Empty node %d\n", nodeid);
|
2008-01-30 12:32:36 +00:00
|
|
|
continue;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2008-01-30 12:32:36 +00:00
|
|
|
if (limit < base) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_err("Node %d bogus settings %lx-%lx.\n",
|
2008-01-30 12:32:36 +00:00
|
|
|
nodeid, base, limit);
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Could sort here, but pun for now. Should not happen anyroads. */
|
2008-01-30 12:32:36 +00:00
|
|
|
if (prevbase > base) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_err("Node map not sorted %lx,%lx\n",
|
2008-01-30 12:32:36 +00:00
|
|
|
prevbase, base);
|
2011-02-16 11:13:06 +00:00
|
|
|
return -EINVAL;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2008-01-30 12:32:36 +00:00
|
|
|
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Node %d MemBase %016lx Limit %016lx\n",
|
|
|
|
nodeid, base, limit);
|
2008-01-30 12:32:36 +00:00
|
|
|
|
|
|
|
nodes[nodeid].start = base;
|
2005-04-16 22:20:36 +00:00
|
|
|
nodes[nodeid].end = limit;
|
|
|
|
|
|
|
|
prevbase = base;
|
|
|
|
|
2011-02-16 11:13:07 +00:00
|
|
|
node_set(nodeid, mem_nodes_parsed);
|
|
|
|
node_set(nodeid, cpu_nodes_parsed);
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-02-16 11:13:07 +00:00
|
|
|
if (!nodes_weight(mem_nodes_parsed))
|
2011-02-16 11:13:06 +00:00
|
|
|
return -ENOENT;
|
2011-02-16 11:13:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We seem to have valid NUMA configuration. Map apicids to nodes
|
|
|
|
* using the coreid bits from early_identify_cpu.
|
|
|
|
*/
|
|
|
|
bits = boot_cpu_data.x86_coreid_bits;
|
|
|
|
cores = 1 << bits;
|
|
|
|
apicid_base = 0;
|
|
|
|
|
|
|
|
/* get the APIC ID of the BSP early for systems with apicid lifting */
|
|
|
|
early_get_boot_cpu_id();
|
|
|
|
if (boot_cpu_physical_apicid > 0) {
|
|
|
|
pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
|
|
|
|
apicid_base = boot_cpu_physical_apicid;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_node_mask(i, cpu_nodes_parsed)
|
|
|
|
for (j = apicid_base; j < cores + apicid_base; j++)
|
|
|
|
set_apicid_to_node((i << bits) + j, i);
|
|
|
|
|
2009-09-25 22:20:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-12-23 01:23:51 +00:00
|
|
|
#ifdef CONFIG_NUMA_EMU
|
|
|
|
static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
|
|
|
|
[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
|
|
|
|
};
|
|
|
|
|
2010-12-23 01:23:56 +00:00
|
|
|
void __init amd_get_nodes(struct bootnode *physnodes)
|
2010-12-23 01:23:51 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2011-02-16 11:13:07 +00:00
|
|
|
for_each_node_mask(i, mem_nodes_parsed) {
|
2010-12-23 01:23:56 +00:00
|
|
|
physnodes[i].start = nodes[i].start;
|
|
|
|
physnodes[i].end = nodes[i].end;
|
2010-12-23 01:23:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init find_node_by_addr(unsigned long addr)
|
|
|
|
{
|
|
|
|
int ret = NUMA_NO_NODE;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
if (addr >= nodes[i].start && addr < nodes[i].end) {
|
|
|
|
ret = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be
|
|
|
|
* setup to represent the physical topology but reflect the emulated
|
|
|
|
* environment. For each emulated node, the real node which it appears on is
|
|
|
|
* found and a fake pxm to nid mapping is created which mirrors the actual
|
|
|
|
* locality. node_distance() then represents the correct distances between
|
|
|
|
* emulated nodes by using the fake acpi mappings to pxms.
|
|
|
|
*/
|
|
|
|
void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
|
|
|
|
{
|
|
|
|
unsigned int bits;
|
|
|
|
unsigned int cores;
|
|
|
|
unsigned int apicid_base = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
bits = boot_cpu_data.x86_coreid_bits;
|
|
|
|
cores = 1 << bits;
|
|
|
|
early_get_boot_cpu_id();
|
|
|
|
if (boot_cpu_physical_apicid > 0)
|
|
|
|
apicid_base = boot_cpu_physical_apicid;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_nodes; i++) {
|
|
|
|
int index;
|
|
|
|
int nid;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
nid = find_node_by_addr(nodes[i].start);
|
|
|
|
if (nid == NUMA_NO_NODE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
index = nodeids[nid] << bits;
|
|
|
|
if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE)
|
|
|
|
for (j = apicid_base; j < cores + apicid_base; j++)
|
|
|
|
fake_apicid_to_node[index + j] = i;
|
|
|
|
#ifdef CONFIG_ACPI_NUMA
|
|
|
|
__acpi_map_pxm_to_node(nid, i);
|
|
|
|
#endif
|
|
|
|
}
|
2011-01-23 13:37:39 +00:00
|
|
|
memcpy(__apicid_to_node, fake_apicid_to_node, sizeof(__apicid_to_node));
|
2010-12-23 01:23:51 +00:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_NUMA_EMU */
|
|
|
|
|
2010-10-29 15:14:30 +00:00
|
|
|
int __init amd_scan_nodes(void)
|
2009-09-25 22:20:00 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2008-03-25 17:14:35 +00:00
|
|
|
memnode_shift = compute_hash_shift(nodes, 8, NULL);
|
2008-01-30 12:32:36 +00:00
|
|
|
if (memnode_shift < 0) {
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_err("No NUMA node hash function found. Contact maintainer\n");
|
2008-01-30 12:32:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-09-25 22:19:47 +00:00
|
|
|
pr_info("Using node hash shift of %d\n", memnode_shift);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-30 12:30:39 +00:00
|
|
|
/* use the coreid bits from early_identify_cpu */
|
x86-64, numa: Put pgtable to local node memory
Introduce init_memory_mapping_high(), and use it with 64bit.
It will go with every memory segment above 4g to create page table to the
memory range itself.
before this patch all page tables was on one node.
with this patch, one RED-PEN is killed
debug out for 8 sockets system after patch
[ 0.000000] initial memory mapped : 0 - 20000000
[ 0.000000] init_memory_mapping: [0x00000000000000-0x0000007f74ffff]
[ 0.000000] 0000000000 - 007f600000 page 2M
[ 0.000000] 007f600000 - 007f750000 page 4k
[ 0.000000] kernel direct mapping tables up to 7f750000 @ [0x7f74c000-0x7f74ffff]
[ 0.000000] RAMDISK: 7bc84000 - 7f745000
....
[ 0.000000] Adding active range (0, 0x10, 0x95) 0 entries of 3200 used
[ 0.000000] Adding active range (0, 0x100, 0x7f750) 1 entries of 3200 used
[ 0.000000] Adding active range (0, 0x100000, 0x1080000) 2 entries of 3200 used
[ 0.000000] Adding active range (1, 0x1080000, 0x2080000) 3 entries of 3200 used
[ 0.000000] Adding active range (2, 0x2080000, 0x3080000) 4 entries of 3200 used
[ 0.000000] Adding active range (3, 0x3080000, 0x4080000) 5 entries of 3200 used
[ 0.000000] Adding active range (4, 0x4080000, 0x5080000) 6 entries of 3200 used
[ 0.000000] Adding active range (5, 0x5080000, 0x6080000) 7 entries of 3200 used
[ 0.000000] Adding active range (6, 0x6080000, 0x7080000) 8 entries of 3200 used
[ 0.000000] Adding active range (7, 0x7080000, 0x8080000) 9 entries of 3200 used
[ 0.000000] init_memory_mapping: [0x00000100000000-0x0000107fffffff]
[ 0.000000] 0100000000 - 1080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 1080000000 @ [0x107ffbd000-0x107fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x107ffc2000-0x107fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00001080000000-0x0000207fffffff]
[ 0.000000] 1080000000 - 2080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 2080000000 @ [0x207ff7d000-0x207fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x207ffc0000-0x207fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00002080000000-0x0000307fffffff]
[ 0.000000] 2080000000 - 3080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 3080000000 @ [0x307ff3d000-0x307fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x307ffc0000-0x307fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00003080000000-0x0000407fffffff]
[ 0.000000] 3080000000 - 4080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 4080000000 @ [0x407fefd000-0x407fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x407ffc0000-0x407fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00004080000000-0x0000507fffffff]
[ 0.000000] 4080000000 - 5080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 5080000000 @ [0x507febd000-0x507fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x507ffc0000-0x507fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00005080000000-0x0000607fffffff]
[ 0.000000] 5080000000 - 6080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 6080000000 @ [0x607fe7d000-0x607fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x607ffc0000-0x607fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00006080000000-0x0000707fffffff]
[ 0.000000] 6080000000 - 7080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 7080000000 @ [0x707fe3d000-0x707fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x707ffc0000-0x707fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00007080000000-0x0000807fffffff]
[ 0.000000] 7080000000 - 8080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 8080000000 @ [0x807fdfc000-0x807fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x807ffbf000-0x807fffffff] PGTABLE
[ 0.000000] Initmem setup node 0 [0000000000000000-000000107fffffff]
[ 0.000000] NODE_DATA [0x0000107ffbd000-0x0000107ffc1fff]
[ 0.000000] Initmem setup node 1 [0000001080000000-000000207fffffff]
[ 0.000000] NODE_DATA [0x0000207ffbb000-0x0000207ffbffff]
[ 0.000000] Initmem setup node 2 [0000002080000000-000000307fffffff]
[ 0.000000] NODE_DATA [0x0000307ffbb000-0x0000307ffbffff]
[ 0.000000] Initmem setup node 3 [0000003080000000-000000407fffffff]
[ 0.000000] NODE_DATA [0x0000407ffbb000-0x0000407ffbffff]
[ 0.000000] Initmem setup node 4 [0000004080000000-000000507fffffff]
[ 0.000000] NODE_DATA [0x0000507ffbb000-0x0000507ffbffff]
[ 0.000000] Initmem setup node 5 [0000005080000000-000000607fffffff]
[ 0.000000] NODE_DATA [0x0000607ffbb000-0x0000607ffbffff]
[ 0.000000] Initmem setup node 6 [0000006080000000-000000707fffffff]
[ 0.000000] NODE_DATA [0x0000707ffbb000-0x0000707ffbffff]
[ 0.000000] Initmem setup node 7 [0000007080000000-000000807fffffff]
[ 0.000000] NODE_DATA [0x0000807ffba000-0x0000807ffbefff]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4D1933D1.9020609@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2010-12-28 00:48:17 +00:00
|
|
|
for_each_node_mask(i, node_possible_map)
|
2010-08-25 20:39:17 +00:00
|
|
|
memblock_x86_register_active_regions(i,
|
2009-01-06 02:39:01 +00:00
|
|
|
nodes[i].start >> PAGE_SHIFT,
|
|
|
|
nodes[i].end >> PAGE_SHIFT);
|
x86-64, numa: Put pgtable to local node memory
Introduce init_memory_mapping_high(), and use it with 64bit.
It will go with every memory segment above 4g to create page table to the
memory range itself.
before this patch all page tables was on one node.
with this patch, one RED-PEN is killed
debug out for 8 sockets system after patch
[ 0.000000] initial memory mapped : 0 - 20000000
[ 0.000000] init_memory_mapping: [0x00000000000000-0x0000007f74ffff]
[ 0.000000] 0000000000 - 007f600000 page 2M
[ 0.000000] 007f600000 - 007f750000 page 4k
[ 0.000000] kernel direct mapping tables up to 7f750000 @ [0x7f74c000-0x7f74ffff]
[ 0.000000] RAMDISK: 7bc84000 - 7f745000
....
[ 0.000000] Adding active range (0, 0x10, 0x95) 0 entries of 3200 used
[ 0.000000] Adding active range (0, 0x100, 0x7f750) 1 entries of 3200 used
[ 0.000000] Adding active range (0, 0x100000, 0x1080000) 2 entries of 3200 used
[ 0.000000] Adding active range (1, 0x1080000, 0x2080000) 3 entries of 3200 used
[ 0.000000] Adding active range (2, 0x2080000, 0x3080000) 4 entries of 3200 used
[ 0.000000] Adding active range (3, 0x3080000, 0x4080000) 5 entries of 3200 used
[ 0.000000] Adding active range (4, 0x4080000, 0x5080000) 6 entries of 3200 used
[ 0.000000] Adding active range (5, 0x5080000, 0x6080000) 7 entries of 3200 used
[ 0.000000] Adding active range (6, 0x6080000, 0x7080000) 8 entries of 3200 used
[ 0.000000] Adding active range (7, 0x7080000, 0x8080000) 9 entries of 3200 used
[ 0.000000] init_memory_mapping: [0x00000100000000-0x0000107fffffff]
[ 0.000000] 0100000000 - 1080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 1080000000 @ [0x107ffbd000-0x107fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x107ffc2000-0x107fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00001080000000-0x0000207fffffff]
[ 0.000000] 1080000000 - 2080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 2080000000 @ [0x207ff7d000-0x207fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x207ffc0000-0x207fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00002080000000-0x0000307fffffff]
[ 0.000000] 2080000000 - 3080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 3080000000 @ [0x307ff3d000-0x307fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x307ffc0000-0x307fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00003080000000-0x0000407fffffff]
[ 0.000000] 3080000000 - 4080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 4080000000 @ [0x407fefd000-0x407fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x407ffc0000-0x407fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00004080000000-0x0000507fffffff]
[ 0.000000] 4080000000 - 5080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 5080000000 @ [0x507febd000-0x507fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x507ffc0000-0x507fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00005080000000-0x0000607fffffff]
[ 0.000000] 5080000000 - 6080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 6080000000 @ [0x607fe7d000-0x607fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x607ffc0000-0x607fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00006080000000-0x0000707fffffff]
[ 0.000000] 6080000000 - 7080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 7080000000 @ [0x707fe3d000-0x707fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x707ffc0000-0x707fffffff] PGTABLE
[ 0.000000] init_memory_mapping: [0x00007080000000-0x0000807fffffff]
[ 0.000000] 7080000000 - 8080000000 page 2M
[ 0.000000] kernel direct mapping tables up to 8080000000 @ [0x807fdfc000-0x807fffffff]
[ 0.000000] memblock_x86_reserve_range: [0x807ffbf000-0x807fffffff] PGTABLE
[ 0.000000] Initmem setup node 0 [0000000000000000-000000107fffffff]
[ 0.000000] NODE_DATA [0x0000107ffbd000-0x0000107ffc1fff]
[ 0.000000] Initmem setup node 1 [0000001080000000-000000207fffffff]
[ 0.000000] NODE_DATA [0x0000207ffbb000-0x0000207ffbffff]
[ 0.000000] Initmem setup node 2 [0000002080000000-000000307fffffff]
[ 0.000000] NODE_DATA [0x0000307ffbb000-0x0000307ffbffff]
[ 0.000000] Initmem setup node 3 [0000003080000000-000000407fffffff]
[ 0.000000] NODE_DATA [0x0000407ffbb000-0x0000407ffbffff]
[ 0.000000] Initmem setup node 4 [0000004080000000-000000507fffffff]
[ 0.000000] NODE_DATA [0x0000507ffbb000-0x0000507ffbffff]
[ 0.000000] Initmem setup node 5 [0000005080000000-000000607fffffff]
[ 0.000000] NODE_DATA [0x0000607ffbb000-0x0000607ffbffff]
[ 0.000000] Initmem setup node 6 [0000006080000000-000000707fffffff]
[ 0.000000] NODE_DATA [0x0000707ffbb000-0x0000707ffbffff]
[ 0.000000] Initmem setup node 7 [0000007080000000-000000807fffffff]
[ 0.000000] NODE_DATA [0x0000807ffba000-0x0000807ffbefff]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4D1933D1.9020609@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2010-12-28 00:48:17 +00:00
|
|
|
init_memory_mapping_high();
|
2011-02-16 11:13:07 +00:00
|
|
|
for_each_node_mask(i, node_possible_map)
|
2009-01-06 02:39:01 +00:00
|
|
|
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
numa_init_array();
|
|
|
|
return 0;
|
2008-01-30 12:32:36 +00:00
|
|
|
}
|