/* Callback for Proximity Domain -> ACPI processor UID mapping */ void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { int pxm, node; if (srat_disabled()) return; if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) { pr_err("SRAT: Invalid SRAT header length: %d\n", pa->header.length); bad_srat(); return; } if (!(pa->flags & ACPI_SRAT_GICC_ENABLED)) return; pxm = pa->proximity_domain; node = acpi_map_pxm_to_node(pxm); if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) { pr_err("SRAT: Too many proximity domains %d\n", pxm); bad_srat(); return; } node_set(node, numa_nodes_parsed); }
int acpi_get_node(acpi_handle *handle) { int pxm, node = -1; pxm = acpi_get_pxm(handle); if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) node = acpi_map_pxm_to_node(pxm); return node; }
int acpi_get_node(acpi_handle *handle) { int pxm, node = -1; pxm = acpi_get_pxm(handle); if (pxm >= 0) node = acpi_map_pxm_to_node(pxm); return node; }
static __cpuinit int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA int pxm_id; int nid; pxm_id = acpi_get_pxm(handle); nid = acpi_map_pxm_to_node(pxm_id); node_cpuid[cpu].phys_id = physid; node_cpuid[cpu].nid = nid; #endif return (0); }
/** * acpi_map_pxm_to_online_node - Map proximity ID to online node * @pxm: ACPI proximity ID * * This is similar to acpi_map_pxm_to_node(), but always returns an online * node. When the mapped node from a given proximity ID is offline, it * looks up the node distance table and returns the nearest online node. * * ACPI device drivers, which are called after the NUMA initialization has * completed in the kernel, can call this interface to obtain their device * NUMA topology from ACPI tables. Such drivers do not have to deal with * offline nodes. A node may be offline when a device proximity ID is * unique, SRAT memory entry does not exist, or NUMA is disabled, ex. * "numa=off" on x86. */ int acpi_map_pxm_to_online_node(int pxm) { int node, n, dist, min_dist; node = acpi_map_pxm_to_node(pxm); if (node == NUMA_NO_NODE) node = 0; if (!node_online(node)) { min_dist = INT_MAX; for_each_online_node(n) { dist = node_distance(node, n); if (dist < min_dist) { min_dist = dist; node = n; } } }
static int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid) { #ifdef CONFIG_ACPI_NUMA int pxm_id; int nid; pxm_id = acpi_get_pxm(handle); /* * We don't have cpu-only-node hotadd. But if the system equips * SRAT table, pxm is already found and node is ready. * So, just pxm_to_nid(pxm) is OK. * This code here is for the system which doesn't have full SRAT * table for possible cpus. */ nid = acpi_map_pxm_to_node(pxm_id); node_cpuid[cpu].phys_id = physid; node_cpuid[cpu].nid = nid; #endif return (0); }
int __init get_memcfg_from_srat(void) { int i, j, nid; if (srat_disabled()) goto out_fail; if (acpi_numa_init() < 0) goto out_fail; if (num_memory_chunks == 0) { printk(KERN_DEBUG "could not find any ACPI SRAT memory areas.\n"); goto out_fail; } /* Calculate total number of nodes in system from PXM bitmap and create * a set of sequential node IDs starting at zero. (ACPI doesn't seem * to specify the range of _PXM values.) */ /* * 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)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } 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_node(node_memory_chunk[i].pxm); printk(KERN_DEBUG "pxm bitmap: "); for (i = 0; i < sizeof(pxm_bitmap); i++) { printk(KERN_CONT "%02x ", pxm_bitmap[i]); } printk(KERN_CONT "\n"); printk(KERN_DEBUG "Number of logical nodes in system = %d\n", num_online_nodes()); printk(KERN_DEBUG "Number of memory chunks in system = %d\n", num_memory_chunks); for (i = 0; i < MAX_LOCAL_APIC; i++) set_apicid_to_node(i, pxm_to_node(apicid_to_pxm[i])); for (j = 0; j < num_memory_chunks; j++){ struct node_memory_chunk_s * chunk = &node_memory_chunk[j]; printk(KERN_DEBUG "chunk %d nid %d start_pfn %08lx end_pfn %08lx\n", j, chunk->nid, chunk->start_pfn, chunk->end_pfn); if (node_read_chunk(chunk->nid, chunk)) continue; memblock_x86_register_active_regions(chunk->nid, chunk->start_pfn, min(chunk->end_pfn, max_pfn)); } /* for out of order entries in SRAT */ sort_node_map(); for_each_online_node(nid) { unsigned long start = node_start_pfn[nid]; unsigned long end = min(node_end_pfn[nid], max_pfn); memory_present(nid, start, end); node_remap_size[nid] = node_memmap_size_bytes(nid, start, end); } return 1; out_fail: printk(KERN_DEBUG "failed to get NUMA memory information from SRAT" " table\n"); return 0; }
static __init int setup_node(int pxm) { return acpi_map_pxm_to_node(pxm); }
void __init acpi_numa_arch_fixup(void) { int i, j, node_from, node_to; /* If there's no SRAT, fix the phys_id and mark node 0 online */ if (srat_num_cpus == 0) { node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } /* * MCD - This can probably be dropped now. No need for pxm ID to node ID * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES. */ nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } /* set logical node id in memory chunk structure */ for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); /* assign memory bank numbers for each chunk on each node */ for_each_online_node(i) { int bank; bank = 0; for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } /* set logical node id in cpu structure */ for_each_possible_early_cpu(i) node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) return; memset(numa_slit, -1, sizeof(numa_slit)); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); for (j = 0; j < slit_table->locality_count; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->locality_count + j]; } } #ifdef SLIT_DEBUG printk("ACPI 2.0 SLIT locality table:\n"); for_each_online_node(i) { for_each_online_node(j) printk("%03d ", node_distance(i, j)); printk("\n"); } #endif }
/* Parse the ACPI Static Resource Affinity Table */ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) { u8 *start, *end, *p; int i, j, nid; start = (u8 *)(&(sratp->reserved) + 1); /* skip header */ p = start; end = (u8 *)sratp + sratp->header.length; memset(pxm_bitmap, 0, sizeof(pxm_bitmap)); /* init proximity domain bitmap */ memset(node_memory_chunk, 0, sizeof(node_memory_chunk)); num_memory_chunks = 0; while (p < end) { switch (*p) { case ACPI_SRAT_TYPE_CPU_AFFINITY: parse_cpu_affinity_structure(p); break; case ACPI_SRAT_TYPE_MEMORY_AFFINITY: parse_memory_affinity_structure(p); break; default: printk("ACPI 2.0 SRAT: unknown entry skipped: type=0x%02X, len=%d\n", p[0], p[1]); break; } p += p[1]; if (p[1] == 0) { printk("acpi20_parse_srat: Entry length value is zero;" " can't parse any further!\n"); break; } } if (num_memory_chunks == 0) { printk("could not finy any ACPI SRAT memory areas.\n"); goto out_fail; } /* Calculate total number of nodes in system from PXM bitmap and create * a set of sequential node IDs starting at zero. (ACPI doesn't seem * to specify the range of _PXM values.) */ /* * 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)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } 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_node(node_memory_chunk[i].pxm); 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", num_online_nodes()); printk("Number of memory chunks in system = %d\n", num_memory_chunks); for (i = 0; i < MAX_APICID; i++) apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]); 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, chunk->nid, chunk->start_pfn, chunk->end_pfn); node_read_chunk(chunk->nid, chunk); add_active_range(chunk->nid, chunk->start_pfn, chunk->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: return 0; }
void __init acpi_numa_arch_fixup(void) { int i, j, node_from, node_to; if (srat_num_cpus == 0) { node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); for_each_online_node(i) { int bank; bank = 0; for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } for_each_possible_early_cpu(i) node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) { for (i = 0; i < MAX_NUMNODES; i++) for (j = 0; j < MAX_NUMNODES; j++) node_distance(i, j) = i == j ? LOCAL_DISTANCE : REMOTE_DISTANCE; return; } memset(numa_slit, -1, sizeof(numa_slit)); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); for (j = 0; j < slit_table->locality_count; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->locality_count + j]; } } #ifdef SLIT_DEBUG printk("ACPI 2.0 SLIT locality table:\n"); for_each_online_node(i) { for_each_online_node(j) printk("%03d ", node_distance(i, j)); printk("\n"); } #endif }