FreeBSD/Linux Kernel Cross Reference
sys/x86/acpica/madt.c
1 /*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/10.4/sys/x86/acpica/madt.c 288461 2015-10-01 20:54:19Z jhb $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/smp.h>
36 #include <vm/vm.h>
37 #include <vm/pmap.h>
38
39 #include <x86/apicreg.h>
40 #include <machine/intr_machdep.h>
41 #include <machine/apicvar.h>
42
43 #include <contrib/dev/acpica/include/acpi.h>
44 #include <contrib/dev/acpica/include/actables.h>
45
46 #include <dev/acpica/acpivar.h>
47 #include <dev/pci/pcivar.h>
48
49 /* These two arrays are indexed by APIC IDs. */
50 static struct {
51 void *io_apic;
52 UINT32 io_vector;
53 } *ioapics;
54
55 static struct lapic_info {
56 u_int la_enabled;
57 u_int la_acpi_id;
58 } lapics[MAX_APIC_ID + 1];
59
60 static int madt_found_sci_override;
61 static ACPI_TABLE_MADT *madt;
62 static vm_paddr_t madt_physaddr;
63 static vm_offset_t madt_length;
64
65 static MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
66
67 static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
68 static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
69 static int madt_find_cpu(u_int acpi_id, u_int *apic_id);
70 static int madt_find_interrupt(int intr, void **apic, u_int *pin);
71 static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
72 static void madt_parse_interrupt_override(
73 ACPI_MADT_INTERRUPT_OVERRIDE *intr);
74 static void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
75 void *arg __unused);
76 static void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
77 static void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
78 static int madt_probe(void);
79 static int madt_probe_cpus(void);
80 static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
81 void *arg __unused);
82 static void madt_register(void *dummy);
83 static int madt_setup_local(void);
84 static int madt_setup_io(void);
85 static void madt_walk_table(acpi_subtable_handler *handler, void *arg);
86
87 static struct apic_enumerator madt_enumerator = {
88 "MADT",
89 madt_probe,
90 madt_probe_cpus,
91 madt_setup_local,
92 madt_setup_io
93 };
94
95 /*
96 * Look for an ACPI Multiple APIC Description Table ("APIC")
97 */
98 static int
99 madt_probe(void)
100 {
101
102 madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
103 if (madt_physaddr == 0)
104 return (ENXIO);
105 return (0);
106 }
107
108 /*
109 * Run through the MP table enumerating CPUs.
110 */
111 static int
112 madt_probe_cpus(void)
113 {
114
115 madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
116 madt_length = madt->Header.Length;
117 KASSERT(madt != NULL, ("Unable to re-map MADT"));
118 madt_walk_table(madt_probe_cpus_handler, NULL);
119 acpi_unmap_table(madt);
120 madt = NULL;
121 return (0);
122 }
123
124 /*
125 * Initialize the local APIC on the BSP.
126 */
127 static int
128 madt_setup_local(void)
129 {
130
131 madt = pmap_mapbios(madt_physaddr, madt_length);
132 lapic_init(madt->Address);
133 printf("ACPI APIC Table: <%.*s %.*s>\n",
134 (int)sizeof(madt->Header.OemId), madt->Header.OemId,
135 (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
136
137 /*
138 * We ignore 64-bit local APIC override entries. Should we
139 * perhaps emit a warning here if we find one?
140 */
141 return (0);
142 }
143
144 /*
145 * Enumerate I/O APICs and setup interrupt sources.
146 */
147 static int
148 madt_setup_io(void)
149 {
150 void *ioapic;
151 u_int pin;
152 int i;
153
154 /* Try to initialize ACPI so that we can access the FADT. */
155 i = acpi_Startup();
156 if (ACPI_FAILURE(i)) {
157 printf("MADT: ACPI Startup failed with %s\n",
158 AcpiFormatException(i));
159 printf("Try disabling either ACPI or apic support.\n");
160 panic("Using MADT but ACPI doesn't work");
161 }
162
163 ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
164 M_WAITOK | M_ZERO);
165
166 /* First, we run through adding I/O APIC's. */
167 madt_walk_table(madt_parse_apics, NULL);
168
169 /* Second, we run through the table tweaking interrupt sources. */
170 madt_walk_table(madt_parse_ints, NULL);
171
172 /*
173 * If there was not an explicit override entry for the SCI,
174 * force it to use level trigger and active-low polarity.
175 */
176 if (!madt_found_sci_override) {
177 if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
178 &pin) != 0)
179 printf("MADT: Could not find APIC for SCI IRQ %u\n",
180 AcpiGbl_FADT.SciInterrupt);
181 else {
182 printf(
183 "MADT: Forcing active-low polarity and level trigger for SCI\n");
184 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
185 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
186 }
187 }
188
189 /* Third, we register all the I/O APIC's. */
190 for (i = 0; i <= MAX_APIC_ID; i++)
191 if (ioapics[i].io_apic != NULL)
192 ioapic_register(ioapics[i].io_apic);
193
194 /* Finally, we throw the switch to enable the I/O APIC's. */
195 acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
196
197 free(ioapics, M_MADT);
198 ioapics = NULL;
199
200 return (0);
201 }
202
203 static void
204 madt_register(void *dummy __unused)
205 {
206
207 apic_register_enumerator(&madt_enumerator);
208 }
209 SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
210
211 /*
212 * Call the handler routine for each entry in the MADT table.
213 */
214 static void
215 madt_walk_table(acpi_subtable_handler *handler, void *arg)
216 {
217
218 acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
219 handler, arg);
220 }
221
222 static void
223 madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags)
224 {
225 struct lapic_info *la;
226
227 /*
228 * The MADT does not include a BSP flag, so we have to let the
229 * MP code figure out which CPU is the BSP on its own.
230 */
231 if (bootverbose)
232 printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
233 apic_id, acpi_id, flags & ACPI_MADT_ENABLED ?
234 "enabled" : "disabled");
235 if (!(flags & ACPI_MADT_ENABLED))
236 return;
237 if (apic_id > MAX_APIC_ID) {
238 printf("MADT: Ignoring local APIC ID %u (too high)\n",
239 apic_id);
240 return;
241 }
242
243 la = &lapics[apic_id];
244 KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id));
245 la->la_enabled = 1;
246 la->la_acpi_id = acpi_id;
247 lapic_create(apic_id, 0);
248 }
249
250 static void
251 madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
252 {
253 ACPI_MADT_LOCAL_APIC *proc;
254 ACPI_MADT_LOCAL_X2APIC *x2apic;
255
256 switch (entry->Type) {
257 case ACPI_MADT_TYPE_LOCAL_APIC:
258 proc = (ACPI_MADT_LOCAL_APIC *)entry;
259 madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags);
260 break;
261 case ACPI_MADT_TYPE_LOCAL_X2APIC:
262 x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry;
263 madt_add_cpu(x2apic->Uid, x2apic->LocalApicId,
264 x2apic->LapicFlags);
265 break;
266 }
267 }
268
269
270 /*
271 * Add an I/O APIC from an entry in the table.
272 */
273 static void
274 madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
275 {
276 ACPI_MADT_IO_APIC *apic;
277
278 switch (entry->Type) {
279 case ACPI_MADT_TYPE_IO_APIC:
280 apic = (ACPI_MADT_IO_APIC *)entry;
281 if (bootverbose)
282 printf(
283 "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
284 apic->Id, apic->GlobalIrqBase,
285 (void *)(uintptr_t)apic->Address);
286 if (apic->Id > MAX_APIC_ID)
287 panic("%s: I/O APIC ID %u too high", __func__,
288 apic->Id);
289 if (ioapics[apic->Id].io_apic != NULL)
290 panic("%s: Double APIC ID %u", __func__, apic->Id);
291 if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
292 printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
293 break;
294 }
295 ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
296 apic->Id, apic->GlobalIrqBase);
297 ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
298 break;
299 default:
300 break;
301 }
302 }
303
304 /*
305 * Determine properties of an interrupt source. Note that for ACPI these
306 * functions are only used for ISA interrupts, so we assume ISA bus values
307 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
308 * SCI for which we use Active Lo, Level Triggered.
309 */
310 static enum intr_polarity
311 interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
312 {
313
314 switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
315 default:
316 printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
317 /* FALLTHROUGH*/
318 case ACPI_MADT_POLARITY_CONFORMS:
319 if (Source == AcpiGbl_FADT.SciInterrupt)
320 return (INTR_POLARITY_LOW);
321 else
322 return (INTR_POLARITY_HIGH);
323 case ACPI_MADT_POLARITY_ACTIVE_HIGH:
324 return (INTR_POLARITY_HIGH);
325 case ACPI_MADT_POLARITY_ACTIVE_LOW:
326 return (INTR_POLARITY_LOW);
327 }
328 }
329
330 static enum intr_trigger
331 interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
332 {
333
334 switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
335 default:
336 printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
337 /*FALLTHROUGH*/
338 case ACPI_MADT_TRIGGER_CONFORMS:
339 if (Source == AcpiGbl_FADT.SciInterrupt)
340 return (INTR_TRIGGER_LEVEL);
341 else
342 return (INTR_TRIGGER_EDGE);
343 case ACPI_MADT_TRIGGER_EDGE:
344 return (INTR_TRIGGER_EDGE);
345 case ACPI_MADT_TRIGGER_LEVEL:
346 return (INTR_TRIGGER_LEVEL);
347 }
348 }
349
350 /*
351 * Find the local APIC ID associated with a given ACPI Processor ID.
352 */
353 static int
354 madt_find_cpu(u_int acpi_id, u_int *apic_id)
355 {
356 int i;
357
358 for (i = 0; i <= MAX_APIC_ID; i++) {
359 if (!lapics[i].la_enabled)
360 continue;
361 if (lapics[i].la_acpi_id != acpi_id)
362 continue;
363 *apic_id = i;
364 return (0);
365 }
366 return (ENOENT);
367 }
368
369 /*
370 * Find the IO APIC and pin on that APIC associated with a given global
371 * interrupt.
372 */
373 static int
374 madt_find_interrupt(int intr, void **apic, u_int *pin)
375 {
376 int i, best;
377
378 best = -1;
379 for (i = 0; i <= MAX_APIC_ID; i++) {
380 if (ioapics[i].io_apic == NULL ||
381 ioapics[i].io_vector > intr)
382 continue;
383 if (best == -1 ||
384 ioapics[best].io_vector < ioapics[i].io_vector)
385 best = i;
386 }
387 if (best == -1)
388 return (ENOENT);
389 *apic = ioapics[best].io_apic;
390 *pin = intr - ioapics[best].io_vector;
391 if (*pin > 32)
392 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
393 intr);
394 return (0);
395 }
396
397 /*
398 * Parse an interrupt source override for an ISA interrupt.
399 */
400 static void
401 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
402 {
403 void *new_ioapic, *old_ioapic;
404 u_int new_pin, old_pin;
405 enum intr_trigger trig;
406 enum intr_polarity pol;
407 char buf[64];
408
409 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
410 intr->GlobalIrq == 2) {
411 if (bootverbose)
412 printf("MADT: Skipping timer override\n");
413 return;
414 }
415 if (bootverbose)
416 printf("MADT: Interrupt override: source %u, irq %u\n",
417 intr->SourceIrq, intr->GlobalIrq);
418 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
419 if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
420 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
421 intr->GlobalIrq, intr->SourceIrq);
422 return;
423 }
424
425 /*
426 * Lookup the appropriate trigger and polarity modes for this
427 * entry.
428 */
429 trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
430 pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
431
432 /*
433 * If the SCI is identity mapped but has edge trigger and
434 * active-hi polarity or the force_sci_lo tunable is set,
435 * force it to use level/lo.
436 */
437 if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
438 madt_found_sci_override = 1;
439 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
440 if (tolower(buf[0]) == 'e')
441 trig = INTR_TRIGGER_EDGE;
442 else if (tolower(buf[0]) == 'l')
443 trig = INTR_TRIGGER_LEVEL;
444 else
445 panic(
446 "Invalid trigger %s: must be 'edge' or 'level'",
447 buf);
448 printf("MADT: Forcing SCI to %s trigger\n",
449 trig == INTR_TRIGGER_EDGE ? "edge" : "level");
450 }
451 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
452 if (tolower(buf[0]) == 'h')
453 pol = INTR_POLARITY_HIGH;
454 else if (tolower(buf[0]) == 'l')
455 pol = INTR_POLARITY_LOW;
456 else
457 panic(
458 "Invalid polarity %s: must be 'high' or 'low'",
459 buf);
460 printf("MADT: Forcing SCI to active %s polarity\n",
461 pol == INTR_POLARITY_HIGH ? "high" : "low");
462 }
463 }
464
465 /* Remap the IRQ if it is mapped to a different interrupt vector. */
466 if (intr->SourceIrq != intr->GlobalIrq) {
467 /*
468 * If the SCI is remapped to a non-ISA global interrupt,
469 * then override the vector we use to setup and allocate
470 * the interrupt.
471 */
472 if (intr->GlobalIrq > 15 &&
473 intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
474 acpi_OverrideInterruptLevel(intr->GlobalIrq);
475 else
476 ioapic_remap_vector(new_ioapic, new_pin,
477 intr->SourceIrq);
478 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
479 &old_pin) != 0)
480 printf("MADT: Could not find APIC for source IRQ %u\n",
481 intr->SourceIrq);
482 else if (ioapic_get_vector(old_ioapic, old_pin) ==
483 intr->SourceIrq)
484 ioapic_disable_pin(old_ioapic, old_pin);
485 }
486
487 /* Program the polarity and trigger mode. */
488 ioapic_set_triggermode(new_ioapic, new_pin, trig);
489 ioapic_set_polarity(new_ioapic, new_pin, pol);
490 }
491
492 /*
493 * Parse an entry for an NMI routed to an IO APIC.
494 */
495 static void
496 madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
497 {
498 void *ioapic;
499 u_int pin;
500
501 if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
502 printf("MADT: Could not find APIC for vector %u\n",
503 nmi->GlobalIrq);
504 return;
505 }
506
507 ioapic_set_nmi(ioapic, pin);
508 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
509 ioapic_set_triggermode(ioapic, pin,
510 interrupt_trigger(nmi->IntiFlags, 0));
511 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
512 ioapic_set_polarity(ioapic, pin,
513 interrupt_polarity(nmi->IntiFlags, 0));
514 }
515
516 /*
517 * Parse an entry for an NMI routed to a local APIC LVT pin.
518 */
519 static void
520 madt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags)
521 {
522 u_int apic_id, pin;
523
524 if (acpi_id == 0xffffffff)
525 apic_id = APIC_ID_ALL;
526 else if (madt_find_cpu(acpi_id, &apic_id) != 0) {
527 if (bootverbose)
528 printf("MADT: Ignoring local NMI routed to "
529 "ACPI CPU %u\n", acpi_id);
530 return;
531 }
532 if (Lint == 0)
533 pin = APIC_LVT_LINT0;
534 else
535 pin = APIC_LVT_LINT1;
536 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
537 if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
538 lapic_set_lvt_triggermode(apic_id, pin,
539 interrupt_trigger(IntiFlags, 0));
540 if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
541 lapic_set_lvt_polarity(apic_id, pin,
542 interrupt_polarity(IntiFlags, 0));
543 }
544
545 static void
546 madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
547 {
548
549 madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff :
550 nmi->ProcessorId, nmi->Lint, nmi->IntiFlags);
551 }
552
553 static void
554 madt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi)
555 {
556
557 madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags);
558 }
559
560 /*
561 * Parse interrupt entries.
562 */
563 static void
564 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
565 {
566
567 switch (entry->Type) {
568 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
569 madt_parse_interrupt_override(
570 (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
571 break;
572 case ACPI_MADT_TYPE_NMI_SOURCE:
573 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
574 break;
575 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
576 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
577 break;
578 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
579 madt_parse_local_x2apic_nmi(
580 (ACPI_MADT_LOCAL_X2APIC_NMI *)entry);
581 break;
582 }
583 }
584
585 /*
586 * Setup per-CPU ACPI IDs.
587 */
588 static void
589 madt_set_ids(void *dummy)
590 {
591 struct lapic_info *la;
592 struct pcpu *pc;
593 u_int i;
594
595 if (madt == NULL)
596 return;
597 CPU_FOREACH(i) {
598 pc = pcpu_find(i);
599 KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
600 la = &lapics[pc->pc_apic_id];
601 if (!la->la_enabled)
602 panic("APIC: CPU with APIC ID %u is not enabled",
603 pc->pc_apic_id);
604 pc->pc_acpi_id = la->la_acpi_id;
605 if (bootverbose)
606 printf("APIC: CPU %u has ACPI ID %u\n", i,
607 la->la_acpi_id);
608 }
609 }
610 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
Cache object: 758fd1a149521c7f31a16e1757e77929
|