]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/acpica/madt.c
guestrpc module to handle VMware backdoor port GuestRPC functionality
[FreeBSD/FreeBSD.git] / sys / x86 / acpica / madt.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/kernel.h>
32 #include <sys/limits.h>
33 #include <sys/malloc.h>
34 #include <sys/smp.h>
35 #include <vm/vm.h>
36 #include <vm/pmap.h>
37
38 #include <x86/apicreg.h>
39 #include <machine/intr_machdep.h>
40 #include <x86/apicvar.h>
41 #include <machine/md_var.h>
42 #include <x86/vmware.h>
43
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/aclocal.h>
46 #include <contrib/dev/acpica/include/actables.h>
47
48 #include <dev/acpica/acpivar.h>
49 #include <dev/pci/pcivar.h>
50
51 /* These two arrays are indexed by APIC IDs. */
52 static struct {
53         void *io_apic;
54         UINT32 io_vector;
55 } *ioapics;
56
57 static struct lapic_info {
58         u_int la_enabled;
59         u_int la_acpi_id;
60 } *lapics;
61
62 int madt_found_sci_override;
63 static ACPI_TABLE_MADT *madt;
64 static vm_paddr_t madt_physaddr;
65 static vm_offset_t madt_length;
66
67 static MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
68
69 static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
70 static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
71 static int      madt_find_cpu(u_int acpi_id, u_int *apic_id);
72 static int      madt_find_interrupt(int intr, void **apic, u_int *pin);
73 static void     madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
74 static void     madt_parse_interrupt_override(
75                     ACPI_MADT_INTERRUPT_OVERRIDE *intr);
76 static void     madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
77                     void *arg __unused);
78 static void     madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
79 static void     madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
80 static int      madt_probe(void);
81 static int      madt_probe_cpus(void);
82 static void     madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
83                     void *arg __unused);
84 static void     madt_setup_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
85                     void *arg __unused);
86 static void     madt_register(void *dummy);
87 static int      madt_setup_local(void);
88 static int      madt_setup_io(void);
89 static void     madt_walk_table(acpi_subtable_handler *handler, void *arg);
90
91 static struct apic_enumerator madt_enumerator = {
92         .apic_name = "MADT",
93         .apic_probe = madt_probe,
94         .apic_probe_cpus = madt_probe_cpus,
95         .apic_setup_local = madt_setup_local,
96         .apic_setup_io = madt_setup_io
97 };
98
99 /*
100  * Look for an ACPI Multiple APIC Description Table ("APIC")
101  */
102 static int
103 madt_probe(void)
104 {
105
106         madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
107         if (madt_physaddr == 0)
108                 return (ENXIO);
109         return (-50);
110 }
111
112 /*
113  * Run through the MP table enumerating CPUs.
114  */
115 static int
116 madt_probe_cpus(void)
117 {
118
119         madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
120         madt_length = madt->Header.Length;
121         KASSERT(madt != NULL, ("Unable to re-map MADT"));
122         madt_walk_table(madt_probe_cpus_handler, NULL);
123         acpi_unmap_table(madt);
124         madt = NULL;
125         return (0);
126 }
127
128 static const char *x2apic_sandy_dis[] = {
129         "LENOVO",
130         "ASUSTeK Computer Inc.",
131         "SAMSUNG ELECTRONICS CO., LTD.",
132 };
133
134 /*
135  * Automatically detect several configurations where x2APIC mode is
136  * known to cause troubles.  User can override the setting with
137  * hw.x2apic_enable tunable.
138  */
139 static const char *
140 madt_x2apic_disable_reason(void)
141 {
142         ACPI_TABLE_DMAR *dmartbl;
143         vm_paddr_t dmartbl_physaddr;
144         const char *reason;
145         char *hw_vendor;
146         u_int p[4];
147         int i;
148
149         reason = NULL;
150
151         dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
152         if (dmartbl_physaddr != 0) {
153                 dmartbl = acpi_map_table(dmartbl_physaddr, ACPI_SIG_DMAR);
154                 if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
155                         reason = "by DMAR table";
156                 acpi_unmap_table(dmartbl);
157                 if (reason != NULL)
158                         return (reason);
159         }
160
161         if (vm_guest == VM_GUEST_VMWARE) {
162                 vmware_hvcall(0, VMW_HVCMD_GETVCPU_INFO,
163                     VMW_HVCMD_DEFAULT_PARAM, p);
164                 if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 ||
165                     (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0)
166                         return ("inside VMWare without intr redirection");
167         }
168
169         if (vm_guest == VM_GUEST_NO &&
170             CPUID_TO_FAMILY(cpu_id) == 0x6 &&
171             CPUID_TO_MODEL(cpu_id) == 0x2a) {
172                 hw_vendor = kern_getenv("smbios.planar.maker");
173                 /*
174                  * It seems that some SandyBridge-based notebook
175                  * BIOSes have a bug which prevents booting AP in
176                  * x2APIC mode.  Since the only way to detect mobile
177                  * CPU is to check northbridge pci id, which cannot be
178                  * done that early, disable x2APIC for all such
179                  * machines.
180                  */
181                 if (hw_vendor != NULL) {
182                         for (i = 0; i < nitems(x2apic_sandy_dis); i++) {
183                                 if (strcmp(hw_vendor, x2apic_sandy_dis[i]) ==
184                                     0) {
185                                         reason =
186                                 "for a suspected SandyBridge BIOS bug";
187                                         break;
188                                 }
189                         }
190                         freeenv(hw_vendor);
191                 }
192                 if (reason != NULL)
193                         return (reason);
194         }
195
196         return (NULL);
197 }
198
199 /*
200  * Initialize the local APIC on the BSP.
201  */
202 static int
203 madt_setup_local(void)
204 {
205         const char *reason;
206         int user_x2apic;
207         bool bios_x2apic;
208
209         if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
210                 reason = madt_x2apic_disable_reason();
211                 bios_x2apic = lapic_is_x2apic();
212                 if (reason != NULL && bios_x2apic) {
213                         if (bootverbose)
214                                 printf("x2APIC should be disabled %s but "
215                                     "already enabled by BIOS; enabling.\n",
216                                      reason);
217                         reason = NULL;
218                 }
219                 if (reason == NULL)
220                         x2apic_mode = 1;
221                 else if (bootverbose)
222                         printf("x2APIC available but disabled %s\n", reason);
223                 user_x2apic = x2apic_mode;
224                 TUNABLE_INT_FETCH("hw.apic.x2apic_mode", &user_x2apic);
225                 if (user_x2apic != x2apic_mode) {
226                         if (bios_x2apic && !user_x2apic)
227                                 printf("x2APIC disabled by tunable and "
228                                     "enabled by BIOS; ignoring tunable.");
229                         else
230                                 x2apic_mode = user_x2apic;
231                 }
232         }
233
234         /*
235          * Truncate max_apic_id if not in x2APIC mode. Some structures
236          * will already be allocated with the previous max_apic_id, but
237          * at least we can prevent wasting more memory elsewhere.
238          */
239         if (!x2apic_mode)
240                 max_apic_id = min(max_apic_id, xAPIC_MAX_APIC_ID);
241
242         madt = pmap_mapbios(madt_physaddr, madt_length);
243         lapics = malloc(sizeof(*lapics) * (max_apic_id + 1), M_MADT,
244             M_WAITOK | M_ZERO);
245         madt_walk_table(madt_setup_cpus_handler, NULL);
246
247         lapic_init(madt->Address);
248         printf("ACPI APIC Table: <%.*s %.*s>\n",
249             (int)sizeof(madt->Header.OemId), madt->Header.OemId,
250             (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
251
252         /*
253          * We ignore 64-bit local APIC override entries.  Should we
254          * perhaps emit a warning here if we find one?
255          */
256         return (0);
257 }
258
259 /*
260  * Enumerate I/O APICs and setup interrupt sources.
261  */
262 static int
263 madt_setup_io(void)
264 {
265         void *ioapic;
266         u_int pin;
267         int i;
268
269         KASSERT(lapics != NULL, ("local APICs not initialized"));
270
271         /* Try to initialize ACPI so that we can access the FADT. */
272         i = acpi_Startup();
273         if (ACPI_FAILURE(i)) {
274                 printf("MADT: ACPI Startup failed with %s\n",
275                     AcpiFormatException(i));
276                 printf("Try disabling either ACPI or apic support.\n");
277                 panic("Using MADT but ACPI doesn't work");
278         }
279
280         ioapics = malloc(sizeof(*ioapics) * (IOAPIC_MAX_ID + 1), M_MADT,
281             M_WAITOK | M_ZERO);
282
283         /* First, we run through adding I/O APIC's. */
284         madt_walk_table(madt_parse_apics, NULL);
285
286         /* Second, we run through the table tweaking interrupt sources. */
287         madt_walk_table(madt_parse_ints, NULL);
288
289         /*
290          * If there was not an explicit override entry for the SCI,
291          * force it to use level trigger and active-low polarity.
292          */
293         if (!madt_found_sci_override) {
294                 if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
295                     &pin) != 0)
296                         printf("MADT: Could not find APIC for SCI IRQ %u\n",
297                             AcpiGbl_FADT.SciInterrupt);
298                 else {
299                         printf(
300         "MADT: Forcing active-low polarity and level trigger for SCI\n");
301                         ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
302                         ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
303                 }
304         }
305
306         /* Third, we register all the I/O APIC's. */
307         for (i = 0; i <= IOAPIC_MAX_ID; i++)
308                 if (ioapics[i].io_apic != NULL)
309                         ioapic_register(ioapics[i].io_apic);
310
311         /* Finally, we throw the switch to enable the I/O APIC's. */
312         acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
313
314         free(ioapics, M_MADT);
315         ioapics = NULL;
316
317         /* NB: this is the last use of the lapics array. */
318         free(lapics, M_MADT);
319         lapics = NULL;
320
321         return (0);
322 }
323
324 static void
325 madt_register(void *dummy __unused)
326 {
327
328         apic_register_enumerator(&madt_enumerator);
329 }
330 SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
331
332 /*
333  * Call the handler routine for each entry in the MADT table.
334  */
335 static void
336 madt_walk_table(acpi_subtable_handler *handler, void *arg)
337 {
338
339         acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
340             handler, arg);
341 }
342
343 static void
344 madt_parse_cpu(unsigned int apic_id, unsigned int flags)
345 {
346
347         if (!(flags & ACPI_MADT_ENABLED) ||
348 #ifdef SMP
349             mp_ncpus == MAXCPU ||
350 #endif
351             apic_id > MAX_APIC_ID)
352                 return;
353
354 #ifdef SMP
355         mp_ncpus++;
356         mp_maxid = mp_ncpus - 1;
357 #endif
358         max_apic_id = max(apic_id, max_apic_id);
359 }
360
361 static void
362 madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags)
363 {
364         struct lapic_info *la;
365
366         /*
367          * The MADT does not include a BSP flag, so we have to let the
368          * MP code figure out which CPU is the BSP on its own.
369          */
370         if (bootverbose)
371                 printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
372                     apic_id, acpi_id, flags & ACPI_MADT_ENABLED ?
373                     "enabled" : "disabled");
374         if (!(flags & ACPI_MADT_ENABLED))
375                 return;
376         if (apic_id > max_apic_id) {
377                 printf("MADT: Ignoring local APIC ID %u (too high)\n",
378                     apic_id);
379                 return;
380         }
381
382         la = &lapics[apic_id];
383         KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id));
384         la->la_enabled = 1;
385         la->la_acpi_id = acpi_id;
386         lapic_create(apic_id, 0);
387 }
388
389 static void
390 madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
391 {
392         ACPI_MADT_LOCAL_APIC *proc;
393         ACPI_MADT_LOCAL_X2APIC *x2apic;
394
395         switch (entry->Type) {
396         case ACPI_MADT_TYPE_LOCAL_APIC:
397                 proc = (ACPI_MADT_LOCAL_APIC *)entry;
398                 madt_parse_cpu(proc->Id, proc->LapicFlags);
399                 break;
400         case ACPI_MADT_TYPE_LOCAL_X2APIC:
401                 x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry;
402                 madt_parse_cpu(x2apic->LocalApicId, x2apic->LapicFlags);
403                 break;
404         }
405 }
406
407 static void
408 madt_setup_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
409 {
410         ACPI_MADT_LOCAL_APIC *proc;
411         ACPI_MADT_LOCAL_X2APIC *x2apic;
412
413         switch (entry->Type) {
414         case ACPI_MADT_TYPE_LOCAL_APIC:
415                 proc = (ACPI_MADT_LOCAL_APIC *)entry;
416                 madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags);
417                 break;
418         case ACPI_MADT_TYPE_LOCAL_X2APIC:
419                 x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry;
420                 madt_add_cpu(x2apic->Uid, x2apic->LocalApicId,
421                     x2apic->LapicFlags);
422                 break;
423         }
424 }
425
426 /*
427  * Add an I/O APIC from an entry in the table.
428  */
429 static void
430 madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
431 {
432         ACPI_MADT_IO_APIC *apic;
433
434         switch (entry->Type) {
435         case ACPI_MADT_TYPE_IO_APIC:
436                 apic = (ACPI_MADT_IO_APIC *)entry;
437                 if (bootverbose)
438                         printf(
439                             "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
440                             apic->Id, apic->GlobalIrqBase,
441                             (void *)(uintptr_t)apic->Address);
442                 if (apic->Id > IOAPIC_MAX_ID)
443                         panic("%s: I/O APIC ID %u too high", __func__,
444                             apic->Id);
445                 if (ioapics[apic->Id].io_apic != NULL)
446                         panic("%s: Double APIC ID %u", __func__, apic->Id);
447                 ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
448                     apic->Id, apic->GlobalIrqBase);
449                 ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
450                 break;
451         default:
452                 break;
453         }
454 }
455
456 /*
457  * Determine properties of an interrupt source.  Note that for ACPI these
458  * functions are only used for ISA interrupts, so we assume ISA bus values
459  * (Active Hi, Edge Triggered) for conforming values except for the ACPI
460  * SCI for which we use Active Lo, Level Triggered.
461  */
462 static enum intr_polarity
463 interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
464 {
465
466         switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
467         default:
468                 printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
469                 /* FALLTHROUGH*/
470         case ACPI_MADT_POLARITY_CONFORMS:
471                 if (Source == AcpiGbl_FADT.SciInterrupt)
472                         return (INTR_POLARITY_LOW);
473                 else
474                         return (INTR_POLARITY_HIGH);
475         case ACPI_MADT_POLARITY_ACTIVE_HIGH:
476                 return (INTR_POLARITY_HIGH);
477         case ACPI_MADT_POLARITY_ACTIVE_LOW:
478                 return (INTR_POLARITY_LOW);
479         }
480 }
481
482 static enum intr_trigger
483 interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
484 {
485
486         switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
487         default:
488                 printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
489                 /*FALLTHROUGH*/
490         case ACPI_MADT_TRIGGER_CONFORMS:
491                 if (Source == AcpiGbl_FADT.SciInterrupt)
492                         return (INTR_TRIGGER_LEVEL);
493                 else
494                         return (INTR_TRIGGER_EDGE);
495         case ACPI_MADT_TRIGGER_EDGE:
496                 return (INTR_TRIGGER_EDGE);
497         case ACPI_MADT_TRIGGER_LEVEL:
498                 return (INTR_TRIGGER_LEVEL);
499         }
500 }
501
502 /*
503  * Find the local APIC ID associated with a given ACPI Processor ID.
504  */
505 static int
506 madt_find_cpu(u_int acpi_id, u_int *apic_id)
507 {
508         int i;
509
510         for (i = 0; i <= max_apic_id; i++) {
511                 if (!lapics[i].la_enabled)
512                         continue;
513                 if (lapics[i].la_acpi_id != acpi_id)
514                         continue;
515                 *apic_id = i;
516                 return (0);
517         }
518         return (ENOENT);
519 }
520
521 /*
522  * Find the IO APIC and pin on that APIC associated with a given global
523  * interrupt.
524  */
525 static int
526 madt_find_interrupt(int intr, void **apic, u_int *pin)
527 {
528         int i, best;
529
530         best = -1;
531         for (i = 0; i <= IOAPIC_MAX_ID; i++) {
532                 if (ioapics[i].io_apic == NULL ||
533                     ioapics[i].io_vector > intr)
534                         continue;
535                 if (best == -1 ||
536                     ioapics[best].io_vector < ioapics[i].io_vector)
537                         best = i;
538         }
539         if (best == -1)
540                 return (ENOENT);
541         *apic = ioapics[best].io_apic;
542         *pin = intr - ioapics[best].io_vector;
543         if (*pin > 32)
544                 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
545                     intr);
546         return (0);
547 }
548
549 void
550 madt_parse_interrupt_values(void *entry,
551     enum intr_trigger *trig, enum intr_polarity *pol)
552 {
553         ACPI_MADT_INTERRUPT_OVERRIDE *intr;
554         char buf[64];
555
556         intr = entry;
557
558         if (bootverbose)
559                 printf("MADT: Interrupt override: source %u, irq %u\n",
560                     intr->SourceIrq, intr->GlobalIrq);
561         KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
562
563         /*
564          * Lookup the appropriate trigger and polarity modes for this
565          * entry.
566          */
567         *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
568         *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
569
570         /*
571          * If the SCI is identity mapped but has edge trigger and
572          * active-hi polarity or the force_sci_lo tunable is set,
573          * force it to use level/lo.
574          */
575         if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
576                 madt_found_sci_override = 1;
577                 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
578                         if (tolower(buf[0]) == 'e')
579                                 *trig = INTR_TRIGGER_EDGE;
580                         else if (tolower(buf[0]) == 'l')
581                                 *trig = INTR_TRIGGER_LEVEL;
582                         else
583                                 panic(
584                                 "Invalid trigger %s: must be 'edge' or 'level'",
585                                     buf);
586                         printf("MADT: Forcing SCI to %s trigger\n",
587                             *trig == INTR_TRIGGER_EDGE ? "edge" : "level");
588                 }
589                 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
590                         if (tolower(buf[0]) == 'h')
591                                 *pol = INTR_POLARITY_HIGH;
592                         else if (tolower(buf[0]) == 'l')
593                                 *pol = INTR_POLARITY_LOW;
594                         else
595                                 panic(
596                                 "Invalid polarity %s: must be 'high' or 'low'",
597                                     buf);
598                         printf("MADT: Forcing SCI to active %s polarity\n",
599                             *pol == INTR_POLARITY_HIGH ? "high" : "low");
600                 }
601         }
602 }
603
604 /*
605  * Parse an interrupt source override for an ISA interrupt.
606  */
607 static void
608 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
609 {
610         void *new_ioapic, *old_ioapic;
611         u_int new_pin, old_pin;
612         enum intr_trigger trig;
613         enum intr_polarity pol;
614
615         if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
616             intr->GlobalIrq == 2) {
617                 if (bootverbose)
618                         printf("MADT: Skipping timer override\n");
619                 return;
620         }
621
622         if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
623                 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
624                     intr->GlobalIrq, intr->SourceIrq);
625                 return;
626         }
627
628         madt_parse_interrupt_values(intr, &trig, &pol);
629
630         /* Remap the IRQ if it is mapped to a different interrupt vector. */
631         if (intr->SourceIrq != intr->GlobalIrq) {
632                 /*
633                  * If the SCI is remapped to a non-ISA global interrupt,
634                  * then override the vector we use to setup and allocate
635                  * the interrupt.
636                  */
637                 if (intr->GlobalIrq > 15 &&
638                     intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
639                         acpi_OverrideInterruptLevel(intr->GlobalIrq);
640                 else
641                         ioapic_remap_vector(new_ioapic, new_pin,
642                             intr->SourceIrq);
643                 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
644                     &old_pin) != 0)
645                         printf("MADT: Could not find APIC for source IRQ %u\n",
646                             intr->SourceIrq);
647                 else if (ioapic_get_vector(old_ioapic, old_pin) ==
648                     intr->SourceIrq)
649                         ioapic_disable_pin(old_ioapic, old_pin);
650         }
651
652         /* Program the polarity and trigger mode. */
653         ioapic_set_triggermode(new_ioapic, new_pin, trig);
654         ioapic_set_polarity(new_ioapic, new_pin, pol);
655 }
656
657 /*
658  * Parse an entry for an NMI routed to an IO APIC.
659  */
660 static void
661 madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
662 {
663         void *ioapic;
664         u_int pin;
665
666         if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
667                 printf("MADT: Could not find APIC for vector %u\n",
668                     nmi->GlobalIrq);
669                 return;
670         }
671
672         ioapic_set_nmi(ioapic, pin);
673         if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
674                 ioapic_set_triggermode(ioapic, pin,
675                     interrupt_trigger(nmi->IntiFlags, 0));
676         if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
677                 ioapic_set_polarity(ioapic, pin,
678                     interrupt_polarity(nmi->IntiFlags, 0));
679 }
680
681 /*
682  * Parse an entry for an NMI routed to a local APIC LVT pin.
683  */
684 static void
685 madt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags)
686 {
687         u_int apic_id, pin;
688
689         if (acpi_id == 0xffffffff)
690                 apic_id = APIC_ID_ALL;
691         else if (madt_find_cpu(acpi_id, &apic_id) != 0) {
692                 if (bootverbose)
693                         printf("MADT: Ignoring local NMI routed to "
694                             "ACPI CPU %u\n", acpi_id);
695                 return;
696         }
697         if (Lint == 0)
698                 pin = APIC_LVT_LINT0;
699         else
700                 pin = APIC_LVT_LINT1;
701         lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
702         if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
703                 lapic_set_lvt_triggermode(apic_id, pin,
704                     interrupt_trigger(IntiFlags, 0));
705         if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
706                 lapic_set_lvt_polarity(apic_id, pin,
707                     interrupt_polarity(IntiFlags, 0));
708 }
709
710 static void
711 madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
712 {
713
714         madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff :
715             nmi->ProcessorId, nmi->Lint, nmi->IntiFlags);
716 }
717
718 static void
719 madt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi)
720 {
721
722         madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags);
723 }
724
725 /*
726  * Parse interrupt entries.
727  */
728 static void
729 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
730 {
731
732         switch (entry->Type) {
733         case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
734                 madt_parse_interrupt_override(
735                         (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
736                 break;
737         case ACPI_MADT_TYPE_NMI_SOURCE:
738                 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
739                 break;
740         case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
741                 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
742                 break;
743         case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
744                 madt_parse_local_x2apic_nmi(
745                     (ACPI_MADT_LOCAL_X2APIC_NMI *)entry);
746                 break;
747         }
748 }
749
750 /*
751  * Setup per-CPU ACPI IDs.
752  */
753 static void
754 madt_set_ids(void *dummy)
755 {
756         struct lapic_info *la;
757         struct pcpu *pc;
758         u_int i;
759
760         if (madt == NULL)
761                 return;
762
763         KASSERT(lapics != NULL, ("local APICs not initialized"));
764
765         CPU_FOREACH(i) {
766                 pc = pcpu_find(i);
767                 KASSERT(pc != NULL, ("no pcpu data for CPU %u", 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_MIDDLE, madt_set_ids, NULL);