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