#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <linux/acpi.h>
+#include <linux/nodemask.h>
#include <asm/srat.h>
+#include <asm/topology.h>
/*
* proximity macros and definitions
static int zholes_size_init;
static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
-extern unsigned long node_start_pfn[], node_end_pfn[];
-
extern void * boot_ioremap(unsigned long, unsigned long);
/* Identify CPU proximity domains */
"enabled and removable" : "enabled" ) );
}
-#if MAX_NR_ZONES != 3
-#error "MAX_NR_ZONES != 3, chunk_to_zone requires review"
+#if MAX_NR_ZONES != 4
+#error "MAX_NR_ZONES != 4, chunk_to_zone requires review"
#endif
/* Take a chunk of pages from page frame cstart to cend and count the number
* of pages in each zone, returned via zones[].
}
}
-static void __init initialize_physnode_map(void)
+/*
+ * The SRAT table always lists ascending addresses, so can always
+ * assume that the first "start" address that you see is the real
+ * start of the node, and that the current "end" address is after
+ * the previous one.
+ */
+static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_chunk)
{
- int i;
- unsigned long pfn;
- struct node_memory_chunk_s *nmcp;
-
- /* Run the list of memory chunks and fill in the phymap. */
- nmcp = node_memory_chunk;
- for (i = num_memory_chunks; --i >= 0; nmcp++) {
- for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
- pfn += PAGES_PER_ELEMENT)
- {
- physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
- }
+ /*
+ * Only add present memory as told by the e820.
+ * There is no guarantee from the SRAT that the memory it
+ * enumerates is present at boot time because it represents
+ * *possible* memory hotplug areas the same as normal RAM.
+ */
+ if (memory_chunk->start_pfn >= max_pfn) {
+ printk (KERN_INFO "Ignoring SRAT pfns: 0x%08lx -> %08lx\n",
+ memory_chunk->start_pfn, memory_chunk->end_pfn);
+ return;
}
+ if (memory_chunk->nid != nid)
+ return;
+
+ if (!node_has_online_mem(nid))
+ node_start_pfn[nid] = memory_chunk->start_pfn;
+
+ if (node_start_pfn[nid] > memory_chunk->start_pfn)
+ node_start_pfn[nid] = memory_chunk->start_pfn;
+
+ if (node_end_pfn[nid] < memory_chunk->end_pfn)
+ node_end_pfn[nid] = memory_chunk->end_pfn;
+}
+
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+ return pxm_to_nid_map[pxm];
}
/* Parse the ACPI Static Resource Affinity Table */
{
u8 *start, *end, *p;
int i, j, nid;
- u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
start = (u8 *)(&(sratp->reserved) + 1); /* skip header */
* a set of sequential node IDs starting at zero. (ACPI doesn't seem
* to specify the range of _PXM values.)
*/
- numnodes = 0; /* init total nodes in system */
+ /*
+ * MCD - we no longer HAVE to number nodes sequentially. PXM domain
+ * numbers could go as high as 256, and MAX_NUMNODES for i386 is typically
+ * 32, so we will continue numbering them in this manner until MAX_NUMNODES
+ * approaches MAX_PXM_DOMAINS for i386.
+ */
+ nodes_clear(node_online_map);
for (i = 0; i < MAX_PXM_DOMAINS; i++) {
if (BMAP_TEST(pxm_bitmap, i)) {
- pxm_to_nid_map[i] = numnodes;
- nid_to_pxm_map[numnodes] = i;
- node_set_online(numnodes);
- ++numnodes;
+ nid = num_online_nodes();
+ pxm_to_nid_map[i] = nid;
+ nid_to_pxm_map[nid] = i;
+ node_set_online(nid);
}
}
-
- if (numnodes == 0)
- BUG();
+ BUG_ON(num_online_nodes() == 0);
/* set cnode id in memory chunk structure */
for (i = 0; i < num_memory_chunks; i++)
node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
- initialize_physnode_map();
-
printk("pxm bitmap: ");
for (i = 0; i < sizeof(pxm_bitmap); i++) {
printk("%02X ", pxm_bitmap[i]);
}
printk("\n");
- printk("Number of logical nodes in system = %d\n", numnodes);
+ printk("Number of logical nodes in system = %d\n", num_online_nodes());
printk("Number of memory chunks in system = %d\n", num_memory_chunks);
for (j = 0; j < num_memory_chunks; j++){
+ struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
- j, node_memory_chunk[j].nid,
- node_memory_chunk[j].start_pfn,
- node_memory_chunk[j].end_pfn);
+ j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
+ node_read_chunk(chunk->nid, chunk);
}
- /*calculate node_start_pfn/node_end_pfn arrays*/
- for (nid = 0; nid < numnodes; nid++) {
- int been_here_before = 0;
-
- for (j = 0; j < num_memory_chunks; j++){
- if (node_memory_chunk[j].nid == nid) {
- if (been_here_before == 0) {
- node_start_pfn[nid] = node_memory_chunk[j].start_pfn;
- node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
- been_here_before = 1;
- } else { /* We've found another chunk of memory for the node */
- if (node_start_pfn[nid] < node_memory_chunk[j].start_pfn) {
- node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
- }
- }
- }
- }
+ 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;
out_fail:
int tables = 0;
int i = 0;
- acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, rsdp_address);
+ if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING,
+ rsdp_address))) {
+ printk("%s: System description tables not found\n",
+ __FUNCTION__);
+ goto out_err;
+ }
if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) {
printk("%s: assigning address to rsdp\n", __FUNCTION__);
int first;
unsigned long end = 0;
- for (nid = 0; nid < numnodes; nid++) {
+ for_each_online_node(nid) {
first = 1;
for (c = 0; c < num_memory_chunks; c++){
if (node_memory_chunk[c].nid == nid) {
zholes_size_init++;
get_zholes_init();
}
- if((nid >= numnodes) | (nid >= MAX_NUMNODES))
- printk("%s: nid = %d is invalid. numnodes = %d",
- __FUNCTION__, nid, numnodes);
+ if (nid >= MAX_NUMNODES || !node_online(nid))
+ printk("%s: nid = %d is invalid/offline. num_online_nodes = %d",
+ __FUNCTION__, nid, num_online_nodes());
return &zholes_size[nid * MAX_NR_ZONES];
}