diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-03-30 17:55:30 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-03 20:08:12 -0400 |
commit | 7237d3de78ff89ec2e18eae5fe962d063024fef5 (patch) | |
tree | 07d0196e9e3122546cc0366c686d363423bfe894 | |
parent | 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff) |
x86, ACPI: add support for x2apic ACPI extensions
All logical processors with APIC ID values of 255 and greater will have their
APIC reported through Processor X2APIC structure (type-9 entry type) and all
logical processors with APIC ID less than 255 will have their APIC reported
through legacy Processor Local APIC (type-0 entry type) only. This is the
same case even for NMI structure reporting.
The Processor X2APIC Affinity structure provides the association between the
X2APIC ID of a logical processor and the proximity domain to which the logical
processor belongs.
For OSPM, Procssor IDs outside the 0-254 range are to be declared as Device()
objects in the ACPI namespace.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 63 | ||||
-rw-r--r-- | arch/x86/mm/srat_64.c | 30 | ||||
-rw-r--r-- | drivers/acpi/numa.c | 46 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 26 | ||||
-rw-r--r-- | drivers/acpi/tables.c | 30 | ||||
-rw-r--r-- | include/linux/acpi.h | 1 |
6 files changed, 191 insertions, 5 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7678f10c456..565e70c7ca9 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -260,6 +260,35 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled) | |||
260 | } | 260 | } |
261 | 261 | ||
262 | static int __init | 262 | static int __init |
263 | acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) | ||
264 | { | ||
265 | struct acpi_madt_local_x2apic *processor = NULL; | ||
266 | |||
267 | processor = (struct acpi_madt_local_x2apic *)header; | ||
268 | |||
269 | if (BAD_MADT_ENTRY(processor, end)) | ||
270 | return -EINVAL; | ||
271 | |||
272 | acpi_table_print_madt_entry(header); | ||
273 | |||
274 | #ifdef CONFIG_X86_X2APIC | ||
275 | /* | ||
276 | * We need to register disabled CPU as well to permit | ||
277 | * counting disabled CPUs. This allows us to size | ||
278 | * cpus_possible_map more accurately, to permit | ||
279 | * to not preallocating memory for all NR_CPUS | ||
280 | * when we use CPU hotplug. | ||
281 | */ | ||
282 | acpi_register_lapic(processor->local_apic_id, /* APIC ID */ | ||
283 | processor->lapic_flags & ACPI_MADT_ENABLED); | ||
284 | #else | ||
285 | printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); | ||
286 | #endif | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int __init | ||
263 | acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) | 292 | acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) |
264 | { | 293 | { |
265 | struct acpi_madt_local_apic *processor = NULL; | 294 | struct acpi_madt_local_apic *processor = NULL; |
@@ -319,6 +348,25 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, | |||
319 | } | 348 | } |
320 | 349 | ||
321 | static int __init | 350 | static int __init |
351 | acpi_parse_x2apic_nmi(struct acpi_subtable_header *header, | ||
352 | const unsigned long end) | ||
353 | { | ||
354 | struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL; | ||
355 | |||
356 | x2apic_nmi = (struct acpi_madt_local_x2apic_nmi *)header; | ||
357 | |||
358 | if (BAD_MADT_ENTRY(x2apic_nmi, end)) | ||
359 | return -EINVAL; | ||
360 | |||
361 | acpi_table_print_madt_entry(header); | ||
362 | |||
363 | if (x2apic_nmi->lint != 1) | ||
364 | printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static int __init | ||
322 | acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) | 370 | acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) |
323 | { | 371 | { |
324 | struct acpi_madt_local_apic_nmi *lapic_nmi = NULL; | 372 | struct acpi_madt_local_apic_nmi *lapic_nmi = NULL; |
@@ -823,6 +871,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void) | |||
823 | static int __init acpi_parse_madt_lapic_entries(void) | 871 | static int __init acpi_parse_madt_lapic_entries(void) |
824 | { | 872 | { |
825 | int count; | 873 | int count; |
874 | int x2count = 0; | ||
826 | 875 | ||
827 | if (!cpu_has_apic) | 876 | if (!cpu_has_apic) |
828 | return -ENODEV; | 877 | return -ENODEV; |
@@ -846,22 +895,28 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
846 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, | 895 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, |
847 | acpi_parse_sapic, MAX_APICS); | 896 | acpi_parse_sapic, MAX_APICS); |
848 | 897 | ||
849 | if (!count) | 898 | if (!count) { |
899 | x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, | ||
900 | acpi_parse_x2apic, MAX_APICS); | ||
850 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, | 901 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, |
851 | acpi_parse_lapic, MAX_APICS); | 902 | acpi_parse_lapic, MAX_APICS); |
852 | if (!count) { | 903 | } |
904 | if (!count && !x2count) { | ||
853 | printk(KERN_ERR PREFIX "No LAPIC entries present\n"); | 905 | printk(KERN_ERR PREFIX "No LAPIC entries present\n"); |
854 | /* TBD: Cleanup to allow fallback to MPS */ | 906 | /* TBD: Cleanup to allow fallback to MPS */ |
855 | return -ENODEV; | 907 | return -ENODEV; |
856 | } else if (count < 0) { | 908 | } else if (count < 0 || x2count < 0) { |
857 | printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); | 909 | printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); |
858 | /* TBD: Cleanup to allow fallback to MPS */ | 910 | /* TBD: Cleanup to allow fallback to MPS */ |
859 | return count; | 911 | return count; |
860 | } | 912 | } |
861 | 913 | ||
914 | x2count = | ||
915 | acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI, | ||
916 | acpi_parse_x2apic_nmi, 0); | ||
862 | count = | 917 | count = |
863 | acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0); | 918 | acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0); |
864 | if (count < 0) { | 919 | if (count < 0 || x2count < 0) { |
865 | printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); | 920 | printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); |
866 | /* TBD: Cleanup to allow fallback to MPS */ | 921 | /* TBD: Cleanup to allow fallback to MPS */ |
867 | return count; | 922 | return count; |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 09737c8af07..13d56f5b134 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -115,6 +115,36 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | |||
115 | reserve_early(phys, phys + length, "ACPI SLIT"); | 115 | reserve_early(phys, phys + length, "ACPI SLIT"); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Callback for Proximity Domain -> x2APIC mapping */ | ||
119 | void __init | ||
120 | acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) | ||
121 | { | ||
122 | int pxm, node; | ||
123 | int apic_id; | ||
124 | |||
125 | if (srat_disabled()) | ||
126 | return; | ||
127 | if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) { | ||
128 | bad_srat(); | ||
129 | return; | ||
130 | } | ||
131 | if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) | ||
132 | return; | ||
133 | pxm = pa->proximity_domain; | ||
134 | node = setup_node(pxm); | ||
135 | if (node < 0) { | ||
136 | printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); | ||
137 | bad_srat(); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | apic_id = pa->apic_id; | ||
142 | apicid_to_node[apic_id] = node; | ||
143 | acpi_numa = 1; | ||
144 | printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", | ||
145 | pxm, apic_id, node); | ||
146 | } | ||
147 | |||
118 | /* Callback for Proximity Domain -> LAPIC mapping */ | 148 | /* Callback for Proximity Domain -> LAPIC mapping */ |
119 | void __init | 149 | void __init |
120 | acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) | 150 | acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 3a0d8ef25c7..d440ccd27d9 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -131,6 +131,21 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) | |||
131 | #endif /* ACPI_DEBUG_OUTPUT */ | 131 | #endif /* ACPI_DEBUG_OUTPUT */ |
132 | break; | 132 | break; |
133 | 133 | ||
134 | case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: | ||
135 | #ifdef ACPI_DEBUG_OUTPUT | ||
136 | { | ||
137 | struct acpi_srat_x2apic_cpu_affinity *p = | ||
138 | (struct acpi_srat_x2apic_cpu_affinity *)header; | ||
139 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
140 | "SRAT Processor (x2apicid[0x%08x]) in" | ||
141 | " proximity domain %d %s\n", | ||
142 | p->apic_id, | ||
143 | p->proximity_domain, | ||
144 | (p->flags & ACPI_SRAT_CPU_ENABLED) ? | ||
145 | "enabled" : "disabled")); | ||
146 | } | ||
147 | #endif /* ACPI_DEBUG_OUTPUT */ | ||
148 | break; | ||
134 | default: | 149 | default: |
135 | printk(KERN_WARNING PREFIX | 150 | printk(KERN_WARNING PREFIX |
136 | "Found unsupported SRAT entry (type = 0x%x)\n", | 151 | "Found unsupported SRAT entry (type = 0x%x)\n", |
@@ -180,8 +195,35 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) | |||
180 | return 0; | 195 | return 0; |
181 | } | 196 | } |
182 | 197 | ||
198 | void __init __attribute__ ((weak)) | ||
199 | acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) | ||
200 | { | ||
201 | printk(KERN_WARNING PREFIX | ||
202 | "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); | ||
203 | return; | ||
204 | } | ||
205 | |||
206 | |||
207 | static int __init | ||
208 | acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, | ||
209 | const unsigned long end) | ||
210 | { | ||
211 | struct acpi_srat_x2apic_cpu_affinity *processor_affinity; | ||
212 | |||
213 | processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header; | ||
214 | if (!processor_affinity) | ||
215 | return -EINVAL; | ||
216 | |||
217 | acpi_table_print_srat_entry(header); | ||
218 | |||
219 | /* let architecture-dependent part to do it */ | ||
220 | acpi_numa_x2apic_affinity_init(processor_affinity); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
183 | static int __init | 225 | static int __init |
184 | acpi_parse_processor_affinity(struct acpi_subtable_header * header, | 226 | acpi_parse_processor_affinity(struct acpi_subtable_header *header, |
185 | const unsigned long end) | 227 | const unsigned long end) |
186 | { | 228 | { |
187 | struct acpi_srat_cpu_affinity *processor_affinity; | 229 | struct acpi_srat_cpu_affinity *processor_affinity; |
@@ -241,6 +283,8 @@ int __init acpi_numa_init(void) | |||
241 | { | 283 | { |
242 | /* SRAT: Static Resource Affinity Table */ | 284 | /* SRAT: Static Resource Affinity Table */ |
243 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { | 285 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
286 | acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, | ||
287 | acpi_parse_x2apic_affinity, NR_CPUS); | ||
244 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, | 288 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, |
245 | acpi_parse_processor_affinity, NR_CPUS); | 289 | acpi_parse_processor_affinity, NR_CPUS); |
246 | acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, | 290 | acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0cc2fd31e37..775324e34ff 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -427,6 +427,29 @@ static int map_lapic_id(struct acpi_subtable_header *entry, | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | static int map_x2apic_id(struct acpi_subtable_header *entry, | ||
431 | int device_declaration, u32 acpi_id, int *apic_id) | ||
432 | { | ||
433 | struct acpi_madt_local_x2apic *apic = | ||
434 | (struct acpi_madt_local_x2apic *)entry; | ||
435 | u32 tmp = apic->local_apic_id; | ||
436 | |||
437 | /* Only check enabled APICs*/ | ||
438 | if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) | ||
439 | return 0; | ||
440 | |||
441 | /* Device statement declaration type */ | ||
442 | if (device_declaration) { | ||
443 | if (apic->uid == acpi_id) | ||
444 | goto found; | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | found: | ||
449 | *apic_id = tmp; | ||
450 | return 1; | ||
451 | } | ||
452 | |||
430 | static int map_lsapic_id(struct acpi_subtable_header *entry, | 453 | static int map_lsapic_id(struct acpi_subtable_header *entry, |
431 | int device_declaration, u32 acpi_id, int *apic_id) | 454 | int device_declaration, u32 acpi_id, int *apic_id) |
432 | { | 455 | { |
@@ -476,6 +499,9 @@ static int map_madt_entry(int type, u32 acpi_id) | |||
476 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { | 499 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { |
477 | if (map_lapic_id(header, acpi_id, &apic_id)) | 500 | if (map_lapic_id(header, acpi_id, &apic_id)) |
478 | break; | 501 | break; |
502 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { | ||
503 | if (map_x2apic_id(header, type, acpi_id, &apic_id)) | ||
504 | break; | ||
479 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 505 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
480 | if (map_lsapic_id(header, type, acpi_id, &apic_id)) | 506 | if (map_lsapic_id(header, type, acpi_id, &apic_id)) |
481 | break; | 507 | break; |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index a8852952fac..991c006a301 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -62,6 +62,18 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) | |||
62 | } | 62 | } |
63 | break; | 63 | break; |
64 | 64 | ||
65 | case ACPI_MADT_TYPE_LOCAL_X2APIC: | ||
66 | { | ||
67 | struct acpi_madt_local_x2apic *p = | ||
68 | (struct acpi_madt_local_x2apic *)header; | ||
69 | printk(KERN_INFO PREFIX | ||
70 | "X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n", | ||
71 | p->local_apic_id, p->uid, | ||
72 | (p->lapic_flags & ACPI_MADT_ENABLED) ? | ||
73 | "enabled" : "disabled"); | ||
74 | } | ||
75 | break; | ||
76 | |||
65 | case ACPI_MADT_TYPE_IO_APIC: | 77 | case ACPI_MADT_TYPE_IO_APIC: |
66 | { | 78 | { |
67 | struct acpi_madt_io_apic *p = | 79 | struct acpi_madt_io_apic *p = |
@@ -116,6 +128,24 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) | |||
116 | } | 128 | } |
117 | break; | 129 | break; |
118 | 130 | ||
131 | case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: | ||
132 | { | ||
133 | u16 polarity, trigger; | ||
134 | struct acpi_madt_local_x2apic_nmi *p = | ||
135 | (struct acpi_madt_local_x2apic_nmi *)header; | ||
136 | |||
137 | polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK; | ||
138 | trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2; | ||
139 | |||
140 | printk(KERN_INFO PREFIX | ||
141 | "X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n", | ||
142 | p->uid, | ||
143 | mps_inti_flags_polarity[polarity], | ||
144 | mps_inti_flags_trigger[trigger], | ||
145 | p->lint); | ||
146 | } | ||
147 | break; | ||
148 | |||
119 | case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: | 149 | case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: |
120 | { | 150 | { |
121 | struct acpi_madt_local_apic_override *p = | 151 | struct acpi_madt_local_apic_override *p = |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6fce2fc2d12..a6989e51754 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -96,6 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); | |||
96 | /* the following four functions are architecture-dependent */ | 96 | /* the following four functions are architecture-dependent */ |
97 | void acpi_numa_slit_init (struct acpi_table_slit *slit); | 97 | void acpi_numa_slit_init (struct acpi_table_slit *slit); |
98 | void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); | 98 | void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); |
99 | void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); | ||
99 | void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); | 100 | void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); |
100 | void acpi_numa_arch_fixup(void); | 101 | void acpi_numa_arch_fixup(void); |
101 | 102 | ||