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

Cache object: ad37f9445718d4d24a3cb292858ea461


[ 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.