Skip to content

Commit

Permalink
Merge branch 'acpi-numa'
Browse files Browse the repository at this point in the history
* acpi-numa:
  ACPI / NUMA: Enable ACPI based NUMA on ARM64
  arm64, ACPI, NUMA: NUMA support based on SRAT and SLIT
  ACPI / processor: Add acpi_map_madt_entry()
  ACPI / NUMA: Improve SRAT error detection and add messages
  ACPI / NUMA: Move acpi_numa_memory_affinity_init() to drivers/acpi/numa.c
  ACPI / NUMA: remove unneeded acpi_numa=1
  ACPI / NUMA: move bad_srat() and srat_disabled() to drivers/acpi/numa.c
  x86 / ACPI / NUMA: cleanup acpi_numa_processor_affinity_init()
  arm64, NUMA: Cleanup NUMA disabled messages
  arm64, NUMA: rework numa_add_memblk()
  ACPI / NUMA: move acpi_numa_slit_init() to drivers/acpi/numa.c
  ACPI / NUMA: Move acpi_numa_arch_fixup() to ia64 only
  ACPI / NUMA: remove duplicate NULL check
  ACPI / NUMA: Replace ACPI_DEBUG_PRINT() with pr_debug()
  ACPI / NUMA: Use pr_fmt() instead of printk
  • Loading branch information
Rafael J. Wysocki committed Jul 25, 2016
2 parents 523d939 + 4bac6fa commit d85f4eb
Show file tree
Hide file tree
Showing 19 changed files with 369 additions and 192 deletions.
8 changes: 8 additions & 0 deletions arch/arm64/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*/
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/numa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
112 changes: 112 additions & 0 deletions arch/arm64/kernel/acpi_numa.c
Original file line number Diff line number Diff line change
@@ -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 <hanjun.guo@linaro.org>
*
* 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 <linux/acpi.h>
#include <linux/bitmap.h>
#include <linux/bootmem.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/memblock.h>
#include <linux/mmzone.h>
#include <linux/module.h>
#include <linux/topology.h>

#include <acpi/processor.h>
#include <asm/numa.h>

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;
}
2 changes: 2 additions & 0 deletions arch/arm64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
}

Expand Down
28 changes: 17 additions & 11 deletions arch/arm64/mm/numa.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <linux/acpi.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
#include <linux/module.h>
Expand All @@ -29,15 +30,15 @@ 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)
{
if (!opt)
return -EINVAL;
if (!strncmp(opt, "off", 3)) {
pr_info("%s\n", "NUMA turned off");
numa_off = 1;
numa_off = true;
}
return 0;
}
Expand Down Expand Up @@ -131,25 +132,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;
}

Expand Down Expand Up @@ -362,20 +363,23 @@ 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);

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;

pr_err("NUMA init failed\n");
return ret;
}

numa_off = 1;
numa_off = true;
return 0;
}

Expand All @@ -388,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;
}

Expand Down
3 changes: 3 additions & 0 deletions arch/ia64/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__*/
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions arch/ia64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion arch/x86/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/numa.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Common code for 32 and 64-bit NUMA */
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
Expand All @@ -15,7 +16,6 @@
#include <asm/e820.h>
#include <asm/proto.h>
#include <asm/dma.h>
#include <asm/acpi.h>
#include <asm/amd_nb.h>

#include "numa_internal.h"
Expand Down
Loading

0 comments on commit d85f4eb

Please sign in to comment.