From ac906a6d56b742e13f9e600c7c7879b323cfbf15 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:31 -0700 Subject: [PATCH 01/15] ACPI / NUMA: Use pr_fmt() instead of printk Just do some cleanups to replace printk with pr_fmt(). Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index d176e0ece470..bdb762239b36 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -18,6 +18,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * */ + +#define pr_fmt(fmt) "ACPI: " fmt + #include #include #include @@ -28,8 +31,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_NUMA 0x80000000 #define _COMPONENT ACPI_NUMA ACPI_MODULE_NAME("numa"); @@ -187,9 +188,8 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) #endif /* ACPI_DEBUG_OUTPUT */ break; default: - printk(KERN_WARNING PREFIX - "Found unsupported SRAT entry (type = 0x%x)\n", - header->type); + pr_warn("Found unsupported SRAT entry (type = 0x%x)\n", + header->type); break; } } @@ -222,7 +222,7 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) struct acpi_table_slit *slit = (struct acpi_table_slit *)table; if (!slit_valid(slit)) { - printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); + pr_info("SLIT table looks invalid. Not used.\n"); return -EINVAL; } acpi_numa_slit_init(slit); @@ -233,12 +233,9 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) void __init __weak acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) { - printk(KERN_WARNING PREFIX - "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); - return; + pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); } - static int __init acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, const unsigned long end) From 3dda448189af1c55637628423487f607244fb669 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:32 -0700 Subject: [PATCH 02/15] ACPI / NUMA: Replace ACPI_DEBUG_PRINT() with pr_debug() ACPI_DEBUG_PRINT is a bit fragile in acpi/numa.c, the first thing is that component ACPI_NUMA(0x80000000) is not described in the Documentation/acpi/debug.txt, and even not defined in the struct acpi_dlayer acpi_debug_layers which we can not dynamically enable/disable it with /sys/modules/acpi/parameters/debug_layer. another thing is that ACPI_DEBUG_OUTPUT is controlled by ACPICA which not coordinate well with ACPI drivers. Replace ACPI_DEBUG_PRINT() with pr_debug() in this patch as pr_debug will do the same thing for debug purpose and it can make the code much cleaner, also remove the related code which not needed anymore if ACPI_DEBUG_PRINT() is gone. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 59 ++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index bdb762239b36..a089c396566d 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -31,10 +31,6 @@ #include #include -#define ACPI_NUMA 0x80000000 -#define _COMPONENT ACPI_NUMA -ACPI_MODULE_NAME("numa"); - static nodemask_t nodes_found_map = NODE_MASK_NONE; /* maps to convert between proximity domain and logical node ID */ @@ -129,64 +125,51 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node); static void __init acpi_table_print_srat_entry(struct acpi_subtable_header *header) { - - ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); - if (!header) return; switch (header->type) { - case ACPI_SRAT_TYPE_CPU_AFFINITY: -#ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_cpu_affinity *p = (struct acpi_srat_cpu_affinity *)header; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", - p->apic_id, p->local_sapic_eid, - p->proximity_domain_lo, - (p->flags & ACPI_SRAT_CPU_ENABLED)? - "enabled" : "disabled")); + pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", + p->apic_id, p->local_sapic_eid, + p->proximity_domain_lo, + (p->flags & ACPI_SRAT_CPU_ENABLED) ? + "enabled" : "disabled"); } -#endif /* ACPI_DEBUG_OUTPUT */ break; case ACPI_SRAT_TYPE_MEMORY_AFFINITY: -#ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", - (unsigned long)p->base_address, - (unsigned long)p->length, - p->proximity_domain, - (p->flags & ACPI_SRAT_MEM_ENABLED)? - "enabled" : "disabled", - (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? - " hot-pluggable" : "", - (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)? - " non-volatile" : "")); + pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", + (unsigned long)p->base_address, + (unsigned long)p->length, + p->proximity_domain, + (p->flags & ACPI_SRAT_MEM_ENABLED) ? + "enabled" : "disabled", + (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? + " hot-pluggable" : "", + (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ? + " non-volatile" : ""); } -#endif /* ACPI_DEBUG_OUTPUT */ break; case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: -#ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_x2apic_cpu_affinity *p = (struct acpi_srat_x2apic_cpu_affinity *)header; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Processor (x2apicid[0x%08x]) in" - " proximity domain %d %s\n", - p->apic_id, - p->proximity_domain, - (p->flags & ACPI_SRAT_CPU_ENABLED) ? - "enabled" : "disabled")); + pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n", + p->apic_id, + p->proximity_domain, + (p->flags & ACPI_SRAT_CPU_ENABLED) ? + "enabled" : "disabled"); } -#endif /* ACPI_DEBUG_OUTPUT */ break; + default: pr_warn("Found unsupported SRAT entry (type = 0x%x)\n", header->type); From 258cb74ba5d16265b0e96225c06bc41cd53b9e61 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:33 -0700 Subject: [PATCH 03/15] ACPI / NUMA: remove duplicate NULL check The argument "header" for acpi_table_print_srat_entry() is always checked before the function is called, it's duplicate to check it again, remove it. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index a089c396566d..6f1cad8d22a3 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -125,9 +125,6 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node); static void __init acpi_table_print_srat_entry(struct acpi_subtable_header *header) { - if (!header) - return; - switch (header->type) { case ACPI_SRAT_TYPE_CPU_AFFINITY: { From 312521d0543513f37f0badb4efc7bfed2d99672e Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 24 May 2016 15:35:34 -0700 Subject: [PATCH 04/15] ACPI / NUMA: Move acpi_numa_arch_fixup() to ia64 only Since acpi_numa_arch_fixup() is only used in arch ia64, move it there to make a generic interface easier. This avoids empty function stubs or some complex kconfig options for x86 and arm64. Signed-off-by: Robert Richter Reviewed-by: Hanjun Guo Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/ia64/include/asm/acpi.h | 3 +++ arch/ia64/kernel/acpi.c | 2 +- arch/ia64/kernel/setup.c | 1 + arch/x86/mm/srat.c | 2 -- drivers/acpi/numa.c | 2 -- include/linux/acpi.h | 1 - 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index aa0fdf125aba..a3d0211970e9 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -140,6 +140,9 @@ static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus) } } } + +extern void acpi_numa_fixup(void); + #endif /* CONFIG_ACPI_NUMA */ #endif /*__KERNEL__*/ diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index b1698bc042c8..92b7bc956795 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -524,7 +524,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) return 0; } -void __init acpi_numa_arch_fixup(void) +void __init acpi_numa_fixup(void) { int i, j, node_from, node_to; diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 2029a38a72ae..afddb3e80a29 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -552,6 +552,7 @@ setup_arch (char **cmdline_p) early_acpi_boot_init(); # ifdef CONFIG_ACPI_NUMA acpi_numa_init(); + acpi_numa_fixup(); # ifdef CONFIG_ACPI_HOTPLUG_CPU prefill_possible_map(); # endif diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index b5f821881465..90b6ed9a00dc 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -212,8 +212,6 @@ out_err: return -1; } -void __init acpi_numa_arch_fixup(void) {} - int __init x86_acpi_numa_init(void) { int ret; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 6f1cad8d22a3..fb2c0d61f252 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -324,8 +324,6 @@ int __init acpi_numa_init(void) /* SLIT: System Locality Information Table */ acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); - acpi_numa_arch_fixup(); - if (cnt < 0) return cnt; else if (!parsed_numa_memblks) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5294f5..8010b266e856 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -237,7 +237,6 @@ void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); -void acpi_numa_arch_fixup(void); #ifndef PHYS_CPUID_INVALID typedef u32 phys_cpuid_t; From 6525afdf53b39968f1a109b1ce1607ca6c98d300 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:35 -0700 Subject: [PATCH 05/15] ACPI / NUMA: move acpi_numa_slit_init() to drivers/acpi/numa.c Identical implementations of acpi_numa_slit_init() are used by both x86 and follow-on arm64 support. Move it to drivers/acpi/numa.c, and guard with CONFIG_X86 || CONFIG_ARM64 because ia64 has its own architecture specific implementation. No code change. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/x86/mm/srat.c | 27 --------------------------- drivers/acpi/numa.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 90b6ed9a00dc..f242a11df488 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -42,33 +42,6 @@ static __init inline int srat_disabled(void) return acpi_numa < 0; } -/* - * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for - * I/O localities since SRAT does not list them. I/O localities are - * not supported at this point. - */ -void __init acpi_numa_slit_init(struct acpi_table_slit *slit) -{ - int i, j; - - for (i = 0; i < slit->locality_count; i++) { - const int from_node = pxm_to_node(i); - - if (from_node == NUMA_NO_NODE) - continue; - - for (j = 0; j < slit->locality_count; j++) { - const int to_node = pxm_to_node(j); - - if (to_node == NUMA_NO_NODE) - continue; - - numa_set_distance(from_node, to_node, - slit->entry[slit->locality_count * i + j]); - } - } -} - /* Callback for Proximity Domain -> x2APIC mapping */ void __init acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index fb2c0d61f252..7e0649d11da2 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -197,6 +197,35 @@ static int __init slit_valid(struct acpi_table_slit *slit) return 1; } +#if defined(CONFIG_X86) || defined(CONFIG_ARM64) +/* + * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for + * I/O localities since SRAT does not list them. I/O localities are + * not supported at this point. + */ +void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +{ + int i, j; + + for (i = 0; i < slit->locality_count; i++) { + const int from_node = pxm_to_node(i); + + if (from_node == NUMA_NO_NODE) + continue; + + for (j = 0; j < slit->locality_count; j++) { + const int to_node = pxm_to_node(j); + + if (to_node == NUMA_NO_NODE) + continue; + + numa_set_distance(from_node, to_node, + slit->entry[slit->locality_count * i + j]); + } + } +} +#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ + static int __init acpi_parse_slit(struct acpi_table_header *table) { struct acpi_table_slit *slit = (struct acpi_table_slit *)table; From 8ccbbdaa2bc06f7b11fec7f44bf2501786a189ba Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:36 -0700 Subject: [PATCH 06/15] arm64, NUMA: rework numa_add_memblk() Rework numa_add_memblk() to update the parameter "u64 size" to "u64 end", this will make it consistent with x86 and simplifies the arm64 ACPI NUMA code to be added later. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Acked-by: Catalin Marinas Signed-off-by: Rafael J. Wysocki --- arch/arm64/mm/numa.c | 12 ++++++------ drivers/of/of_numa.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 98dc1047f2a2..6cb03f9c904d 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -131,25 +131,25 @@ void __init early_map_cpu_to_node(unsigned int cpu, int nid) * numa_add_memblk - Set node id to memblk * @nid: NUMA node ID of the new memblk * @start: Start address of the new memblk - * @size: Size of the new memblk + * @end: End address of the new memblk * * RETURNS: * 0 on success, -errno on failure. */ -int __init numa_add_memblk(int nid, u64 start, u64 size) +int __init numa_add_memblk(int nid, u64 start, u64 end) { int ret; - ret = memblock_set_node(start, size, &memblock.memory, nid); + ret = memblock_set_node(start, (end - start), &memblock.memory, nid); if (ret < 0) { pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n", - start, (start + size - 1), nid); + start, (end - 1), nid); return ret; } node_set(nid, numa_nodes_parsed); pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n", - start, (start + size - 1), nid); + start, (end - 1), nid); return ret; } @@ -367,7 +367,7 @@ static int __init dummy_numa_init(void) 0LLU, PFN_PHYS(max_pfn) - 1); for_each_memblock(memory, mblk) { - ret = numa_add_memblk(0, mblk->base, mblk->size); + ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size); if (!ret) continue; diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c index 0f2784bc1874..ed5a097f0801 100644 --- a/drivers/of/of_numa.c +++ b/drivers/of/of_numa.c @@ -91,8 +91,8 @@ static int __init of_numa_parse_memory_nodes(void) pr_debug("NUMA: base = %llx len = %llx, node = %u\n", rsrc.start, rsrc.end - rsrc.start + 1, nid); - r = numa_add_memblk(nid, rsrc.start, - rsrc.end - rsrc.start + 1); + + r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1); if (r) break; } From 34c333705238dcc82aa758ef1fbb002dbcd76414 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 24 May 2016 15:35:37 -0700 Subject: [PATCH 07/15] arm64, NUMA: Cleanup NUMA disabled messages As noted by Dennis Chen, we don't want to print "No NUMA configuration found" if NUMA was forced off from the command line. Change the type of numa_off to bool, and clean up printing code. Print "NUMA disabled" if forced off on command line and "No NUMA configuration found" if there was no firmware NUMA information. Signed-off-by: David Daney Acked-by: Catalin Marinas Reviewed-by: Dennis Chen Signed-off-by: Rafael J. Wysocki --- arch/arm64/mm/numa.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 6cb03f9c904d..1def1de51578 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -29,7 +29,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE }; static int numa_distance_cnt; static u8 *numa_distance; -static int numa_off; +static bool numa_off; static __init int numa_parse_early_param(char *opt) { @@ -37,7 +37,7 @@ static __init int numa_parse_early_param(char *opt) return -EINVAL; if (!strncmp(opt, "off", 3)) { pr_info("%s\n", "NUMA turned off"); - numa_off = 1; + numa_off = true; } return 0; } @@ -362,7 +362,10 @@ static int __init dummy_numa_init(void) int ret; struct memblock_region *mblk; - pr_info("%s\n", "No NUMA configuration found"); + if (numa_off) + pr_info("NUMA disabled\n"); /* Forced off on command line. */ + else + pr_info("No NUMA configuration found\n"); pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n", 0LLU, PFN_PHYS(max_pfn) - 1); @@ -375,7 +378,7 @@ static int __init dummy_numa_init(void) return ret; } - numa_off = 1; + numa_off = true; return 0; } From 2faeff1d507c21d262e8afca862243909970d567 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:38 -0700 Subject: [PATCH 08/15] x86 / ACPI / NUMA: cleanup acpi_numa_processor_affinity_init() Cleanup acpi_numa_processor_affinity_init() in preparation for its move to drivers/acpi/numa.c. It will be reused by arm64, this has no functional change. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/x86/mm/srat.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index f242a11df488..9e2a833b54fb 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -26,11 +26,6 @@ int acpi_numa __initdata; -static __init int setup_node(int pxm) -{ - return acpi_map_pxm_to_node(pxm); -} - static __init void bad_srat(void) { printk(KERN_ERR "SRAT: SRAT not used.\n"); @@ -64,7 +59,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) pxm, apic_id); return; } - node = setup_node(pxm); + node = acpi_map_pxm_to_node(pxm); if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); bad_srat(); @@ -100,7 +95,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) pxm = pa->proximity_domain_lo; if (acpi_srat_revision >= 2) pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8; - node = setup_node(pxm); + node = acpi_map_pxm_to_node(pxm); if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); bad_srat(); @@ -124,12 +119,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) pxm, apic_id, node); } -#ifdef CONFIG_MEMORY_HOTPLUG -static inline int save_add_info(void) {return 1;} -#else -static inline int save_add_info(void) {return 0;} -#endif - /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) @@ -145,7 +134,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) goto out_err; hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; - if (hotpluggable && !save_add_info()) + if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) goto out_err; start = ma->base_address; @@ -154,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (acpi_srat_revision <= 1) pxm &= 0xff; - node = setup_node(pxm); + node = acpi_map_pxm_to_node(pxm); if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains.\n"); goto out_err_bad_srat; @@ -182,7 +171,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) out_err_bad_srat: bad_srat(); out_err: - return -1; + return -EINVAL; } int __init x86_acpi_numa_init(void) From e84025e274e66986277e11f0dda03373e246ffad Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 24 May 2016 15:35:39 -0700 Subject: [PATCH 09/15] ACPI / NUMA: move bad_srat() and srat_disabled() to drivers/acpi/numa.c bad_srat() and srat_disabled() are shared by x86 and follow-on arm64 patches. Move them to drivers/acpi/numa.c in preparation for arm64 support. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter [david.daney@cavium.com moved definitions to drivers/acpi/numa.c] Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/acpi.h | 1 - arch/x86/mm/numa.c | 2 +- arch/x86/mm/srat.c | 13 ------------- drivers/acpi/numa.c | 12 ++++++++++++ include/acpi/acpi_numa.h | 4 ++++ 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 94c18ebfd68c..65f1e95cade9 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -145,7 +145,6 @@ static inline void disable_acpi(void) { } #define ARCH_HAS_POWER_INIT 1 #ifdef CONFIG_ACPI_NUMA -extern int acpi_numa; extern int x86_acpi_numa_init(void); #endif /* CONFIG_ACPI_NUMA */ diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 9c086c57105c..968ac028c34e 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -1,4 +1,5 @@ /* Common code for 32 and 64-bit NUMA */ +#include #include #include #include @@ -15,7 +16,6 @@ #include #include #include -#include #include #include "numa_internal.h" diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 9e2a833b54fb..4217071fb4d2 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -24,19 +24,6 @@ #include #include -int acpi_numa __initdata; - -static __init void bad_srat(void) -{ - printk(KERN_ERR "SRAT: SRAT not used.\n"); - acpi_numa = -1; -} - -static __init inline int srat_disabled(void) -{ - return acpi_numa < 0; -} - /* Callback for Proximity Domain -> x2APIC mapping */ void __init acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 7e0649d11da2..af0c8d5c845b 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -40,6 +40,7 @@ static int node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; unsigned char acpi_srat_revision __initdata; +int acpi_numa __initdata; int pxm_to_node(int pxm) { @@ -197,6 +198,17 @@ static int __init slit_valid(struct acpi_table_slit *slit) return 1; } +void __init bad_srat(void) +{ + pr_err("SRAT: SRAT not used.\n"); + acpi_numa = -1; +} + +int __init srat_disabled(void) +{ + return acpi_numa < 0; +} + #if defined(CONFIG_X86) || defined(CONFIG_ARM64) /* * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index 94a37cd7fbda..d4b72944ccda 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h @@ -15,6 +15,10 @@ extern int pxm_to_node(int); extern int node_to_pxm(int); extern int acpi_map_pxm_to_node(int); extern unsigned char acpi_srat_revision; +extern int acpi_numa __initdata; + +extern void bad_srat(void); +extern int srat_disabled(void); #endif /* CONFIG_ACPI_NUMA */ #endif /* __ACP_NUMA_H */ From fb1f4181cef6ca15840164a5bd41f3dc4cb4f88d Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:40 -0700 Subject: [PATCH 10/15] ACPI / NUMA: remove unneeded acpi_numa=1 acpi_numa is default to 0, it's set to -1 when disable acpi numa or when a bad SRAT is parsed, and it's only consumed in srat_disabled() (compare it with 0) to continue parse the SRAT or not, so we don't need to set acpi_numa to 1 when we get a valid SRAT entry. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/x86/mm/srat.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 4217071fb4d2..30460f57b7f3 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -59,7 +59,6 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) } set_apicid_to_node(apic_id, node); node_set(node, numa_nodes_parsed); - acpi_numa = 1; printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", pxm, apic_id, node); } @@ -101,7 +100,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) set_apicid_to_node(apic_id, node); node_set(node, numa_nodes_parsed); - acpi_numa = 1; printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", pxm, apic_id, node); } From 3770442e79380cf105c8e272622c565cf63524d6 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:41 -0700 Subject: [PATCH 11/15] ACPI / NUMA: Move acpi_numa_memory_affinity_init() to drivers/acpi/numa.c acpi_numa_memory_affinity_init() will be reused by arm64. Move it to drivers/acpi/numa.c to facilitate reuse. No code change. Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- arch/x86/mm/srat.c | 57 ------------------------------------------ drivers/acpi/numa.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 30460f57b7f3..b1ecff460a46 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -15,8 +15,6 @@ #include #include #include -#include -#include #include #include #include @@ -104,61 +102,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) pxm, apic_id, node); } -/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ -int __init -acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) -{ - u64 start, end; - u32 hotpluggable; - int node, pxm; - - if (srat_disabled()) - goto out_err; - if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) - goto out_err_bad_srat; - if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) - goto out_err; - hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; - if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) - goto out_err; - - start = ma->base_address; - end = start + ma->length; - pxm = ma->proximity_domain; - if (acpi_srat_revision <= 1) - pxm &= 0xff; - - node = acpi_map_pxm_to_node(pxm); - if (node < 0) { - printk(KERN_ERR "SRAT: Too many proximity domains.\n"); - goto out_err_bad_srat; - } - - if (numa_add_memblk(node, start, end) < 0) - goto out_err_bad_srat; - - node_set(node, numa_nodes_parsed); - - pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n", - node, pxm, - (unsigned long long) start, (unsigned long long) end - 1, - hotpluggable ? " hotplug" : "", - ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : ""); - - /* Mark hotplug range in memblock. */ - if (hotpluggable && memblock_mark_hotplug(start, ma->length)) - pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n", - (unsigned long long)start, (unsigned long long)end - 1); - - max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1)); - - return 0; -out_err_bad_srat: - bad_srat(); -out_err: - return -EINVAL; -} - int __init x86_acpi_numa_init(void) { int ret; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index af0c8d5c845b..811f90a70eab 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -236,6 +238,64 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) } } } + +/* + * Default callback for parsing of the Proximity Domain <-> Memory + * Area mappings + */ +int __init +acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +{ + u64 start, end; + u32 hotpluggable; + int node, pxm; + + if (srat_disabled()) + goto out_err; + if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) + goto out_err_bad_srat; + if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) + goto out_err; + hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; + if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) + goto out_err; + + start = ma->base_address; + end = start + ma->length; + pxm = ma->proximity_domain; + if (acpi_srat_revision <= 1) + pxm &= 0xff; + + node = acpi_map_pxm_to_node(pxm); + if (node < 0) { + printk(KERN_ERR "SRAT: Too many proximity domains.\n"); + goto out_err_bad_srat; + } + + if (numa_add_memblk(node, start, end) < 0) + goto out_err_bad_srat; + + node_set(node, numa_nodes_parsed); + + pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n", + node, pxm, + (unsigned long long) start, (unsigned long long) end - 1, + hotpluggable ? " hotplug" : "", + ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : ""); + + /* Mark hotplug range in memblock. */ + if (hotpluggable && memblock_mark_hotplug(start, ma->length)) + pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n", + (unsigned long long)start, (unsigned long long)end - 1); + + max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1)); + + return 0; +out_err_bad_srat: + bad_srat(); +out_err: + return -EINVAL; +} #endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ static int __init acpi_parse_slit(struct acpi_table_header *table) From e0af261a437db4f4b21478ac677ccca5fc0ec07e Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 24 May 2016 15:35:42 -0700 Subject: [PATCH 12/15] ACPI / NUMA: Improve SRAT error detection and add messages Loosely based on code from Robert Richter and Hanjun Guo. Improve out of range node detection as well as allow for Larger SRAT entities. Add printing of nice messages. Signed-off-by: David Daney Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 811f90a70eab..fad6d288117f 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -252,8 +252,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (srat_disabled()) goto out_err; - if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) + if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) { + pr_err("SRAT: Unexpected header length: %d\n", + ma->header.length); goto out_err_bad_srat; + } if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) goto out_err; hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; @@ -267,13 +270,17 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) pxm &= 0xff; node = acpi_map_pxm_to_node(pxm); - if (node < 0) { - printk(KERN_ERR "SRAT: Too many proximity domains.\n"); + if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) { + pr_err("SRAT: Too many proximity domains.\n"); goto out_err_bad_srat; } - if (numa_add_memblk(node, start, end) < 0) + if (numa_add_memblk(node, start, end) < 0) { + pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n", + node, (unsigned long long) start, + (unsigned long long) end - 1); goto out_err_bad_srat; + } node_set(node, numa_nodes_parsed); From fb7c2bae8a479e388a1f664e32d6ddca55c7a249 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 24 May 2016 15:35:43 -0700 Subject: [PATCH 13/15] ACPI / processor: Add acpi_map_madt_entry() Follow-on arm64 ACPI/NUMA patches need to map MADT entries very early (before kmalloc is usable). Add acpi_map_madt_entry() which, indirectly, uses early_memremap()/early_memunmap() to access the table and parse out the mpidr. The existing implementation of map_madt_entry() is modified to take a pointer to the MADT as a parameter and the callers adjusted. Signed-off-by: David Daney Acked-by: Catalin Marinas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_core.c | 26 ++++++++++++++++++++++---- include/acpi/processor.h | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 33a38d604630..9125d7d96372 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -108,13 +108,12 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry, return -EINVAL; } -static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) +static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, + int type, u32 acpi_id) { unsigned long madt_end, entry; phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ - struct acpi_table_madt *madt; - madt = get_madt_table(); if (!madt) return phys_id; @@ -145,6 +144,25 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) return phys_id; } +phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id) +{ + struct acpi_table_madt *madt = NULL; + acpi_size tbl_size; + phys_cpuid_t rv; + + acpi_get_table_with_size(ACPI_SIG_MADT, 0, + (struct acpi_table_header **)&madt, + &tbl_size); + if (!madt) + return PHYS_CPUID_INVALID; + + rv = map_madt_entry(madt, 1, acpi_id); + + early_acpi_os_unmap_memory(madt, tbl_size); + + return rv; +} + static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -185,7 +203,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) phys_id = map_mat_entry(handle, type, acpi_id); if (invalid_phys_cpuid(phys_id)) - phys_id = map_madt_entry(type, acpi_id); + phys_id = map_madt_entry(get_madt_table(), type, acpi_id); return phys_id; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 6f1805dd5d3c..f473e6618339 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -309,6 +309,7 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) /* in processor_core.c */ phys_cpuid_t acpi_get_phys_id(acpi_handle, int type, u32 acpi_id); +phys_cpuid_t acpi_map_madt_entry(u32 acpi_id); int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id); int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id); From d8b47fca8c233642d1a20fa4025579ebc8be6f1e Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 24 May 2016 15:35:44 -0700 Subject: [PATCH 14/15] arm64, ACPI, NUMA: NUMA support based on SRAT and SLIT Introduce a new file to hold ACPI based NUMA information parsing from SRAT and SLIT. SRAT includes the CPU ACPI ID to Proximity Domain mappings and memory ranges to Proximity Domain mapping. SLIT has the information of inter node distances(relative number for access latency). Signed-off-by: Hanjun Guo Signed-off-by: Ganapatrao Kulkarni [rrichter@cavium.com Reworked for numa v10 series ] Signed-off-by: Robert Richter [david.daney@cavium.com reorderd and combinded with other patches in Hanjun Guo's original set, removed get_mpidr_in_madt() and use acpi_map_madt_entry() instead.] Signed-off-by: David Daney Reviewed-by: Catalin Marinas Tested-by: Dennis Chen Signed-off-by: Rafael J. Wysocki --- arch/arm64/include/asm/acpi.h | 8 +++ arch/arm64/include/asm/numa.h | 2 + arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/acpi_numa.c | 112 ++++++++++++++++++++++++++++++++++ arch/arm64/kernel/smp.c | 2 + arch/arm64/mm/numa.c | 5 +- 6 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kernel/acpi_numa.c diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index aee323b13802..4b13ecd3977a 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -113,4 +113,12 @@ static inline const char *acpi_get_enable_method(int cpu) pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr); #endif +#ifdef CONFIG_ACPI_NUMA +int arm64_acpi_numa_init(void); +int acpi_numa_get_nid(unsigned int cpu, u64 hwid); +#else +static inline int arm64_acpi_numa_init(void) { return -ENOSYS; } +static inline int acpi_numa_get_nid(unsigned int cpu, u64 hwid) { return NUMA_NO_NODE; } +#endif /* CONFIG_ACPI_NUMA */ + #endif /*_ASM_ACPI_H*/ diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h index e9b4f2942335..600887e491fd 100644 --- a/arch/arm64/include/asm/numa.h +++ b/arch/arm64/include/asm/numa.h @@ -5,6 +5,8 @@ #ifdef CONFIG_NUMA +#define NR_NODE_MEMBLKS (MAX_NUMNODES * 2) + /* currently, arm64 implements flat NUMA topology */ #define parent_node(node) (node) diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 2173149d8954..a5125c6d1f87 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -42,6 +42,7 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o arm64-obj-$(CONFIG_PCI) += pci.o arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_ACPI) += acpi.o +arm64-obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o arm64-obj-$(CONFIG_PARAVIRT) += paravirt.o arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c new file mode 100644 index 000000000000..f85149cc7c71 --- /dev/null +++ b/arch/arm64/kernel/acpi_numa.c @@ -0,0 +1,112 @@ +/* + * ACPI 5.1 based NUMA setup for ARM64 + * Lots of code was borrowed from arch/x86/mm/srat.c + * + * Copyright 2004 Andi Kleen, SuSE Labs. + * Copyright (C) 2013-2016, Linaro Ltd. + * Author: Hanjun Guo + * + * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. + * + * Called from acpi_numa_init while reading the SRAT and SLIT tables. + * Assumes all memory regions belonging to a single proximity domain + * are in one chunk. Holes between them will be included in the node. + */ + +#define pr_fmt(fmt) "ACPI: NUMA: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int cpus_in_srat; + +struct __node_cpu_hwid { + u32 node_id; /* logical node containing this CPU */ + u64 cpu_hwid; /* MPIDR for this CPU */ +}; + +static struct __node_cpu_hwid early_node_cpu_hwid[NR_CPUS] = { +[0 ... NR_CPUS - 1] = {NUMA_NO_NODE, PHYS_CPUID_INVALID} }; + +int acpi_numa_get_nid(unsigned int cpu, u64 hwid) +{ + int i; + + for (i = 0; i < cpus_in_srat; i++) { + if (hwid == early_node_cpu_hwid[i].cpu_hwid) + return early_node_cpu_hwid[i].node_id; + } + + return NUMA_NO_NODE; +} + +/* Callback for Proximity Domain -> ACPI processor UID mapping */ +void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) +{ + int pxm, node; + phys_cpuid_t mpidr; + + 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; + + if (cpus_in_srat >= NR_CPUS) { + pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n", + NR_CPUS); + 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; + } + + mpidr = acpi_map_madt_entry(pa->acpi_processor_uid); + if (mpidr == PHYS_CPUID_INVALID) { + pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n", + pxm, pa->acpi_processor_uid); + bad_srat(); + return; + } + + early_node_cpu_hwid[cpus_in_srat].node_id = node; + early_node_cpu_hwid[cpus_in_srat].cpu_hwid = mpidr; + node_set(node, numa_nodes_parsed); + cpus_in_srat++; + pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d\n", + pxm, mpidr, node); +} + +int __init arm64_acpi_numa_init(void) +{ + int ret; + + ret = acpi_numa_init(); + if (ret) + return ret; + + return srat_disabled() ? -EINVAL : 0; +} diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 678e0842cb3b..d0993068c44c 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -560,6 +560,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) */ acpi_set_mailbox_entry(cpu_count, processor); + early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid)); + cpu_count++; } diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 1def1de51578..c7fe3ec70774 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -391,7 +392,9 @@ static int __init dummy_numa_init(void) void __init arm64_numa_init(void) { if (!numa_off) { - if (!numa_init(of_numa_init)) + if (!acpi_disabled && !numa_init(arm64_acpi_numa_init)) + return; + if (acpi_disabled && !numa_init(of_numa_init)) return; } From 4bac6fa73db77d4ff49a965a7c6dc69d9e235e5f Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 17 Jun 2016 11:53:02 +0800 Subject: [PATCH 15/15] ACPI / NUMA: Enable ACPI based NUMA on ARM64 Add function needed for cpu to node mapping, and enable ACPI based NUMA for ARM64 in Kconfig Signed-off-by: Hanjun Guo Signed-off-by: Robert Richter [david.daney@cavium.com added ACPI_NUMA default to y for ARM64] Signed-off-by: David Daney Acked-by: Catalin Marinas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 4 ++-- drivers/acpi/numa.c | 37 ++++++++++++++++++++++++++++++++++++- include/linux/acpi.h | 17 ++++++++++++++++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b7e2e776397d..dd76b36c431f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -291,8 +291,8 @@ config ACPI_THERMAL config ACPI_NUMA bool "NUMA support" depends on NUMA - depends on (X86 || IA64) - default y if IA64_GENERIC || IA64_SGI_SN2 + depends on (X86 || IA64 || ARM64) + default y if IA64_GENERIC || IA64_SGI_SN2 || ARM64 config ACPI_CUSTOM_DSDT_FILE string "Custom DSDT Table file to include" diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index fad6d288117f..ce3a7a16f03f 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -170,6 +170,18 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) } break; + case ACPI_SRAT_TYPE_GICC_AFFINITY: + { + struct acpi_srat_gicc_affinity *p = + (struct acpi_srat_gicc_affinity *)header; + pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n", + p->acpi_processor_uid, + p->proximity_domain, + (p->flags & ACPI_SRAT_GICC_ENABLED) ? + "enabled" : "disabled"); + } + break; + default: pr_warn("Found unsupported SRAT entry (type = 0x%x)\n", header->type); @@ -360,6 +372,24 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header, return 0; } +static int __init +acpi_parse_gicc_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_gicc_affinity *processor_affinity; + + processor_affinity = (struct acpi_srat_gicc_affinity *)header; + if (!processor_affinity) + return -EINVAL; + + acpi_table_print_srat_entry(header); + + /* let architecture-dependent part to do it */ + acpi_numa_gicc_affinity_init(processor_affinity); + + return 0; +} + static int __initdata parsed_numa_memblks; static int __init @@ -404,6 +434,9 @@ int __init acpi_numa_init(void) { int cnt = 0; + if (acpi_disabled) + return -EINVAL; + /* * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= * SRAT cpu entries could have different order with that in MADT. @@ -412,13 +445,15 @@ int __init acpi_numa_init(void) /* SRAT: Static Resource Affinity Table */ if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { - struct acpi_subtable_proc srat_proc[2]; + struct acpi_subtable_proc srat_proc[3]; memset(srat_proc, 0, sizeof(srat_proc)); srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; srat_proc[0].handler = acpi_parse_processor_affinity; srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; srat_proc[1].handler = acpi_parse_x2apic_affinity; + srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY; + srat_proc[2].handler = acpi_parse_gicc_affinity; acpi_table_parse_entries_array(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 8010b266e856..9515db6f03f0 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -232,10 +232,25 @@ int acpi_table_parse_madt(enum acpi_madt_type id, int acpi_parse_mcfg (struct acpi_table_header *header); void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); -/* the following four functions are architecture-dependent */ +/* the following numa functions are architecture-dependent */ void acpi_numa_slit_init (struct acpi_table_slit *slit); + +#if defined(CONFIG_X86) || defined(CONFIG_IA64) void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); +#else +static inline void +acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { } +#endif + void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); + +#ifdef CONFIG_ARM64 +void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa); +#else +static inline void +acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { } +#endif + int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); #ifndef PHYS_CPUID_INVALID