mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
Merge branch 'acpi-numa'
* 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
This commit is contained in:
commit
d85f4eb699
@ -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*/
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
112
arch/arm64/kernel/acpi_numa.c
Normal file
112
arch/arm64/kernel/acpi_numa.c
Normal file
@ -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;
|
||||
}
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
@ -29,7 +30,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 +38,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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -362,12 +363,15 @@ 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;
|
||||
|
||||
@ -375,7 +379,7 @@ static int __init dummy_numa_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
numa_off = 1;
|
||||
numa_off = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__*/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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>
|
||||
@ -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"
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/topology.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/numa.h>
|
||||
@ -24,51 +22,6 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/uv/uv.h>
|
||||
|
||||
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");
|
||||
acpi_numa = -1;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -91,7 +44,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();
|
||||
@ -104,7 +57,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);
|
||||
}
|
||||
@ -127,7 +79,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();
|
||||
@ -146,74 +98,10 @@ 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);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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 && !save_add_info())
|
||||
goto out_err;
|
||||
|
||||
start = ma->base_address;
|
||||
end = start + ma->length;
|
||||
pxm = ma->proximity_domain;
|
||||
if (acpi_srat_revision <= 1)
|
||||
pxm &= 0xff;
|
||||
|
||||
node = setup_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 -1;
|
||||
}
|
||||
|
||||
void __init acpi_numa_arch_fixup(void) {}
|
||||
|
||||
int __init x86_acpi_numa_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -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"
|
||||
|
@ -18,22 +18,21 @@
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ACPI: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/numa.h>
|
||||
#include <linux/nodemask.h>
|
||||
#include <linux/topology.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#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 */
|
||||
@ -43,6 +42,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)
|
||||
{
|
||||
@ -128,68 +128,63 @@ 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;
|
||||
|
||||
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:
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -217,12 +212,117 @@ 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
|
||||
* 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
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;
|
||||
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 == 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) {
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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 +333,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)
|
||||
@ -275,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
|
||||
@ -319,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.
|
||||
@ -327,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),
|
||||
@ -347,8 +467,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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -232,12 +232,26 @@ 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);
|
||||
void acpi_numa_arch_fixup(void);
|
||||
|
||||
#ifndef PHYS_CPUID_INVALID
|
||||
typedef u32 phys_cpuid_t;
|
||||
|
Loading…
Reference in New Issue
Block a user