0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define pr_fmt(fmt) "ACPI: NUMA: " fmt
0018
0019 #include <linux/acpi.h>
0020 #include <linux/bitmap.h>
0021 #include <linux/kernel.h>
0022 #include <linux/mm.h>
0023 #include <linux/memblock.h>
0024 #include <linux/mmzone.h>
0025 #include <linux/module.h>
0026 #include <linux/topology.h>
0027
0028 #include <asm/numa.h>
0029
0030 static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
0031
0032 int __init acpi_numa_get_nid(unsigned int cpu)
0033 {
0034 return acpi_early_node_map[cpu];
0035 }
0036
0037 static inline int get_cpu_for_acpi_id(u32 uid)
0038 {
0039 int cpu;
0040
0041 for (cpu = 0; cpu < nr_cpu_ids; cpu++)
0042 if (uid == get_acpi_id_for_cpu(cpu))
0043 return cpu;
0044
0045 return -EINVAL;
0046 }
0047
0048 static int __init acpi_parse_gicc_pxm(union acpi_subtable_headers *header,
0049 const unsigned long end)
0050 {
0051 struct acpi_srat_gicc_affinity *pa;
0052 int cpu, pxm, node;
0053
0054 if (srat_disabled())
0055 return -EINVAL;
0056
0057 pa = (struct acpi_srat_gicc_affinity *)header;
0058 if (!pa)
0059 return -EINVAL;
0060
0061 if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
0062 return 0;
0063
0064 pxm = pa->proximity_domain;
0065 node = pxm_to_node(pxm);
0066
0067
0068
0069
0070
0071
0072
0073 cpu = get_cpu_for_acpi_id(pa->acpi_processor_uid);
0074 if (cpu < 0)
0075 return 0;
0076
0077 acpi_early_node_map[cpu] = node;
0078 pr_info("SRAT: PXM %d -> MPIDR 0x%llx -> Node %d\n", pxm,
0079 cpu_logical_map(cpu), node);
0080
0081 return 0;
0082 }
0083
0084 void __init acpi_map_cpus_to_nodes(void)
0085 {
0086 acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat),
0087 ACPI_SRAT_TYPE_GICC_AFFINITY,
0088 acpi_parse_gicc_pxm, 0);
0089 }
0090
0091
0092 void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
0093 {
0094 int pxm, node;
0095
0096 if (srat_disabled())
0097 return;
0098
0099 if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
0100 pr_err("SRAT: Invalid SRAT header length: %d\n",
0101 pa->header.length);
0102 bad_srat();
0103 return;
0104 }
0105
0106 if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
0107 return;
0108
0109 pxm = pa->proximity_domain;
0110 node = acpi_map_pxm_to_node(pxm);
0111
0112 if (node == NUMA_NO_NODE) {
0113 pr_err("SRAT: Too many proximity domains %d\n", pxm);
0114 bad_srat();
0115 return;
0116 }
0117
0118 node_set(node, numa_nodes_parsed);
0119 }
0120