Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * acpi_numa.c - ACPI NUMA support
4 *
5 * Copyright (C) 2002 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
6 */
7
8#define pr_fmt(fmt) "ACPI: " fmt
9
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/errno.h>
15#include <linux/acpi.h>
16#include <linux/memblock.h>
17#include <linux/numa.h>
18#include <linux/nodemask.h>
19#include <linux/topology.h>
20
21static nodemask_t nodes_found_map = NODE_MASK_NONE;
22
23/* maps to convert between proximity domain and logical node ID */
24static int pxm_to_node_map[MAX_PXM_DOMAINS]
25 = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
26static int node_to_pxm_map[MAX_NUMNODES]
27 = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
28
29unsigned char acpi_srat_revision __initdata;
30int acpi_numa __initdata;
31
32int pxm_to_node(int pxm)
33{
34 if (pxm < 0)
35 return NUMA_NO_NODE;
36 return pxm_to_node_map[pxm];
37}
38EXPORT_SYMBOL(pxm_to_node);
39
40int node_to_pxm(int node)
41{
42 if (node < 0)
43 return PXM_INVAL;
44 return node_to_pxm_map[node];
45}
46
47static void __acpi_map_pxm_to_node(int pxm, int node)
48{
49 if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
50 pxm_to_node_map[pxm] = node;
51 if (node_to_pxm_map[node] == PXM_INVAL || pxm < node_to_pxm_map[node])
52 node_to_pxm_map[node] = pxm;
53}
54
55int acpi_map_pxm_to_node(int pxm)
56{
57 int node;
58
59 if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
60 return NUMA_NO_NODE;
61
62 node = pxm_to_node_map[pxm];
63
64 if (node == NUMA_NO_NODE) {
65 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
66 return NUMA_NO_NODE;
67 node = first_unset_node(nodes_found_map);
68 __acpi_map_pxm_to_node(pxm, node);
69 node_set(node, nodes_found_map);
70 }
71
72 return node;
73}
74EXPORT_SYMBOL(acpi_map_pxm_to_node);
75
76static void __init
77acpi_table_print_srat_entry(struct acpi_subtable_header *header)
78{
79 switch (header->type) {
80 case ACPI_SRAT_TYPE_CPU_AFFINITY:
81 {
82 struct acpi_srat_cpu_affinity *p =
83 (struct acpi_srat_cpu_affinity *)header;
84 pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
85 p->apic_id, p->local_sapic_eid,
86 p->proximity_domain_lo,
87 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
88 "enabled" : "disabled");
89 }
90 break;
91
92 case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
93 {
94 struct acpi_srat_mem_affinity *p =
95 (struct acpi_srat_mem_affinity *)header;
96 pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
97 (unsigned long long)p->base_address,
98 (unsigned long long)p->length,
99 p->proximity_domain,
100 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
101 "enabled" : "disabled",
102 (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
103 " hot-pluggable" : "",
104 (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ?
105 " non-volatile" : "");
106 }
107 break;
108
109 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
110 {
111 struct acpi_srat_x2apic_cpu_affinity *p =
112 (struct acpi_srat_x2apic_cpu_affinity *)header;
113 pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n",
114 p->apic_id,
115 p->proximity_domain,
116 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
117 "enabled" : "disabled");
118 }
119 break;
120
121 case ACPI_SRAT_TYPE_GICC_AFFINITY:
122 {
123 struct acpi_srat_gicc_affinity *p =
124 (struct acpi_srat_gicc_affinity *)header;
125 pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
126 p->acpi_processor_uid,
127 p->proximity_domain,
128 (p->flags & ACPI_SRAT_GICC_ENABLED) ?
129 "enabled" : "disabled");
130 }
131 break;
132
133 default:
134 pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
135 header->type);
136 break;
137 }
138}
139
140/*
141 * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
142 * up the NUMA heuristics which wants the local node to have a smaller
143 * distance than the others.
144 * Do some quick checks here and only use the SLIT if it passes.
145 */
146static int __init slit_valid(struct acpi_table_slit *slit)
147{
148 int i, j;
149 int d = slit->locality_count;
150 for (i = 0; i < d; i++) {
151 for (j = 0; j < d; j++) {
152 u8 val = slit->entry[d*i + j];
153 if (i == j) {
154 if (val != LOCAL_DISTANCE)
155 return 0;
156 } else if (val <= LOCAL_DISTANCE)
157 return 0;
158 }
159 }
160 return 1;
161}
162
163void __init bad_srat(void)
164{
165 pr_err("SRAT: SRAT not used.\n");
166 acpi_numa = -1;
167}
168
169int __init srat_disabled(void)
170{
171 return acpi_numa < 0;
172}
173
174#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
175/*
176 * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
177 * I/O localities since SRAT does not list them. I/O localities are
178 * not supported at this point.
179 */
180void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
181{
182 int i, j;
183
184 for (i = 0; i < slit->locality_count; i++) {
185 const int from_node = pxm_to_node(i);
186
187 if (from_node == NUMA_NO_NODE)
188 continue;
189
190 for (j = 0; j < slit->locality_count; j++) {
191 const int to_node = pxm_to_node(j);
192
193 if (to_node == NUMA_NO_NODE)
194 continue;
195
196 numa_set_distance(from_node, to_node,
197 slit->entry[slit->locality_count * i + j]);
198 }
199 }
200}
201
202/*
203 * Default callback for parsing of the Proximity Domain <-> Memory
204 * Area mappings
205 */
206int __init
207acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
208{
209 u64 start, end;
210 u32 hotpluggable;
211 int node, pxm;
212
213 if (srat_disabled())
214 goto out_err;
215 if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) {
216 pr_err("SRAT: Unexpected header length: %d\n",
217 ma->header.length);
218 goto out_err_bad_srat;
219 }
220 if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
221 goto out_err;
222 hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
223 if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
224 goto out_err;
225
226 start = ma->base_address;
227 end = start + ma->length;
228 pxm = ma->proximity_domain;
229 if (acpi_srat_revision <= 1)
230 pxm &= 0xff;
231
232 node = acpi_map_pxm_to_node(pxm);
233 if (node == NUMA_NO_NODE) {
234 pr_err("SRAT: Too many proximity domains.\n");
235 goto out_err_bad_srat;
236 }
237
238 if (numa_add_memblk(node, start, end) < 0) {
239 pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n",
240 node, (unsigned long long) start,
241 (unsigned long long) end - 1);
242 goto out_err_bad_srat;
243 }
244
245 node_set(node, numa_nodes_parsed);
246
247 pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
248 node, pxm,
249 (unsigned long long) start, (unsigned long long) end - 1,
250 hotpluggable ? " hotplug" : "",
251 ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
252
253 /* Mark hotplug range in memblock. */
254 if (hotpluggable && memblock_mark_hotplug(start, ma->length))
255 pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
256 (unsigned long long)start, (unsigned long long)end - 1);
257
258 max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
259
260 return 0;
261out_err_bad_srat:
262 bad_srat();
263out_err:
264 return -EINVAL;
265}
266#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
267
268static int __init acpi_parse_slit(struct acpi_table_header *table)
269{
270 struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
271
272 if (!slit_valid(slit)) {
273 pr_info("SLIT table looks invalid. Not used.\n");
274 return -EINVAL;
275 }
276 acpi_numa_slit_init(slit);
277
278 return 0;
279}
280
281void __init __weak
282acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
283{
284 pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
285}
286
287static int __init
288acpi_parse_x2apic_affinity(union acpi_subtable_headers *header,
289 const unsigned long end)
290{
291 struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
292
293 processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
294
295 acpi_table_print_srat_entry(&header->common);
296
297 /* let architecture-dependent part to do it */
298 acpi_numa_x2apic_affinity_init(processor_affinity);
299
300 return 0;
301}
302
303static int __init
304acpi_parse_processor_affinity(union acpi_subtable_headers *header,
305 const unsigned long end)
306{
307 struct acpi_srat_cpu_affinity *processor_affinity;
308
309 processor_affinity = (struct acpi_srat_cpu_affinity *)header;
310
311 acpi_table_print_srat_entry(&header->common);
312
313 /* let architecture-dependent part to do it */
314 acpi_numa_processor_affinity_init(processor_affinity);
315
316 return 0;
317}
318
319static int __init
320acpi_parse_gicc_affinity(union acpi_subtable_headers *header,
321 const unsigned long end)
322{
323 struct acpi_srat_gicc_affinity *processor_affinity;
324
325 processor_affinity = (struct acpi_srat_gicc_affinity *)header;
326
327 acpi_table_print_srat_entry(&header->common);
328
329 /* let architecture-dependent part to do it */
330 acpi_numa_gicc_affinity_init(processor_affinity);
331
332 return 0;
333}
334
335static int __initdata parsed_numa_memblks;
336
337static int __init
338acpi_parse_memory_affinity(union acpi_subtable_headers * header,
339 const unsigned long end)
340{
341 struct acpi_srat_mem_affinity *memory_affinity;
342
343 memory_affinity = (struct acpi_srat_mem_affinity *)header;
344
345 acpi_table_print_srat_entry(&header->common);
346
347 /* let architecture-dependent part to do it */
348 if (!acpi_numa_memory_affinity_init(memory_affinity))
349 parsed_numa_memblks++;
350 return 0;
351}
352
353static int __init acpi_parse_srat(struct acpi_table_header *table)
354{
355 struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
356
357 acpi_srat_revision = srat->header.revision;
358
359 /* Real work done in acpi_table_parse_srat below. */
360
361 return 0;
362}
363
364static int __init
365acpi_table_parse_srat(enum acpi_srat_type id,
366 acpi_tbl_entry_handler handler, unsigned int max_entries)
367{
368 return acpi_table_parse_entries(ACPI_SIG_SRAT,
369 sizeof(struct acpi_table_srat), id,
370 handler, max_entries);
371}
372
373int __init acpi_numa_init(void)
374{
375 int cnt = 0;
376
377 if (acpi_disabled)
378 return -EINVAL;
379
380 /*
381 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
382 * SRAT cpu entries could have different order with that in MADT.
383 * So go over all cpu entries in SRAT to get apicid to node mapping.
384 */
385
386 /* SRAT: System Resource Affinity Table */
387 if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
388 struct acpi_subtable_proc srat_proc[3];
389
390 memset(srat_proc, 0, sizeof(srat_proc));
391 srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
392 srat_proc[0].handler = acpi_parse_processor_affinity;
393 srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
394 srat_proc[1].handler = acpi_parse_x2apic_affinity;
395 srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
396 srat_proc[2].handler = acpi_parse_gicc_affinity;
397
398 acpi_table_parse_entries_array(ACPI_SIG_SRAT,
399 sizeof(struct acpi_table_srat),
400 srat_proc, ARRAY_SIZE(srat_proc), 0);
401
402 cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
403 acpi_parse_memory_affinity, 0);
404 }
405
406 /* SLIT: System Locality Information Table */
407 acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
408
409 if (cnt < 0)
410 return cnt;
411 else if (!parsed_numa_memblks)
412 return -ENOENT;
413 return 0;
414}
415
416static int acpi_get_pxm(acpi_handle h)
417{
418 unsigned long long pxm;
419 acpi_status status;
420 acpi_handle handle;
421 acpi_handle phandle = h;
422
423 do {
424 handle = phandle;
425 status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
426 if (ACPI_SUCCESS(status))
427 return pxm;
428 status = acpi_get_parent(handle, &phandle);
429 } while (ACPI_SUCCESS(status));
430 return -1;
431}
432
433int acpi_get_node(acpi_handle handle)
434{
435 int pxm;
436
437 pxm = acpi_get_pxm(handle);
438
439 return acpi_map_pxm_to_node(pxm);
440}
441EXPORT_SYMBOL(acpi_get_node);