0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "ACPI: " fmt
0009
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/types.h>
0014 #include <linux/errno.h>
0015 #include <linux/acpi.h>
0016 #include <linux/memblock.h>
0017 #include <linux/numa.h>
0018 #include <linux/nodemask.h>
0019 #include <linux/topology.h>
0020
0021 static nodemask_t nodes_found_map = NODE_MASK_NONE;
0022
0023
0024 static int pxm_to_node_map[MAX_PXM_DOMAINS]
0025 = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
0026 static int node_to_pxm_map[MAX_NUMNODES]
0027 = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
0028
0029 unsigned char acpi_srat_revision __initdata;
0030 static int acpi_numa __initdata;
0031
0032 void __init disable_srat(void)
0033 {
0034 acpi_numa = -1;
0035 }
0036
0037 int pxm_to_node(int pxm)
0038 {
0039 if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
0040 return NUMA_NO_NODE;
0041 return pxm_to_node_map[pxm];
0042 }
0043 EXPORT_SYMBOL(pxm_to_node);
0044
0045 int node_to_pxm(int node)
0046 {
0047 if (node < 0)
0048 return PXM_INVAL;
0049 return node_to_pxm_map[node];
0050 }
0051
0052 static void __acpi_map_pxm_to_node(int pxm, int node)
0053 {
0054 if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
0055 pxm_to_node_map[pxm] = node;
0056 if (node_to_pxm_map[node] == PXM_INVAL || pxm < node_to_pxm_map[node])
0057 node_to_pxm_map[node] = pxm;
0058 }
0059
0060 int acpi_map_pxm_to_node(int pxm)
0061 {
0062 int node;
0063
0064 if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
0065 return NUMA_NO_NODE;
0066
0067 node = pxm_to_node_map[pxm];
0068
0069 if (node == NUMA_NO_NODE) {
0070 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
0071 return NUMA_NO_NODE;
0072 node = first_unset_node(nodes_found_map);
0073 __acpi_map_pxm_to_node(pxm, node);
0074 node_set(node, nodes_found_map);
0075 }
0076
0077 return node;
0078 }
0079 EXPORT_SYMBOL(acpi_map_pxm_to_node);
0080
0081 static void __init
0082 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
0083 {
0084 switch (header->type) {
0085 case ACPI_SRAT_TYPE_CPU_AFFINITY:
0086 {
0087 struct acpi_srat_cpu_affinity *p =
0088 (struct acpi_srat_cpu_affinity *)header;
0089 pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
0090 p->apic_id, p->local_sapic_eid,
0091 p->proximity_domain_lo,
0092 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
0093 "enabled" : "disabled");
0094 }
0095 break;
0096
0097 case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
0098 {
0099 struct acpi_srat_mem_affinity *p =
0100 (struct acpi_srat_mem_affinity *)header;
0101 pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
0102 (unsigned long long)p->base_address,
0103 (unsigned long long)p->length,
0104 p->proximity_domain,
0105 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
0106 "enabled" : "disabled",
0107 (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
0108 " hot-pluggable" : "",
0109 (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ?
0110 " non-volatile" : "");
0111 }
0112 break;
0113
0114 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
0115 {
0116 struct acpi_srat_x2apic_cpu_affinity *p =
0117 (struct acpi_srat_x2apic_cpu_affinity *)header;
0118 pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n",
0119 p->apic_id,
0120 p->proximity_domain,
0121 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
0122 "enabled" : "disabled");
0123 }
0124 break;
0125
0126 case ACPI_SRAT_TYPE_GICC_AFFINITY:
0127 {
0128 struct acpi_srat_gicc_affinity *p =
0129 (struct acpi_srat_gicc_affinity *)header;
0130 pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
0131 p->acpi_processor_uid,
0132 p->proximity_domain,
0133 (p->flags & ACPI_SRAT_GICC_ENABLED) ?
0134 "enabled" : "disabled");
0135 }
0136 break;
0137
0138 case ACPI_SRAT_TYPE_GENERIC_AFFINITY:
0139 {
0140 struct acpi_srat_generic_affinity *p =
0141 (struct acpi_srat_generic_affinity *)header;
0142
0143 if (p->device_handle_type == 0) {
0144
0145
0146
0147
0148 pr_debug("SRAT Generic Initiator(Seg:%u BDF:%u) in proximity domain %d %s\n",
0149 *(u16 *)(&p->device_handle[0]),
0150 *(u16 *)(&p->device_handle[2]),
0151 p->proximity_domain,
0152 (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ?
0153 "enabled" : "disabled");
0154 } else {
0155
0156
0157
0158
0159 pr_debug("SRAT Generic Initiator(HID=%.8s UID=%.4s) in proximity domain %d %s\n",
0160 (char *)(&p->device_handle[0]),
0161 (char *)(&p->device_handle[8]),
0162 p->proximity_domain,
0163 (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ?
0164 "enabled" : "disabled");
0165 }
0166 }
0167 break;
0168 default:
0169 pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
0170 header->type);
0171 break;
0172 }
0173 }
0174
0175
0176
0177
0178
0179
0180
0181 static int __init slit_valid(struct acpi_table_slit *slit)
0182 {
0183 int i, j;
0184 int d = slit->locality_count;
0185 for (i = 0; i < d; i++) {
0186 for (j = 0; j < d; j++) {
0187 u8 val = slit->entry[d*i + j];
0188 if (i == j) {
0189 if (val != LOCAL_DISTANCE)
0190 return 0;
0191 } else if (val <= LOCAL_DISTANCE)
0192 return 0;
0193 }
0194 }
0195 return 1;
0196 }
0197
0198 void __init bad_srat(void)
0199 {
0200 pr_err("SRAT: SRAT not used.\n");
0201 disable_srat();
0202 }
0203
0204 int __init srat_disabled(void)
0205 {
0206 return acpi_numa < 0;
0207 }
0208
0209 #if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
0210
0211
0212
0213
0214
0215 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
0216 {
0217 int i, j;
0218
0219 for (i = 0; i < slit->locality_count; i++) {
0220 const int from_node = pxm_to_node(i);
0221
0222 if (from_node == NUMA_NO_NODE)
0223 continue;
0224
0225 for (j = 0; j < slit->locality_count; j++) {
0226 const int to_node = pxm_to_node(j);
0227
0228 if (to_node == NUMA_NO_NODE)
0229 continue;
0230
0231 numa_set_distance(from_node, to_node,
0232 slit->entry[slit->locality_count * i + j]);
0233 }
0234 }
0235 }
0236
0237
0238
0239
0240
0241 int __init
0242 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
0243 {
0244 u64 start, end;
0245 u32 hotpluggable;
0246 int node, pxm;
0247
0248 if (srat_disabled())
0249 goto out_err;
0250 if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) {
0251 pr_err("SRAT: Unexpected header length: %d\n",
0252 ma->header.length);
0253 goto out_err_bad_srat;
0254 }
0255 if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
0256 goto out_err;
0257 hotpluggable = IS_ENABLED(CONFIG_MEMORY_HOTPLUG) &&
0258 (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE);
0259
0260 start = ma->base_address;
0261 end = start + ma->length;
0262 pxm = ma->proximity_domain;
0263 if (acpi_srat_revision <= 1)
0264 pxm &= 0xff;
0265
0266 node = acpi_map_pxm_to_node(pxm);
0267 if (node == NUMA_NO_NODE) {
0268 pr_err("SRAT: Too many proximity domains.\n");
0269 goto out_err_bad_srat;
0270 }
0271
0272 if (numa_add_memblk(node, start, end) < 0) {
0273 pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n",
0274 node, (unsigned long long) start,
0275 (unsigned long long) end - 1);
0276 goto out_err_bad_srat;
0277 }
0278
0279 node_set(node, numa_nodes_parsed);
0280
0281 pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
0282 node, pxm,
0283 (unsigned long long) start, (unsigned long long) end - 1,
0284 hotpluggable ? " hotplug" : "",
0285 ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
0286
0287
0288 if (hotpluggable && memblock_mark_hotplug(start, ma->length))
0289 pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
0290 (unsigned long long)start, (unsigned long long)end - 1);
0291
0292 max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
0293
0294 return 0;
0295 out_err_bad_srat:
0296 bad_srat();
0297 out_err:
0298 return -EINVAL;
0299 }
0300
0301 static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
0302 void *arg, const unsigned long table_end)
0303 {
0304 struct acpi_cedt_cfmws *cfmws;
0305 int *fake_pxm = arg;
0306 u64 start, end;
0307 int node;
0308
0309 cfmws = (struct acpi_cedt_cfmws *)header;
0310 start = cfmws->base_hpa;
0311 end = cfmws->base_hpa + cfmws->window_size;
0312
0313
0314 node = phys_to_target_node(start);
0315 if (node != NUMA_NO_NODE)
0316 return 0;
0317
0318 node = acpi_map_pxm_to_node(*fake_pxm);
0319
0320 if (node == NUMA_NO_NODE) {
0321 pr_err("ACPI NUMA: Too many proximity domains while processing CFMWS.\n");
0322 return -EINVAL;
0323 }
0324
0325 if (numa_add_memblk(node, start, end) < 0) {
0326
0327 pr_warn("ACPI NUMA: Failed to add memblk for CFMWS node %d [mem %#llx-%#llx]\n",
0328 node, start, end);
0329 }
0330
0331
0332 (*fake_pxm)++;
0333 return 0;
0334 }
0335 #else
0336 static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
0337 void *arg, const unsigned long table_end)
0338 {
0339 return 0;
0340 }
0341 #endif
0342
0343 static int __init acpi_parse_slit(struct acpi_table_header *table)
0344 {
0345 struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
0346
0347 if (!slit_valid(slit)) {
0348 pr_info("SLIT table looks invalid. Not used.\n");
0349 return -EINVAL;
0350 }
0351 acpi_numa_slit_init(slit);
0352
0353 return 0;
0354 }
0355
0356 void __init __weak
0357 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
0358 {
0359 pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
0360 }
0361
0362 static int __init
0363 acpi_parse_x2apic_affinity(union acpi_subtable_headers *header,
0364 const unsigned long end)
0365 {
0366 struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
0367
0368 processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
0369
0370 acpi_table_print_srat_entry(&header->common);
0371
0372
0373 acpi_numa_x2apic_affinity_init(processor_affinity);
0374
0375 return 0;
0376 }
0377
0378 static int __init
0379 acpi_parse_processor_affinity(union acpi_subtable_headers *header,
0380 const unsigned long end)
0381 {
0382 struct acpi_srat_cpu_affinity *processor_affinity;
0383
0384 processor_affinity = (struct acpi_srat_cpu_affinity *)header;
0385
0386 acpi_table_print_srat_entry(&header->common);
0387
0388
0389 acpi_numa_processor_affinity_init(processor_affinity);
0390
0391 return 0;
0392 }
0393
0394 static int __init
0395 acpi_parse_gicc_affinity(union acpi_subtable_headers *header,
0396 const unsigned long end)
0397 {
0398 struct acpi_srat_gicc_affinity *processor_affinity;
0399
0400 processor_affinity = (struct acpi_srat_gicc_affinity *)header;
0401
0402 acpi_table_print_srat_entry(&header->common);
0403
0404
0405 acpi_numa_gicc_affinity_init(processor_affinity);
0406
0407 return 0;
0408 }
0409
0410 #if defined(CONFIG_X86) || defined(CONFIG_ARM64)
0411 static int __init
0412 acpi_parse_gi_affinity(union acpi_subtable_headers *header,
0413 const unsigned long end)
0414 {
0415 struct acpi_srat_generic_affinity *gi_affinity;
0416 int node;
0417
0418 gi_affinity = (struct acpi_srat_generic_affinity *)header;
0419 if (!gi_affinity)
0420 return -EINVAL;
0421 acpi_table_print_srat_entry(&header->common);
0422
0423 if (!(gi_affinity->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED))
0424 return -EINVAL;
0425
0426 node = acpi_map_pxm_to_node(gi_affinity->proximity_domain);
0427 if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
0428 pr_err("SRAT: Too many proximity domains.\n");
0429 return -EINVAL;
0430 }
0431 node_set(node, numa_nodes_parsed);
0432 node_set_state(node, N_GENERIC_INITIATOR);
0433
0434 return 0;
0435 }
0436 #else
0437 static int __init
0438 acpi_parse_gi_affinity(union acpi_subtable_headers *header,
0439 const unsigned long end)
0440 {
0441 return 0;
0442 }
0443 #endif
0444
0445 static int __initdata parsed_numa_memblks;
0446
0447 static int __init
0448 acpi_parse_memory_affinity(union acpi_subtable_headers * header,
0449 const unsigned long end)
0450 {
0451 struct acpi_srat_mem_affinity *memory_affinity;
0452
0453 memory_affinity = (struct acpi_srat_mem_affinity *)header;
0454
0455 acpi_table_print_srat_entry(&header->common);
0456
0457
0458 if (!acpi_numa_memory_affinity_init(memory_affinity))
0459 parsed_numa_memblks++;
0460 return 0;
0461 }
0462
0463 static int __init acpi_parse_srat(struct acpi_table_header *table)
0464 {
0465 struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
0466
0467 acpi_srat_revision = srat->header.revision;
0468
0469
0470
0471 return 0;
0472 }
0473
0474 static int __init
0475 acpi_table_parse_srat(enum acpi_srat_type id,
0476 acpi_tbl_entry_handler handler, unsigned int max_entries)
0477 {
0478 return acpi_table_parse_entries(ACPI_SIG_SRAT,
0479 sizeof(struct acpi_table_srat), id,
0480 handler, max_entries);
0481 }
0482
0483 int __init acpi_numa_init(void)
0484 {
0485 int i, fake_pxm, cnt = 0;
0486
0487 if (acpi_disabled)
0488 return -EINVAL;
0489
0490
0491
0492
0493
0494
0495
0496
0497 if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
0498 struct acpi_subtable_proc srat_proc[4];
0499
0500 memset(srat_proc, 0, sizeof(srat_proc));
0501 srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
0502 srat_proc[0].handler = acpi_parse_processor_affinity;
0503 srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
0504 srat_proc[1].handler = acpi_parse_x2apic_affinity;
0505 srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
0506 srat_proc[2].handler = acpi_parse_gicc_affinity;
0507 srat_proc[3].id = ACPI_SRAT_TYPE_GENERIC_AFFINITY;
0508 srat_proc[3].handler = acpi_parse_gi_affinity;
0509
0510 acpi_table_parse_entries_array(ACPI_SIG_SRAT,
0511 sizeof(struct acpi_table_srat),
0512 srat_proc, ARRAY_SIZE(srat_proc), 0);
0513
0514 cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
0515 acpi_parse_memory_affinity, 0);
0516 }
0517
0518
0519 acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529 for (i = 0, fake_pxm = -1; i < MAX_NUMNODES - 1; i++) {
0530 if (node_to_pxm_map[i] > fake_pxm)
0531 fake_pxm = node_to_pxm_map[i];
0532 }
0533 fake_pxm++;
0534 acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, acpi_parse_cfmws,
0535 &fake_pxm);
0536
0537 if (cnt < 0)
0538 return cnt;
0539 else if (!parsed_numa_memblks)
0540 return -ENOENT;
0541 return 0;
0542 }
0543
0544 static int acpi_get_pxm(acpi_handle h)
0545 {
0546 unsigned long long pxm;
0547 acpi_status status;
0548 acpi_handle handle;
0549 acpi_handle phandle = h;
0550
0551 do {
0552 handle = phandle;
0553 status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
0554 if (ACPI_SUCCESS(status))
0555 return pxm;
0556 status = acpi_get_parent(handle, &phandle);
0557 } while (ACPI_SUCCESS(status));
0558 return -1;
0559 }
0560
0561 int acpi_get_node(acpi_handle handle)
0562 {
0563 int pxm;
0564
0565 pxm = acpi_get_pxm(handle);
0566
0567 return pxm_to_node(pxm);
0568 }
0569 EXPORT_SYMBOL(acpi_get_node);