Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * ACPI 3.0 based NUMA setup 4 : : * Copyright 2004 Andi Kleen, SuSE Labs. 5 : : * 6 : : * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. 7 : : * 8 : : * Called from acpi_numa_init while reading the SRAT and SLIT tables. 9 : : * Assumes all memory regions belonging to a single proximity domain 10 : : * are in one chunk. Holes between them will be included in the node. 11 : : */ 12 : : 13 : : #include <linux/kernel.h> 14 : : #include <linux/acpi.h> 15 : : #include <linux/mmzone.h> 16 : : #include <linux/bitmap.h> 17 : : #include <linux/init.h> 18 : : #include <linux/topology.h> 19 : : #include <linux/mm.h> 20 : : #include <asm/proto.h> 21 : : #include <asm/numa.h> 22 : : #include <asm/e820/api.h> 23 : : #include <asm/apic.h> 24 : : #include <asm/uv/uv.h> 25 : : 26 : : /* Callback for Proximity Domain -> x2APIC mapping */ 27 : : void __init 28 : 0 : acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) 29 : : { 30 : 0 : int pxm, node; 31 : 0 : int apic_id; 32 : : 33 [ # # ]: 0 : if (srat_disabled()) 34 : : return; 35 [ # # ]: 0 : if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) { 36 : 0 : bad_srat(); 37 : 0 : return; 38 : : } 39 [ # # ]: 0 : if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) 40 : : return; 41 : 0 : pxm = pa->proximity_domain; 42 : 0 : apic_id = pa->apic_id; 43 [ # # ]: 0 : if (!apic->apic_id_valid(apic_id)) { 44 : 0 : printk(KERN_INFO "SRAT: PXM %u -> X2APIC 0x%04x ignored\n", 45 : : pxm, apic_id); 46 : 0 : return; 47 : : } 48 : 0 : node = acpi_map_pxm_to_node(pxm); 49 [ # # ]: 0 : if (node < 0) { 50 : 0 : printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); 51 : 0 : bad_srat(); 52 : 0 : return; 53 : : } 54 : : 55 [ # # ]: 0 : if (apic_id >= MAX_LOCAL_APIC) { 56 : 0 : printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node); 57 : 0 : return; 58 : : } 59 : 0 : set_apicid_to_node(apic_id, node); 60 : 0 : node_set(node, numa_nodes_parsed); 61 : 0 : printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", 62 : : pxm, apic_id, node); 63 : : } 64 : : 65 : : /* Callback for Proximity Domain -> LAPIC mapping */ 66 : : void __init 67 : 0 : acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) 68 : : { 69 : 0 : int pxm, node; 70 : 0 : int apic_id; 71 : : 72 [ # # ]: 0 : if (srat_disabled()) 73 : : return; 74 [ # # ]: 0 : if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) { 75 : 0 : bad_srat(); 76 : 0 : return; 77 : : } 78 [ # # ]: 0 : if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) 79 : : return; 80 : 0 : pxm = pa->proximity_domain_lo; 81 [ # # ]: 0 : if (acpi_srat_revision >= 2) 82 : 0 : pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8; 83 : 0 : node = acpi_map_pxm_to_node(pxm); 84 [ # # ]: 0 : if (node < 0) { 85 : 0 : printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); 86 : 0 : bad_srat(); 87 : 0 : return; 88 : : } 89 : : 90 : 0 : if (get_uv_system_type() >= UV_X2APIC) 91 : : apic_id = (pa->apic_id << 8) | pa->local_sapic_eid; 92 : : else 93 : 0 : apic_id = pa->apic_id; 94 : : 95 : 0 : if (apic_id >= MAX_LOCAL_APIC) { 96 : : printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node); 97 : : return; 98 : : } 99 : : 100 : 0 : set_apicid_to_node(apic_id, node); 101 : 0 : node_set(node, numa_nodes_parsed); 102 : 0 : printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", 103 : : pxm, apic_id, node); 104 : : } 105 : : 106 : 78 : int __init x86_acpi_numa_init(void) 107 : : { 108 : 78 : int ret; 109 : : 110 : 78 : ret = acpi_numa_init(); 111 [ - + ]: 78 : if (ret < 0) 112 : : return ret; 113 [ # # ]: 0 : return srat_disabled() ? -EINVAL : 0; 114 : : }