The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/x86/acpica/madt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 758fd1a149521c7f31a16e1757e77929


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.