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

Cache object: 35cc16d85c4d813bf70786014ed830a3


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