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