FreeBSD/Linux Kernel Cross Reference
sys/i386/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 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: releng/6.2/sys/i386/acpica/madt.c 158448 2006-05-11 17:41:00Z njl $");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/smp.h>
39
40 #include <vm/vm.h>
41 #include <vm/vm_param.h>
42 #include <vm/pmap.h>
43
44 #include <machine/apicreg.h>
45 #include <machine/frame.h>
46 #include <machine/intr_machdep.h>
47 #include <machine/apicvar.h>
48 #include <machine/md_var.h>
49 #include <machine/specialreg.h>
50
51 #include <contrib/dev/acpica/acpi.h>
52 #include <contrib/dev/acpica/actables.h>
53 #include <dev/acpica/acpivar.h>
54 #include <dev/pci/pcivar.h>
55
56 #define NIOAPICS 32 /* Max number of I/O APICs */
57 #define NLAPICS 32 /* Max number of local APICs */
58
59 typedef void madt_entry_handler(APIC_HEADER *entry, void *arg);
60
61 /* These two arrays are indexed by APIC IDs. */
62 struct ioapic_info {
63 void *io_apic;
64 UINT32 io_vector;
65 } ioapics[NIOAPICS];
66
67 struct lapic_info {
68 u_int la_enabled:1;
69 u_int la_acpi_id:8;
70 } lapics[NLAPICS];
71
72 static int madt_found_sci_override;
73 static MULTIPLE_APIC_TABLE *madt;
74 static vm_paddr_t madt_physaddr;
75 static vm_offset_t madt_length;
76
77 MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
78
79 static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
80 static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
81 static int madt_find_cpu(u_int acpi_id, u_int *apic_id);
82 static int madt_find_interrupt(int intr, void **apic, u_int *pin);
83 static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
84 static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig);
85 static void madt_parse_apics(APIC_HEADER *entry, void *arg);
86 static void madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
87 static void madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
88 static void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
89 static void madt_parse_nmi(MADT_NMI_SOURCE *nmi);
90 static int madt_probe(void);
91 static int madt_probe_cpus(void);
92 static void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
93 static int madt_probe_table(vm_paddr_t address);
94 static void madt_register(void *dummy);
95 static int madt_setup_local(void);
96 static int madt_setup_io(void);
97 static void madt_unmap(void *data, vm_offset_t length);
98 static void madt_unmap_table(void *table);
99 static void madt_walk_table(madt_entry_handler *handler, void *arg);
100
101 static struct apic_enumerator madt_enumerator = {
102 "MADT",
103 madt_probe,
104 madt_probe_cpus,
105 madt_setup_local,
106 madt_setup_io
107 };
108
109 /*
110 * Code to abuse the crashdump map to map in the tables for the early
111 * probe. We cheat and make the following assumptions about how we
112 * use this KVA: page 0 is used to map in the first page of each table
113 * found via the RSDT or XSDT and pages 1 to n are used to map in the
114 * RSDT or XSDT. The offset is in pages; the length is in bytes.
115 */
116 static void *
117 madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
118 {
119 vm_offset_t va, off;
120 void *data;
121
122 off = pa & PAGE_MASK;
123 length = roundup(length + off, PAGE_SIZE);
124 pa = pa & PG_FRAME;
125 va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
126 (offset * PAGE_SIZE);
127 data = (void *)(va + off);
128 length -= PAGE_SIZE;
129 while (length > 0) {
130 va += PAGE_SIZE;
131 pa += PAGE_SIZE;
132 length -= PAGE_SIZE;
133 pmap_kenter(va, pa);
134 invlpg(va);
135 }
136 return (data);
137 }
138
139 static void
140 madt_unmap(void *data, vm_offset_t length)
141 {
142 vm_offset_t va, off;
143
144 va = (vm_offset_t)data;
145 off = va & PAGE_MASK;
146 length = roundup(length + off, PAGE_SIZE);
147 va &= ~PAGE_MASK;
148 while (length > 0) {
149 pmap_kremove(va);
150 invlpg(va);
151 va += PAGE_SIZE;
152 length -= PAGE_SIZE;
153 }
154 }
155
156 static void *
157 madt_map_table(vm_paddr_t pa, int offset, const char *sig)
158 {
159 ACPI_TABLE_HEADER *header;
160 vm_offset_t length;
161 void *table;
162
163 header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
164 if (strncmp(header->Signature, sig, 4) != 0) {
165 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
166 return (NULL);
167 }
168 length = header->Length;
169 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
170 table = madt_map(pa, offset, length);
171 if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
172 if (bootverbose)
173 printf("MADT: Failed checksum for table %s\n", sig);
174 madt_unmap(table, length);
175 return (NULL);
176 }
177 return (table);
178 }
179
180 static void
181 madt_unmap_table(void *table)
182 {
183 ACPI_TABLE_HEADER *header;
184
185 header = (ACPI_TABLE_HEADER *)table;
186 madt_unmap(table, header->Length);
187 }
188
189 /*
190 * Look for an ACPI Multiple APIC Description Table ("APIC")
191 */
192 static int
193 madt_probe(void)
194 {
195 ACPI_POINTER rsdp_ptr;
196 RSDP_DESCRIPTOR *rsdp;
197 RSDT_DESCRIPTOR *rsdt;
198 XSDT_DESCRIPTOR *xsdt;
199 int i, count;
200
201 if (resource_disabled("acpi", 0))
202 return (ENXIO);
203
204 /*
205 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn
206 * calls pmap_mapdev() to find the RSDP, we assume that we can use
207 * pmap_mapdev() to map the RSDP.
208 */
209 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
210 return (ENXIO);
211 #ifdef __i386__
212 KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
213 #endif
214 rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
215 if (rsdp == NULL) {
216 if (bootverbose)
217 printf("MADT: Failed to map RSDP\n");
218 return (ENXIO);
219 }
220
221 /*
222 * For ACPI >= 2.0, use the XSDT if it is available.
223 * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1
224 * in the crashdump area. Page 0 is used to map in the
225 * headers of candidate ACPI tables.
226 */
227 if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
228 /*
229 * AcpiOsGetRootPointer only verifies the checksum for
230 * the version 1.0 portion of the RSDP. Version 2.0 has
231 * an additional checksum that we verify first.
232 */
233 if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
234 if (bootverbose)
235 printf("MADT: RSDP failed extended checksum\n");
236 return (ENXIO);
237 }
238 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
239 if (xsdt == NULL) {
240 if (bootverbose)
241 printf("MADT: Failed to map XSDT\n");
242 return (ENXIO);
243 }
244 count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
245 sizeof(UINT64);
246 for (i = 0; i < count; i++)
247 if (madt_probe_table(xsdt->TableOffsetEntry[i]))
248 break;
249 madt_unmap_table(xsdt);
250 } else {
251 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
252 if (rsdt == NULL) {
253 if (bootverbose)
254 printf("MADT: Failed to map RSDT\n");
255 return (ENXIO);
256 }
257 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
258 sizeof(UINT32);
259 for (i = 0; i < count; i++)
260 if (madt_probe_table(rsdt->TableOffsetEntry[i]))
261 break;
262 madt_unmap_table(rsdt);
263 }
264 pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
265 if (madt_physaddr == 0) {
266 if (bootverbose)
267 printf("MADT: No MADT table found\n");
268 return (ENXIO);
269 }
270 if (bootverbose)
271 printf("MADT: Found table at 0x%jx\n",
272 (uintmax_t)madt_physaddr);
273
274 /*
275 * Verify that we can map the full table and that its checksum is
276 * correct, etc.
277 */
278 madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
279 if (madt == NULL)
280 return (ENXIO);
281 madt_unmap_table(madt);
282 madt = NULL;
283
284 return (0);
285 }
286
287 /*
288 * See if a given ACPI table is the MADT.
289 */
290 static int
291 madt_probe_table(vm_paddr_t address)
292 {
293 ACPI_TABLE_HEADER *table;
294
295 table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
296 if (table == NULL) {
297 if (bootverbose)
298 printf("MADT: Failed to map table at 0x%jx\n",
299 (uintmax_t)address);
300 return (0);
301 }
302 if (bootverbose)
303 printf("Table '%.4s' at 0x%jx\n", table->Signature,
304 (uintmax_t)address);
305
306 if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
307 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
308 return (0);
309 }
310 madt_physaddr = address;
311 madt_length = table->Length;
312 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
313 return (1);
314 }
315
316 /*
317 * Run through the MP table enumerating CPUs.
318 */
319 static int
320 madt_probe_cpus(void)
321 {
322
323 madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
324 KASSERT(madt != NULL, ("Unable to re-map MADT"));
325 madt_walk_table(madt_probe_cpus_handler, NULL);
326 madt_unmap_table(madt);
327 madt = NULL;
328 return (0);
329 }
330
331 /*
332 * Initialize the local APIC on the BSP.
333 */
334 static int
335 madt_setup_local(void)
336 {
337
338 madt = pmap_mapdev(madt_physaddr, madt_length);
339 lapic_init((uintptr_t)madt->LocalApicAddress);
340 printf("ACPI APIC Table: <%.*s %.*s>\n",
341 (int)sizeof(madt->OemId), madt->OemId,
342 (int)sizeof(madt->OemTableId), madt->OemTableId);
343
344 /*
345 * We ignore 64-bit local APIC override entries. Should we
346 * perhaps emit a warning here if we find one?
347 */
348 return (0);
349 }
350
351 /*
352 * Enumerate I/O APICs and setup interrupt sources.
353 */
354 static int
355 madt_setup_io(void)
356 {
357 void *ioapic;
358 u_int pin;
359 int i;
360
361 /* Try to initialize ACPI so that we can access the FADT. */
362 i = acpi_Startup();
363 if (ACPI_FAILURE(i)) {
364 printf("MADT: ACPI Startup failed with %s\n",
365 AcpiFormatException(i));
366 printf("Try disabling either ACPI or apic support.\n");
367 panic("Using MADT but ACPI doesn't work");
368 }
369
370 /* First, we run through adding I/O APIC's. */
371 madt_walk_table(madt_parse_apics, NULL);
372
373 /* Second, we run through the table tweaking interrupt sources. */
374 madt_walk_table(madt_parse_ints, NULL);
375
376 /*
377 * If there was not an explicit override entry for the SCI,
378 * force it to use level trigger and active-low polarity.
379 */
380 if (!madt_found_sci_override) {
381 if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
382 != 0)
383 printf("MADT: Could not find APIC for SCI IRQ %d\n",
384 AcpiGbl_FADT->SciInt);
385 else {
386 printf(
387 "MADT: Forcing active-low polarity and level trigger for SCI\n");
388 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
389 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
390 }
391 }
392
393 /* Third, we register all the I/O APIC's. */
394 for (i = 0; i < NIOAPICS; i++)
395 if (ioapics[i].io_apic != NULL)
396 ioapic_register(ioapics[i].io_apic);
397
398 /* Finally, we throw the switch to enable the I/O APIC's. */
399 acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
400
401 return (0);
402 }
403
404 static void
405 madt_register(void *dummy __unused)
406 {
407
408 apic_register_enumerator(&madt_enumerator);
409 }
410 SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
411
412 /*
413 * Call the handler routine for each entry in the MADT table.
414 */
415 static void
416 madt_walk_table(madt_entry_handler *handler, void *arg)
417 {
418 APIC_HEADER *entry;
419 u_char *p, *end;
420
421 end = (u_char *)(madt) + madt->Length;
422 for (p = (u_char *)(madt + 1); p < end; ) {
423 entry = (APIC_HEADER *)p;
424 handler(entry, arg);
425 p += entry->Length;
426 }
427 }
428
429 static void
430 madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
431 {
432 MADT_PROCESSOR_APIC *proc;
433 struct lapic_info *la;
434
435 switch (entry->Type) {
436 case APIC_PROCESSOR:
437 /*
438 * The MADT does not include a BSP flag, so we have to
439 * let the MP code figure out which CPU is the BSP on
440 * its own.
441 */
442 proc = (MADT_PROCESSOR_APIC *)entry;
443 if (bootverbose)
444 printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
445 proc->LocalApicId, proc->ProcessorId,
446 proc->ProcessorEnabled ? "enabled" : "disabled");
447 if (!proc->ProcessorEnabled)
448 break;
449 if (proc->LocalApicId >= NLAPICS)
450 panic("%s: CPU ID %d too high", __func__,
451 proc->LocalApicId);
452 la = &lapics[proc->LocalApicId];
453 KASSERT(la->la_enabled == 0,
454 ("Duplicate local APIC ID %d", proc->LocalApicId));
455 la->la_enabled = 1;
456 la->la_acpi_id = proc->ProcessorId;
457 lapic_create(proc->LocalApicId, 0);
458 break;
459 }
460 }
461
462
463 /*
464 * Add an I/O APIC from an entry in the table.
465 */
466 static void
467 madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
468 {
469 MADT_IO_APIC *apic;
470
471 switch (entry->Type) {
472 case APIC_IO:
473 apic = (MADT_IO_APIC *)entry;
474 if (bootverbose)
475 printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
476 apic->IoApicId, apic->Interrupt,
477 (void *)(uintptr_t)apic->Address);
478 if (apic->IoApicId >= NIOAPICS)
479 panic("%s: I/O APIC ID %d too high", __func__,
480 apic->IoApicId);
481 if (ioapics[apic->IoApicId].io_apic != NULL)
482 panic("%s: Double APIC ID %d", __func__,
483 apic->IoApicId);
484 ioapics[apic->IoApicId].io_apic = ioapic_create(
485 (uintptr_t)apic->Address, apic->IoApicId,
486 apic->Interrupt);
487 ioapics[apic->IoApicId].io_vector = apic->Interrupt;
488 break;
489 default:
490 break;
491 }
492 }
493
494 /*
495 * Determine properties of an interrupt source. Note that for ACPI these
496 * functions are only used for ISA interrupts, so we assume ISA bus values
497 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
498 * SCI for which we use Active Lo, Level Triggered.
499 */
500 static enum intr_polarity
501 interrupt_polarity(UINT16 Polarity, UINT8 Source)
502 {
503
504 switch (Polarity) {
505 case POLARITY_CONFORMS:
506 if (Source == AcpiGbl_FADT->SciInt)
507 return (INTR_POLARITY_LOW);
508 else
509 return (INTR_POLARITY_HIGH);
510 case POLARITY_ACTIVE_HIGH:
511 return (INTR_POLARITY_HIGH);
512 case POLARITY_ACTIVE_LOW:
513 return (INTR_POLARITY_LOW);
514 default:
515 panic("Bogus Interrupt Polarity");
516 }
517 }
518
519 static enum intr_trigger
520 interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
521 {
522
523 switch (TriggerMode) {
524 case TRIGGER_CONFORMS:
525 if (Source == AcpiGbl_FADT->SciInt)
526 return (INTR_TRIGGER_LEVEL);
527 else
528 return (INTR_TRIGGER_EDGE);
529 case TRIGGER_EDGE:
530 return (INTR_TRIGGER_EDGE);
531 case TRIGGER_LEVEL:
532 return (INTR_TRIGGER_LEVEL);
533 default:
534 panic("Bogus Interrupt Trigger Mode");
535 }
536 }
537
538 /*
539 * Find the local APIC ID associated with a given ACPI Processor ID.
540 */
541 static int
542 madt_find_cpu(u_int acpi_id, u_int *apic_id)
543 {
544 int i;
545
546 for (i = 0; i < NLAPICS; i++) {
547 if (!lapics[i].la_enabled)
548 continue;
549 if (lapics[i].la_acpi_id != acpi_id)
550 continue;
551 *apic_id = i;
552 return (0);
553 }
554 return (ENOENT);
555 }
556
557 /*
558 * Find the IO APIC and pin on that APIC associated with a given global
559 * interrupt.
560 */
561 static int
562 madt_find_interrupt(int intr, void **apic, u_int *pin)
563 {
564 int i, best;
565
566 best = -1;
567 for (i = 0; i < NIOAPICS; i++) {
568 if (ioapics[i].io_apic == NULL ||
569 ioapics[i].io_vector > intr)
570 continue;
571 if (best == -1 ||
572 ioapics[best].io_vector < ioapics[i].io_vector)
573 best = i;
574 }
575 if (best == -1)
576 return (ENOENT);
577 *apic = ioapics[best].io_apic;
578 *pin = intr - ioapics[best].io_vector;
579 if (*pin > 32)
580 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
581 intr);
582 return (0);
583 }
584
585 /*
586 * Parse an interrupt source override for an ISA interrupt.
587 */
588 static void
589 madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
590 {
591 void *new_ioapic, *old_ioapic;
592 u_int new_pin, old_pin;
593 enum intr_trigger trig;
594 enum intr_polarity pol;
595 char buf[64];
596
597 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->Source == 0 &&
598 intr->Interrupt == 2) {
599 if (bootverbose)
600 printf("MADT: Skipping timer override\n");
601 return;
602 }
603 if (bootverbose)
604 printf("MADT: Interrupt override: source %u, irq %u\n",
605 intr->Source, intr->Interrupt);
606 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
607 if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
608 &new_pin) != 0) {
609 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
610 intr->Interrupt, intr->Source);
611 return;
612 }
613
614 /*
615 * Lookup the appropriate trigger and polarity modes for this
616 * entry.
617 */
618 trig = interrupt_trigger(intr->TriggerMode, intr->Source);
619 pol = interrupt_polarity(intr->Polarity, intr->Source);
620
621 /*
622 * If the SCI is identity mapped but has edge trigger and
623 * active-hi polarity or the force_sci_lo tunable is set,
624 * force it to use level/lo.
625 */
626 if (intr->Source == AcpiGbl_FADT->SciInt) {
627 madt_found_sci_override = 1;
628 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
629 if (tolower(buf[0]) == 'e')
630 trig = INTR_TRIGGER_EDGE;
631 else if (tolower(buf[0]) == 'l')
632 trig = INTR_TRIGGER_LEVEL;
633 else
634 panic(
635 "Invalid trigger %s: must be 'edge' or 'level'",
636 buf);
637 printf("MADT: Forcing SCI to %s trigger\n",
638 trig == INTR_TRIGGER_EDGE ? "edge" : "level");
639 }
640 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
641 if (tolower(buf[0]) == 'h')
642 pol = INTR_POLARITY_HIGH;
643 else if (tolower(buf[0]) == 'l')
644 pol = INTR_POLARITY_LOW;
645 else
646 panic(
647 "Invalid polarity %s: must be 'high' or 'low'",
648 buf);
649 printf("MADT: Forcing SCI to active %s polarity\n",
650 pol == INTR_POLARITY_HIGH ? "high" : "low");
651 }
652 }
653
654 /* Remap the IRQ if it is mapped to a different interrupt vector. */
655 if (intr->Source != intr->Interrupt) {
656 /*
657 * If the SCI is remapped to a non-ISA global interrupt,
658 * then override the vector we use to setup and allocate
659 * the interrupt.
660 */
661 if (intr->Interrupt > 15 &&
662 intr->Source == AcpiGbl_FADT->SciInt)
663 acpi_OverrideInterruptLevel(intr->Interrupt);
664 else
665 ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
666 if (madt_find_interrupt(intr->Source, &old_ioapic,
667 &old_pin) != 0)
668 printf("MADT: Could not find APIC for source IRQ %d\n",
669 intr->Source);
670 else if (ioapic_get_vector(old_ioapic, old_pin) ==
671 intr->Source)
672 ioapic_disable_pin(old_ioapic, old_pin);
673 }
674
675 /* Program the polarity and trigger mode. */
676 ioapic_set_triggermode(new_ioapic, new_pin, trig);
677 ioapic_set_polarity(new_ioapic, new_pin, pol);
678 }
679
680 /*
681 * Parse an entry for an NMI routed to an IO APIC.
682 */
683 static void
684 madt_parse_nmi(MADT_NMI_SOURCE *nmi)
685 {
686 void *ioapic;
687 u_int pin;
688
689 if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
690 printf("MADT: Could not find APIC for vector %d\n",
691 nmi->Interrupt);
692 return;
693 }
694
695 ioapic_set_nmi(ioapic, pin);
696 if (nmi->TriggerMode != TRIGGER_CONFORMS)
697 ioapic_set_triggermode(ioapic, pin,
698 interrupt_trigger(nmi->TriggerMode, 0));
699 if (nmi->Polarity != TRIGGER_CONFORMS)
700 ioapic_set_polarity(ioapic, pin,
701 interrupt_polarity(nmi->Polarity, 0));
702 }
703
704 /*
705 * Parse an entry for an NMI routed to a local APIC LVT pin.
706 */
707 static void
708 madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
709 {
710 u_int apic_id, pin;
711
712 if (nmi->ProcessorId == 0xff)
713 apic_id = APIC_ID_ALL;
714 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
715 if (bootverbose)
716 printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
717 nmi->ProcessorId);
718 return;
719 }
720 if (nmi->Lint == 0)
721 pin = LVT_LINT0;
722 else
723 pin = LVT_LINT1;
724 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
725 if (nmi->TriggerMode != TRIGGER_CONFORMS)
726 lapic_set_lvt_triggermode(apic_id, pin,
727 interrupt_trigger(nmi->TriggerMode, 0));
728 if (nmi->Polarity != POLARITY_CONFORMS)
729 lapic_set_lvt_polarity(apic_id, pin,
730 interrupt_polarity(nmi->Polarity, 0));
731 }
732
733 /*
734 * Parse interrupt entries.
735 */
736 static void
737 madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
738 {
739
740 switch (entry->Type) {
741 case APIC_XRUPT_OVERRIDE:
742 madt_parse_interrupt_override(
743 (MADT_INTERRUPT_OVERRIDE *)entry);
744 break;
745 case APIC_NMI:
746 madt_parse_nmi((MADT_NMI_SOURCE *)entry);
747 break;
748 case APIC_LOCAL_NMI:
749 madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
750 break;
751 }
752 }
753
754 /*
755 * Setup per-CPU ACPI IDs.
756 */
757 static void
758 madt_set_ids(void *dummy)
759 {
760 struct lapic_info *la;
761 struct pcpu *pc;
762 u_int i;
763
764 if (madt == NULL)
765 return;
766 for (i = 0; i <= mp_maxid; i++) {
767 if (CPU_ABSENT(i))
768 continue;
769 pc = pcpu_find(i);
770 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
771 la = &lapics[pc->pc_apic_id];
772 if (!la->la_enabled)
773 panic("APIC: CPU with APIC ID %u is not enabled",
774 pc->pc_apic_id);
775 pc->pc_acpi_id = la->la_acpi_id;
776 if (bootverbose)
777 printf("APIC: CPU %u has ACPI ID %u\n", i,
778 la->la_acpi_id);
779 }
780 }
781 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
Cache object: 7120f66704f86bbe31ad042f80cb2f87
|