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/5.2/sys/i386/acpica/madt.c 123133 2003-12-03 20:33:18Z 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 
   40 #include <vm/vm.h>
   41 #include <vm/vm_param.h>
   42 #include <vm/pmap.h>
   43 
   44 #include <machine/apicreg.h>
   45 #include <machine/frame.h>
   46 #include <machine/intr_machdep.h>
   47 #include <machine/apicvar.h>
   48 #include <machine/md_var.h>
   49 #include <machine/specialreg.h>
   50 
   51 #include "acpi.h"
   52 #include <dev/acpica/acpivar.h>
   53 #include <dev/acpica/madt.h>
   54 #include <dev/pci/pcivar.h>
   55 
   56 #define NIOAPICS                32      /* Max number of I/O APICs */
   57 #define NLAPICS                 32      /* Max number of local APICs */
   58 
   59 typedef void madt_entry_handler(APIC_HEADER *entry, void *arg);
   60 
   61 /* These two arrays are indexed by APIC IDs. */
   62 struct ioapic_info {
   63         void *io_apic;
   64         UINT32 io_vector;
   65 } ioapics[NIOAPICS];
   66 
   67 struct lapic_info {
   68         u_int la_present:1;
   69         u_int la_enabled:1;
   70         u_int la_apic_id:8;
   71 } lapics[NLAPICS + 1];
   72 
   73 static APIC_TABLE *madt;
   74 static vm_paddr_t madt_physaddr;
   75 static vm_offset_t madt_length;
   76 
   77 MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
   78 
   79 static u_char   interrupt_polarity(UINT16 Polarity);
   80 static u_char   interrupt_trigger(UINT16 TriggerMode);
   81 static int      madt_find_cpu(u_int acpi_id, u_int *apic_id);
   82 static int      madt_find_interrupt(int intr, void **apic, u_int *pin);
   83 static void     *madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
   84 static void     *madt_map_table(vm_paddr_t pa, int offset, const char *sig);
   85 static void     madt_parse_apics(APIC_HEADER *entry, void *arg);
   86 static void     madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr);
   87 static void     madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
   88 static void     madt_parse_local_nmi(LAPIC_NMI *nmi);
   89 static void     madt_parse_nmi(NMI *nmi);
   90 static int      madt_probe(void);
   91 static int      madt_probe_cpus(void);
   92 static void     madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
   93 static int      madt_probe_table(vm_paddr_t address);
   94 static void     madt_register(void *dummy);
   95 static int      madt_setup_local(void);
   96 static int      madt_setup_io(void);
   97 static void     madt_unmap(void *data, vm_offset_t length);
   98 static void     madt_unmap_table(void *table);
   99 static void     madt_walk_table(madt_entry_handler *handler, void *arg);
  100 
  101 static struct apic_enumerator madt_enumerator = {
  102         "MADT",
  103         madt_probe,
  104         madt_probe_cpus,
  105         madt_setup_local,
  106         madt_setup_io
  107 };
  108 
  109 /*
  110  * Code to abuse the crashdump map to map in the tables for the early
  111  * probe.  We cheat and make the following assumptions about how we
  112  * use this KVA: page 0 is used to map in the first page of each table
  113  * found via the RSDT or XSDT and pages 1 to n are used to map in the
  114  * RSDT or XSDT.  The offset is in pages; the length is in bytes.
  115  */
  116 static void *
  117 madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
  118 {
  119         vm_offset_t va, off;
  120         void *data;
  121 
  122         off = pa & PAGE_MASK;
  123         length = roundup(length + off, PAGE_SIZE);
  124         pa = pa & PG_FRAME;
  125         va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
  126             (offset * PAGE_SIZE);
  127         data = (void *)(va + off);
  128         length -= PAGE_SIZE;
  129         while (length > 0) {
  130                 va += PAGE_SIZE;
  131                 pa += PAGE_SIZE;
  132                 length -= PAGE_SIZE;
  133                 pmap_kenter(va, pa);
  134                 invlpg(va);
  135         }
  136         return (data);
  137 }
  138 
  139 static void
  140 madt_unmap(void *data, vm_offset_t length)
  141 {
  142         vm_offset_t va, off;
  143 
  144         va = (vm_offset_t)data;
  145         off = va & PAGE_MASK;
  146         length = roundup(length + off, PAGE_SIZE);
  147         va &= ~PAGE_MASK;
  148         while (length > 0) {
  149                 pmap_kremove(va);
  150                 invlpg(va);
  151                 va += PAGE_SIZE;
  152                 length -= PAGE_SIZE;
  153         }
  154 }
  155 
  156 static void *
  157 madt_map_table(vm_paddr_t pa, int offset, const char *sig)
  158 {
  159         ACPI_TABLE_HEADER *header;
  160         vm_offset_t length;
  161 
  162         header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
  163         if (strncmp(header->Signature, sig, 4) != 0) {
  164                 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  165                 return (NULL);
  166         }
  167         length = header->Length;
  168         madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  169         return (madt_map(pa, offset, length));
  170 }
  171 
  172 static void
  173 madt_unmap_table(void *table)
  174 {
  175         ACPI_TABLE_HEADER *header;
  176 
  177         header = (ACPI_TABLE_HEADER *)table;
  178         madt_unmap(table, header->Length);
  179 }
  180 
  181 /*
  182  * Look for an ACPI Multiple APIC Description Table ("APIC")
  183  */
  184 static int
  185 madt_probe(void)
  186 {
  187         ACPI_POINTER rsdp_ptr;
  188         RSDP_DESCRIPTOR *rsdp;
  189         RSDT_DESCRIPTOR *rsdt;
  190         XSDT_DESCRIPTOR *xsdt;
  191         int i, count;
  192 
  193         if (resource_disabled("acpi", 0))
  194                 return (ENXIO);
  195 
  196         /*
  197          * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
  198          * calls pmap_mapdev() to find the RSDP, we assume that we can use
  199          * pmap_mapdev() to map the RSDP.
  200          */
  201         if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
  202                 return (ENXIO);
  203 #ifdef __i386__
  204         KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
  205 #endif
  206         rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
  207         if (rsdp == NULL) {
  208                 if (bootverbose)
  209                         printf("MADT: Failed to map RSDP\n");
  210                 return (ENXIO);
  211         }
  212 
  213         /*
  214          * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
  215          * We map the XSDT and RSDT at page 1 in the crashdump area.
  216          * Page 0 is used to map in the headers of candidate ACPI tables.
  217          */
  218         if (rsdp->Revision >= 2) {
  219                 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
  220                 if (xsdt == NULL) {
  221                         if (bootverbose)
  222                                 printf("MADT: Failed to map XSDT\n");
  223                         return (ENXIO);
  224                 }
  225                 count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
  226                     sizeof(UINT64);
  227                 for (i = 0; i < count; i++)
  228                         if (madt_probe_table(xsdt->TableOffsetEntry[i]))
  229                                 break;
  230                 madt_unmap_table(xsdt);
  231         } else {
  232                 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
  233                 if (rsdt == NULL) {
  234                         if (bootverbose)
  235                                 printf("MADT: Failed to map RSDT\n");
  236                         return (ENXIO);
  237                 }
  238                 count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
  239                     sizeof(UINT32);
  240                 for (i = 0; i < count; i++)
  241                         if (madt_probe_table(rsdt->TableOffsetEntry[i]))
  242                                 break;
  243                 madt_unmap_table(rsdt);
  244         }
  245         pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
  246         if (madt_physaddr == 0) {
  247                 if (bootverbose)
  248                         printf("MADT: No MADT table found\n");
  249                 return (ENXIO);
  250         }
  251         if (bootverbose)
  252                 printf("MADT: Found table at 0x%jx\n",
  253                     (uintmax_t)madt_physaddr);
  254 
  255         return (0);
  256 }
  257 
  258 /*
  259  * See if a given ACPI table is the MADT.
  260  */
  261 static int
  262 madt_probe_table(vm_paddr_t address)
  263 {
  264         ACPI_TABLE_HEADER *table;
  265 
  266         table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
  267         if (table == NULL) {
  268                 if (bootverbose)
  269                         printf("MADT: Failed to map table at 0x%jx\n",
  270                             (uintmax_t)address);
  271                 return (0);
  272         }
  273         if (bootverbose)
  274                 printf("Table '%.4s' at 0x%jx\n", table->Signature,
  275                     (uintmax_t)address);
  276 
  277         /* XXX: Verify checksum? */
  278         if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
  279                 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  280                 return (0);
  281         }
  282         madt_physaddr = address;
  283         madt_length = table->Length;
  284         madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  285         return (1);
  286 }
  287 
  288 /*
  289  * Run through the MP table enumerating CPUs.
  290  */
  291 static int
  292 madt_probe_cpus(void)
  293 {
  294 
  295         madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
  296         KASSERT(madt != NULL, ("Unable to re-map MADT"));
  297         madt_walk_table(madt_probe_cpus_handler, NULL);
  298         madt_unmap_table(madt);
  299         madt = NULL;
  300         return (0);
  301 }
  302 
  303 /*
  304  * Initialize the local APIC on the BSP.
  305  */
  306 static int
  307 madt_setup_local(void)
  308 {
  309 
  310         madt = pmap_mapdev(madt_physaddr, madt_length);
  311         lapic_init((uintptr_t)madt->LocalApicAddress);
  312         printf("ACPI APIC Table: <%.*s %.*s>\n",
  313             (int)sizeof(madt->Header.OemId), madt->Header.OemId,
  314             (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
  315 
  316         /*
  317          * We ignore 64-bit local APIC override entries.  Should we
  318          * perhaps emit a warning here if we find one?
  319          */
  320         return (0);
  321 }
  322 
  323 /*
  324  * Run through the MP table enumerating I/O APICs.
  325  */
  326 static int
  327 madt_setup_io(void)
  328 {
  329         int i;
  330 
  331         /* First, we run through adding I/O APIC's. */
  332         madt_walk_table(madt_parse_apics, NULL);
  333 
  334         /* Second, we run through the table tweaking interrupt sources. */
  335         madt_walk_table(madt_parse_ints, NULL);
  336 
  337         /* Third, we register all the I/O APIC's. */
  338         for (i = 0; i < NIOAPICS; i++)
  339                 if (ioapics[i].io_apic != NULL)
  340                         ioapic_register(ioapics[i].io_apic);
  341 
  342         /* Finally, we throw the switch to enable the I/O APIC's. */
  343         acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
  344 
  345         return (0);
  346 }
  347 
  348 static void
  349 madt_register(void *dummy __unused)
  350 {
  351 
  352         apic_register_enumerator(&madt_enumerator);
  353 }
  354 SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
  355 
  356 /*
  357  * Call the handler routine for each entry in the MADT table.
  358  */
  359 static void
  360 madt_walk_table(madt_entry_handler *handler, void *arg)
  361 {
  362         APIC_HEADER *entry;
  363         u_char *p, *end;
  364 
  365         end = (u_char *)(madt) + madt->Header.Length;
  366         for (p = (u_char *)(madt + 1); p < end; ) {
  367                 entry = (APIC_HEADER *)p;
  368                 handler(entry, arg);
  369                 p += entry->Length;
  370         }
  371 }
  372 
  373 static void
  374 madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
  375 {
  376         PROCESSOR_APIC *proc;
  377         struct lapic_info *la;
  378 
  379         switch (entry->Type) {
  380         case APIC_PROC:
  381                 /*
  382                  * The MADT does not include a BSP flag, so we have to
  383                  * let the MP code figure out which CPU is the BSP on
  384                  * its own.
  385                  */
  386                 proc = (PROCESSOR_APIC *)entry;
  387                 if (bootverbose)
  388                         printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
  389                             proc->LocalApicId, proc->ProcessorApicId,
  390                             proc->ProcessorEnabled ? "enabled" : "disabled");
  391                 if (proc->ProcessorApicId > NLAPICS)
  392                         panic("%s: CPU ID %d too high", __func__,
  393                             proc->ProcessorApicId);
  394                 la = &lapics[proc->ProcessorApicId];
  395                 KASSERT(la->la_present == 0,
  396                     ("Duplicate local ACPI ID %d", proc->ProcessorApicId));
  397                 la->la_present = 1;
  398                 la->la_apic_id = proc->LocalApicId;
  399                 if (proc->ProcessorEnabled) {
  400                         la->la_enabled = 1;
  401                         lapic_create(proc->LocalApicId, 0);
  402                 }
  403                 break;
  404         }
  405 }
  406 
  407 
  408 /*
  409  * Add an I/O APIC from an entry in the table.
  410  */
  411 static void
  412 madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
  413 {
  414         IO_APIC *apic;
  415 
  416 
  417         switch (entry->Type) {
  418         case APIC_IO:
  419                 apic = (IO_APIC *)entry;
  420                 if (bootverbose)
  421                         printf("MADT: Found IO APIC ID %d, Vector %d at %p\n",
  422                             apic->IoApicId, apic->Vector,
  423                             (void *)(uintptr_t)apic->IoApicAddress);
  424                 if (apic->IoApicId >= NIOAPICS)
  425                         panic("%s: I/O APIC ID %d too high", __func__,
  426                             apic->IoApicId);
  427                 if (ioapics[apic->IoApicId].io_apic != NULL)
  428                         panic("%s: Double APIC ID %d", __func__,
  429                             apic->IoApicId);
  430                 ioapics[apic->IoApicId].io_apic = ioapic_create(
  431                         (uintptr_t)apic->IoApicAddress, apic->IoApicId,
  432                             apic->Vector);
  433                 ioapics[apic->IoApicId].io_vector = apic->Vector;
  434                 break;
  435         default:
  436                 break;
  437         }
  438 }
  439 
  440 /*
  441  * Determine properties of an interrupt source.  Note that for ACPI,
  442  * these are only used for ISA interrupts, so we assume ISA bus values
  443  * (Active Hi, Edge Triggered) for conforming values.
  444  */
  445 static u_char
  446 interrupt_polarity(UINT16 Polarity)
  447 {
  448 
  449         switch (Polarity) {
  450         case APIC_POLARITY_CONFORM:
  451         case APIC_POLARITY_ACTIVEHI:
  452                 return (1);
  453         case APIC_POLARITY_ACTIVELO:
  454                 return (0);
  455         default:
  456                 panic("Bogus Interrupt Polarity");
  457         }
  458 }
  459 
  460 static u_char
  461 interrupt_trigger(UINT16 TriggerMode)
  462 {
  463 
  464         switch (TriggerMode) {
  465         case APIC_TRIGGER_CONFORM:
  466         case APIC_TRIGGER_EDGE:
  467                 return (1);
  468         case APIC_TRIGGER_LEVEL:
  469                 return (0);
  470         default:
  471                 panic("Bogus Interrupt Trigger Mode");
  472         }
  473 }
  474 
  475 /*
  476  * Find the local APIC ID associated with a given ACPI Processor ID.
  477  */
  478 static int
  479 madt_find_cpu(u_int acpi_id, u_int *apic_id)
  480 {
  481 
  482         if (!lapics[acpi_id].la_present)
  483                 return (ENOENT);
  484         *apic_id = lapics[acpi_id].la_apic_id;
  485         if (lapics[acpi_id].la_enabled)
  486                 return (0);
  487         else
  488                 return (ENXIO);
  489 }
  490 
  491 /*
  492  * Find the IO APIC and pin on that APIC associated with a given global
  493  * interrupt.
  494  */
  495 static int
  496 madt_find_interrupt(int intr, void **apic, u_int *pin)
  497 {
  498         int i, best;
  499 
  500         best = -1;
  501         for (i = 0; i < NIOAPICS; i++) {
  502                 if (ioapics[i].io_apic == NULL ||
  503                     ioapics[i].io_vector > intr)
  504                         continue;
  505                 if (best == -1 ||
  506                     ioapics[best].io_vector < ioapics[i].io_vector)
  507                         best = i;
  508         }
  509         if (best == -1)
  510                 return (ENOENT);
  511         *apic = ioapics[best].io_apic;
  512         *pin = intr - ioapics[best].io_vector;
  513         if (*pin > 32)
  514                 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
  515                     intr);
  516         return (0);
  517 }
  518 
  519 /*
  520  * Parse an interrupt source override for an ISA interrupt.
  521  */
  522 static void
  523 madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr)
  524 {
  525         void *new_ioapic, *old_ioapic;
  526         u_int new_pin, old_pin;
  527 
  528         if (bootverbose)
  529                 printf("MADT: intr override: source %u, irq %u\n",
  530                     intr->Source, intr->GlobalSystemInterrupt);
  531         KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
  532         if (madt_find_interrupt(intr->GlobalSystemInterrupt, &new_ioapic,
  533             &new_pin) != 0) {
  534                 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
  535                     intr->GlobalSystemInterrupt, intr->Source);
  536                 return;
  537         }
  538 
  539         if (intr->Source != intr->GlobalSystemInterrupt) {
  540                 /* XXX: This assumes that the SCI uses IRQ 9. */
  541                 if (intr->GlobalSystemInterrupt > 15 && intr->Source == 9)
  542                         acpi_OverrideInterruptLevel(
  543                                 intr->GlobalSystemInterrupt);
  544                 else
  545                         ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
  546                 if (madt_find_interrupt(intr->Source, &old_ioapic,
  547                     &old_pin) != 0)
  548                         printf("MADT: Could not find APIC for source IRQ %d\n",
  549                             intr->Source);
  550                 else if (ioapic_get_vector(old_ioapic, old_pin) ==
  551                     intr->Source)
  552                         ioapic_disable_pin(old_ioapic, old_pin);
  553         }
  554         ioapic_set_triggermode(new_ioapic, new_pin,
  555             interrupt_trigger(intr->TriggerMode));
  556         ioapic_set_polarity(new_ioapic, new_pin,
  557             interrupt_polarity(intr->Polarity));
  558 }
  559 
  560 /*
  561  * Parse an entry for an NMI routed to an IO APIC.
  562  */
  563 static void
  564 madt_parse_nmi(NMI *nmi)
  565 {
  566         void *ioapic;
  567         u_int pin;
  568 
  569         if (madt_find_interrupt(nmi->GlobalSystemInterrupt,
  570             &ioapic, &pin) != 0) {
  571                 printf("MADT: Could not find APIC for vector %d\n",
  572                     nmi->GlobalSystemInterrupt);
  573                 return;
  574         }
  575 
  576         ioapic_set_nmi(ioapic, pin);
  577         if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
  578                 ioapic_set_triggermode(ioapic, pin,
  579                     interrupt_trigger(nmi->TriggerMode));
  580         if (nmi->Polarity != APIC_TRIGGER_CONFORM)
  581                 ioapic_set_polarity(ioapic, pin,
  582                     interrupt_polarity(nmi->Polarity));
  583 }
  584 
  585 /*
  586  * Parse an entry for an NMI routed to a local APIC LVT pin.
  587  */
  588 static void
  589 madt_parse_local_nmi(LAPIC_NMI *nmi)
  590 {
  591         u_int apic_id, pin;
  592 
  593         if (nmi->ProcessorApicId == 0xff)
  594                 apic_id = APIC_ID_ALL;
  595         else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) != 0) {
  596                 if (bootverbose)
  597                         printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
  598                             nmi->ProcessorApicId);
  599                 return;
  600         }
  601         if (nmi->LINTPin == 0)
  602                 pin = LVT_LINT0;
  603         else
  604                 pin = LVT_LINT1;
  605         lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
  606         if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
  607                 lapic_set_lvt_triggermode(apic_id, pin,
  608                     interrupt_trigger(nmi->TriggerMode));
  609         if (nmi->Polarity != APIC_POLARITY_CONFORM)
  610                 lapic_set_lvt_polarity(apic_id, pin,
  611                     interrupt_polarity(nmi->Polarity));
  612 }
  613 
  614 /*
  615  * Parse interrupt entries.
  616  */
  617 static void
  618 madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
  619 {
  620 
  621         switch (entry->Type) {
  622         case APIC_INTERRUPT_SOURCE_OVERRIDE:
  623                 madt_parse_interrupt_override(
  624                         (INTERRUPT_SOURCE_OVERRIDE *)entry);
  625                 break;
  626         case APIC_NMI:
  627                 madt_parse_nmi((NMI *)entry);
  628                 break;
  629         case APIC_LOCAL_APIC_NMI:
  630                 madt_parse_local_nmi((LAPIC_NMI *)entry);
  631                 break;
  632         }
  633 }
  634 
  635 /*
  636  * Setup per-CPU ACPI IDs.
  637  */
  638 static void
  639 madt_set_ids(void *dummy)
  640 {
  641         struct pcpu *pc;
  642         u_int i, j;
  643 
  644         if (madt == NULL)
  645                 return;
  646         for (i = 0; i <= mp_maxid; i++) {
  647                 if (CPU_ABSENT(i))
  648                         continue;
  649                 pc = pcpu_find(i);
  650                 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
  651                 for (j = 0; j < NLAPICS + 1; j++) {
  652                         if (!lapics[j].la_present || !lapics[j].la_enabled)
  653                                 continue;
  654                         if (lapics[j].la_apic_id == pc->pc_apic_id) {
  655                                 pc->pc_acpi_id = j;
  656                                 if (bootverbose)
  657                                         printf("APIC: CPU %u has ACPI ID %u\n",
  658                                             i, j);
  659                                 break;
  660                         }
  661                 }
  662                 if (j == NLAPICS + 1)
  663                         panic("Unable to find ACPI ID for CPU %d", i);
  664         }
  665 }
  666 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)

Cache object: c9f027c2f219a917ea9f16bede0cd54d


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