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