aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2009-03-30 17:55:30 -0400
committerLen Brown <len.brown@intel.com>2009-04-03 20:08:12 -0400
commit7237d3de78ff89ec2e18eae5fe962d063024fef5 (patch)
tree07d0196e9e3122546cc0366c686d363423bfe894
parent8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (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.c63
-rw-r--r--arch/x86/mm/srat_64.c30
-rw-r--r--drivers/acpi/numa.c46
-rw-r--r--drivers/acpi/processor_core.c26
-rw-r--r--drivers/acpi/tables.c30
-rw-r--r--include/linux/acpi.h1
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
262static int __init 262static int __init
263acpi_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
291static int __init
263acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) 292acpi_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
321static int __init 350static int __init
351acpi_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
369static int __init
322acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) 370acpi_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)
823static int __init acpi_parse_madt_lapic_entries(void) 871static 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 */
119void __init
120acpi_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 */
119void __init 149void __init
120acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) 150acpi_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
198void __init __attribute__ ((weak))
199acpi_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
207static int __init
208acpi_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
183static int __init 225static int __init
184acpi_parse_processor_affinity(struct acpi_subtable_header * header, 226acpi_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
430static 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;
448found:
449 *apic_id = tmp;
450 return 1;
451}
452
430static int map_lsapic_id(struct acpi_subtable_header *entry, 453static 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 */
97void acpi_numa_slit_init (struct acpi_table_slit *slit); 97void acpi_numa_slit_init (struct acpi_table_slit *slit);
98void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); 98void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
99void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
99void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); 100void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
100void acpi_numa_arch_fixup(void); 101void acpi_numa_arch_fixup(void);
101 102