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/6.3/sys/i386/acpica/madt.c 172452 2007-10-05 15:22:37Z 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 <contrib/dev/acpica/acpi.h>
   52 #include <contrib/dev/acpica/actables.h>
   53 #include <dev/acpica/acpivar.h>
   54 #include <dev/pci/pcivar.h>
   55 
   56 typedef void madt_entry_handler(APIC_HEADER *entry, void *arg);
   57 
   58 /* These two arrays are indexed by APIC IDs. */
   59 struct ioapic_info {
   60         void *io_apic;
   61         UINT32 io_vector;
   62 } ioapics[MAX_APIC_ID + 1];
   63 
   64 struct lapic_info {
   65         u_int la_enabled:1;
   66         u_int la_acpi_id:8;
   67 } lapics[MAX_APIC_ID + 1];
   68 
   69 static int madt_found_sci_override;
   70 static MULTIPLE_APIC_TABLE *madt;
   71 static vm_paddr_t madt_physaddr;
   72 static vm_offset_t madt_length;
   73 
   74 MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
   75 
   76 static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
   77 static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
   78 static int      madt_find_cpu(u_int acpi_id, u_int *apic_id);
   79 static int      madt_find_interrupt(int intr, void **apic, u_int *pin);
   80 static void     *madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
   81 static void     *madt_map_table(vm_paddr_t pa, int offset, const char *sig);
   82 static void     madt_parse_apics(APIC_HEADER *entry, void *arg);
   83 static void     madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
   84 static void     madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
   85 static void     madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
   86 static void     madt_parse_nmi(MADT_NMI_SOURCE *nmi);
   87 static int      madt_probe(void);
   88 static int      madt_probe_cpus(void);
   89 static void     madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
   90 static int      madt_probe_table(vm_paddr_t address);
   91 static void     madt_register(void *dummy);
   92 static int      madt_setup_local(void);
   93 static int      madt_setup_io(void);
   94 static void     madt_unmap(void *data, vm_offset_t length);
   95 static void     madt_unmap_table(void *table);
   96 static void     madt_walk_table(madt_entry_handler *handler, void *arg);
   97 
   98 static struct apic_enumerator madt_enumerator = {
   99         "MADT",
  100         madt_probe,
  101         madt_probe_cpus,
  102         madt_setup_local,
  103         madt_setup_io
  104 };
  105 
  106 /*
  107  * Code to abuse the crashdump map to map in the tables for the early
  108  * probe.  We cheat and make the following assumptions about how we
  109  * use this KVA: page 0 is used to map in the first page of each table
  110  * found via the RSDT or XSDT and pages 1 to n are used to map in the
  111  * RSDT or XSDT.  The offset is in pages; the length is in bytes.
  112  */
  113 static void *
  114 madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
  115 {
  116         vm_offset_t va, off;
  117         void *data;
  118 
  119         off = pa & PAGE_MASK;
  120         length = roundup(length + off, PAGE_SIZE);
  121         pa = pa & PG_FRAME;
  122         va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
  123             (offset * PAGE_SIZE);
  124         data = (void *)(va + off);
  125         length -= PAGE_SIZE;
  126         while (length > 0) {
  127                 va += PAGE_SIZE;
  128                 pa += PAGE_SIZE;
  129                 length -= PAGE_SIZE;
  130                 pmap_kenter(va, pa);
  131                 invlpg(va);
  132         }
  133         return (data);
  134 }
  135 
  136 static void
  137 madt_unmap(void *data, vm_offset_t length)
  138 {
  139         vm_offset_t va, off;
  140 
  141         va = (vm_offset_t)data;
  142         off = va & PAGE_MASK;
  143         length = roundup(length + off, PAGE_SIZE);
  144         va &= ~PAGE_MASK;
  145         while (length > 0) {
  146                 pmap_kremove(va);
  147                 invlpg(va);
  148                 va += PAGE_SIZE;
  149                 length -= PAGE_SIZE;
  150         }
  151 }
  152 
  153 static void *
  154 madt_map_table(vm_paddr_t pa, int offset, const char *sig)
  155 {
  156         ACPI_TABLE_HEADER *header;
  157         vm_offset_t length;
  158         void *table;
  159 
  160         header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
  161         if (strncmp(header->Signature, sig, 4) != 0) {
  162                 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  163                 return (NULL);
  164         }
  165         length = header->Length;
  166         madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  167         table = madt_map(pa, offset, length);
  168         if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
  169                 if (bootverbose)
  170                         printf("MADT: Failed checksum for table %s\n", sig);
  171                 madt_unmap(table, length);
  172                 return (NULL);
  173         }
  174         return (table);
  175 }
  176 
  177 static void
  178 madt_unmap_table(void *table)
  179 {
  180         ACPI_TABLE_HEADER *header;
  181 
  182         header = (ACPI_TABLE_HEADER *)table;
  183         madt_unmap(table, header->Length);
  184 }
  185 
  186 /*
  187  * Look for an ACPI Multiple APIC Description Table ("APIC")
  188  */
  189 static int
  190 madt_probe(void)
  191 {
  192         ACPI_POINTER rsdp_ptr;
  193         RSDP_DESCRIPTOR *rsdp;
  194         RSDT_DESCRIPTOR *rsdt;
  195         XSDT_DESCRIPTOR *xsdt;
  196         int i, count;
  197 
  198         if (resource_disabled("acpi", 0))
  199                 return (ENXIO);
  200 
  201         /*
  202          * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
  203          * calls pmap_mapbios() to find the RSDP, we assume that we can use
  204          * pmap_mapbios() to map the RSDP.
  205          */
  206         if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
  207                 return (ENXIO);
  208 #ifdef __i386__
  209         KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
  210 #endif
  211         rsdp = pmap_mapbios(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
  212         if (rsdp == NULL) {
  213                 if (bootverbose)
  214                         printf("MADT: Failed to map RSDP\n");
  215                 return (ENXIO);
  216         }
  217 
  218         /*
  219          * For ACPI >= 2.0, use the XSDT if it is available.
  220          * Otherwise, use the RSDT.  We map the XSDT or RSDT at page 1
  221          * in the crashdump area.  Page 0 is used to map in the
  222          * headers of candidate ACPI tables.
  223          */
  224         if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
  225                 /*
  226                  * AcpiOsGetRootPointer only verifies the checksum for
  227                  * the version 1.0 portion of the RSDP.  Version 2.0 has
  228                  * an additional checksum that we verify first.
  229                  */
  230                 if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
  231                         if (bootverbose)
  232                                 printf("MADT: RSDP failed extended checksum\n");
  233                         return (ENXIO);
  234                 }
  235                 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
  236                 if (xsdt == NULL) {
  237                         if (bootverbose)
  238                                 printf("MADT: Failed to map XSDT\n");
  239                         return (ENXIO);
  240                 }
  241                 count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
  242                     sizeof(UINT64);
  243                 for (i = 0; i < count; i++)
  244                         if (madt_probe_table(xsdt->TableOffsetEntry[i]))
  245                                 break;
  246                 madt_unmap_table(xsdt);
  247         } else {
  248                 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
  249                 if (rsdt == NULL) {
  250                         if (bootverbose)
  251                                 printf("MADT: Failed to map RSDT\n");
  252                         return (ENXIO);
  253                 }
  254                 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
  255                     sizeof(UINT32);
  256                 for (i = 0; i < count; i++)
  257                         if (madt_probe_table(rsdt->TableOffsetEntry[i]))
  258                                 break;
  259                 madt_unmap_table(rsdt);
  260         }
  261         pmap_unmapbios((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
  262         if (madt_physaddr == 0) {
  263                 if (bootverbose)
  264                         printf("MADT: No MADT table found\n");
  265                 return (ENXIO);
  266         }
  267         if (bootverbose)
  268                 printf("MADT: Found table at 0x%jx\n",
  269                     (uintmax_t)madt_physaddr);
  270 
  271         /*
  272          * Verify that we can map the full table and that its checksum is
  273          * correct, etc.
  274          */
  275         madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
  276         if (madt == NULL)
  277                 return (ENXIO);
  278         madt_unmap_table(madt);
  279         madt = NULL;
  280 
  281         return (0);
  282 }
  283 
  284 /*
  285  * See if a given ACPI table is the MADT.
  286  */
  287 static int
  288 madt_probe_table(vm_paddr_t address)
  289 {
  290         ACPI_TABLE_HEADER *table;
  291 
  292         table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
  293         if (table == NULL) {
  294                 if (bootverbose)
  295                         printf("MADT: Failed to map table at 0x%jx\n",
  296                             (uintmax_t)address);
  297                 return (0);
  298         }
  299         if (bootverbose)
  300                 printf("Table '%.4s' at 0x%jx\n", table->Signature,
  301                     (uintmax_t)address);
  302 
  303         if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
  304                 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  305                 return (0);
  306         }
  307         madt_physaddr = address;
  308         madt_length = table->Length;
  309         madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  310         return (1);
  311 }
  312 
  313 /*
  314  * Run through the MP table enumerating CPUs.
  315  */
  316 static int
  317 madt_probe_cpus(void)
  318 {
  319 
  320         madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
  321         KASSERT(madt != NULL, ("Unable to re-map MADT"));
  322         madt_walk_table(madt_probe_cpus_handler, NULL);
  323         madt_unmap_table(madt);
  324         madt = NULL;
  325         return (0);
  326 }
  327 
  328 /*
  329  * Initialize the local APIC on the BSP.
  330  */
  331 static int
  332 madt_setup_local(void)
  333 {
  334 
  335         madt = pmap_mapbios(madt_physaddr, madt_length);
  336         lapic_init((uintptr_t)madt->LocalApicAddress);
  337         printf("ACPI APIC Table: <%.*s %.*s>\n",
  338             (int)sizeof(madt->OemId), madt->OemId,
  339             (int)sizeof(madt->OemTableId), madt->OemTableId);
  340 
  341         /*
  342          * We ignore 64-bit local APIC override entries.  Should we
  343          * perhaps emit a warning here if we find one?
  344          */
  345         return (0);
  346 }
  347 
  348 /*
  349  * Enumerate I/O APICs and setup interrupt sources.
  350  */
  351 static int
  352 madt_setup_io(void)
  353 {
  354         void *ioapic;
  355         u_int pin;
  356         int i;
  357 
  358         /* Try to initialize ACPI so that we can access the FADT. */
  359         i = acpi_Startup();
  360         if (ACPI_FAILURE(i)) {
  361                 printf("MADT: ACPI Startup failed with %s\n",
  362                     AcpiFormatException(i));
  363                 printf("Try disabling either ACPI or apic support.\n");
  364                 panic("Using MADT but ACPI doesn't work");
  365         }
  366                     
  367         /* First, we run through adding I/O APIC's. */
  368         madt_walk_table(madt_parse_apics, NULL);
  369 
  370         /* Second, we run through the table tweaking interrupt sources. */
  371         madt_walk_table(madt_parse_ints, NULL);
  372 
  373         /*
  374          * If there was not an explicit override entry for the SCI,
  375          * force it to use level trigger and active-low polarity.
  376          */
  377         if (!madt_found_sci_override) {
  378                 if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
  379                     != 0)
  380                         printf("MADT: Could not find APIC for SCI IRQ %d\n",
  381                             AcpiGbl_FADT->SciInt);
  382                 else {
  383                         printf(
  384         "MADT: Forcing active-low polarity and level trigger for SCI\n");
  385                         ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
  386                         ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
  387                 }
  388         }
  389 
  390         /* Third, we register all the I/O APIC's. */
  391         for (i = 0; i <= MAX_APIC_ID; i++)
  392                 if (ioapics[i].io_apic != NULL)
  393                         ioapic_register(ioapics[i].io_apic);
  394 
  395         /* Finally, we throw the switch to enable the I/O APIC's. */
  396         acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
  397 
  398         return (0);
  399 }
  400 
  401 static void
  402 madt_register(void *dummy __unused)
  403 {
  404 
  405         apic_register_enumerator(&madt_enumerator);
  406 }
  407 SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
  408 
  409 /*
  410  * Call the handler routine for each entry in the MADT table.
  411  */
  412 static void
  413 madt_walk_table(madt_entry_handler *handler, void *arg)
  414 {
  415         APIC_HEADER *entry;
  416         u_char *p, *end;
  417 
  418         end = (u_char *)(madt) + madt->Length;
  419         for (p = (u_char *)(madt + 1); p < end; ) {
  420                 entry = (APIC_HEADER *)p;
  421                 handler(entry, arg);
  422                 p += entry->Length;
  423         }
  424 }
  425 
  426 static void
  427 madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
  428 {
  429         MADT_PROCESSOR_APIC *proc;
  430         struct lapic_info *la;
  431 
  432         switch (entry->Type) {
  433         case APIC_PROCESSOR:
  434                 /*
  435                  * The MADT does not include a BSP flag, so we have to
  436                  * let the MP code figure out which CPU is the BSP on
  437                  * its own.
  438                  */
  439                 proc = (MADT_PROCESSOR_APIC *)entry;
  440                 if (bootverbose)
  441                         printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
  442                             proc->LocalApicId, proc->ProcessorId,
  443                             proc->ProcessorEnabled ? "enabled" : "disabled");
  444                 if (!proc->ProcessorEnabled)
  445                         break;
  446                 if (proc->LocalApicId > MAX_APIC_ID)
  447                         panic("%s: CPU ID %d too high", __func__,
  448                             proc->LocalApicId);
  449                 la = &lapics[proc->LocalApicId];
  450                 KASSERT(la->la_enabled == 0,
  451                     ("Duplicate local APIC ID %d", proc->LocalApicId));
  452                 la->la_enabled = 1;
  453                 la->la_acpi_id = proc->ProcessorId;
  454                 lapic_create(proc->LocalApicId, 0);
  455                 break;
  456         }
  457 }
  458 
  459 
  460 /*
  461  * Add an I/O APIC from an entry in the table.
  462  */
  463 static void
  464 madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
  465 {
  466         MADT_IO_APIC *apic;
  467 
  468         switch (entry->Type) {
  469         case APIC_IO:
  470                 apic = (MADT_IO_APIC *)entry;
  471                 if (bootverbose)
  472                         printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
  473                             apic->IoApicId, apic->Interrupt,
  474                             (void *)(uintptr_t)apic->Address);
  475                 if (apic->IoApicId > MAX_APIC_ID)
  476                         panic("%s: I/O APIC ID %d too high", __func__,
  477                             apic->IoApicId);
  478                 if (ioapics[apic->IoApicId].io_apic != NULL)
  479                         panic("%s: Double APIC ID %d", __func__,
  480                             apic->IoApicId);
  481                 ioapics[apic->IoApicId].io_apic = ioapic_create(
  482                         (uintptr_t)apic->Address, apic->IoApicId,
  483                             apic->Interrupt);
  484                 ioapics[apic->IoApicId].io_vector = apic->Interrupt;
  485                 break;
  486         default:
  487                 break;
  488         }
  489 }
  490 
  491 /*
  492  * Determine properties of an interrupt source.  Note that for ACPI these
  493  * functions are only used for ISA interrupts, so we assume ISA bus values
  494  * (Active Hi, Edge Triggered) for conforming values except for the ACPI
  495  * SCI for which we use Active Lo, Level Triggered.
  496  */
  497 static enum intr_polarity
  498 interrupt_polarity(UINT16 Polarity, UINT8 Source)
  499 {
  500 
  501         switch (Polarity) {
  502         case POLARITY_CONFORMS:
  503                 if (Source == AcpiGbl_FADT->SciInt)
  504                         return (INTR_POLARITY_LOW);
  505                 else
  506                         return (INTR_POLARITY_HIGH);
  507         case POLARITY_ACTIVE_HIGH:
  508                 return (INTR_POLARITY_HIGH);
  509         case POLARITY_ACTIVE_LOW:
  510                 return (INTR_POLARITY_LOW);
  511         default:
  512                 panic("Bogus Interrupt Polarity");
  513         }
  514 }
  515 
  516 static enum intr_trigger
  517 interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
  518 {
  519 
  520         switch (TriggerMode) {
  521         case TRIGGER_CONFORMS:
  522                 if (Source == AcpiGbl_FADT->SciInt)
  523                         return (INTR_TRIGGER_LEVEL);
  524                 else
  525                         return (INTR_TRIGGER_EDGE);
  526         case TRIGGER_EDGE:
  527                 return (INTR_TRIGGER_EDGE);
  528         case TRIGGER_LEVEL:
  529                 return (INTR_TRIGGER_LEVEL);
  530         default:
  531                 panic("Bogus Interrupt Trigger Mode");
  532         }
  533 }
  534 
  535 /*
  536  * Find the local APIC ID associated with a given ACPI Processor ID.
  537  */
  538 static int
  539 madt_find_cpu(u_int acpi_id, u_int *apic_id)
  540 {
  541         int i;
  542 
  543         for (i = 0; i <= MAX_APIC_ID; i++) {
  544                 if (!lapics[i].la_enabled)
  545                         continue;
  546                 if (lapics[i].la_acpi_id != acpi_id)
  547                         continue;
  548                 *apic_id = i;
  549                 return (0);
  550         }
  551         return (ENOENT);
  552 }
  553 
  554 /*
  555  * Find the IO APIC and pin on that APIC associated with a given global
  556  * interrupt.
  557  */
  558 static int
  559 madt_find_interrupt(int intr, void **apic, u_int *pin)
  560 {
  561         int i, best;
  562 
  563         best = -1;
  564         for (i = 0; i <= MAX_APIC_ID; i++) {
  565                 if (ioapics[i].io_apic == NULL ||
  566                     ioapics[i].io_vector > intr)
  567                         continue;
  568                 if (best == -1 ||
  569                     ioapics[best].io_vector < ioapics[i].io_vector)
  570                         best = i;
  571         }
  572         if (best == -1)
  573                 return (ENOENT);
  574         *apic = ioapics[best].io_apic;
  575         *pin = intr - ioapics[best].io_vector;
  576         if (*pin > 32)
  577                 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
  578                     intr);
  579         return (0);
  580 }
  581 
  582 /*
  583  * Parse an interrupt source override for an ISA interrupt.
  584  */
  585 static void
  586 madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
  587 {
  588         void *new_ioapic, *old_ioapic;
  589         u_int new_pin, old_pin;
  590         enum intr_trigger trig;
  591         enum intr_polarity pol;
  592         char buf[64];
  593 
  594         if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->Source == 0 &&
  595             intr->Interrupt == 2) {
  596                 if (bootverbose)
  597                         printf("MADT: Skipping timer override\n");
  598                 return;
  599         }
  600         if (bootverbose)
  601                 printf("MADT: Interrupt override: source %u, irq %u\n",
  602                     intr->Source, intr->Interrupt);
  603         KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
  604         if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
  605             &new_pin) != 0) {
  606                 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
  607                     intr->Interrupt, intr->Source);
  608                 return;
  609         }
  610 
  611         /*
  612          * Lookup the appropriate trigger and polarity modes for this
  613          * entry.
  614          */
  615         trig = interrupt_trigger(intr->TriggerMode, intr->Source);
  616         pol = interrupt_polarity(intr->Polarity, intr->Source);
  617         
  618         /*
  619          * If the SCI is identity mapped but has edge trigger and
  620          * active-hi polarity or the force_sci_lo tunable is set,
  621          * force it to use level/lo.
  622          */
  623         if (intr->Source == AcpiGbl_FADT->SciInt) {
  624                 madt_found_sci_override = 1;
  625                 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
  626                         if (tolower(buf[0]) == 'e')
  627                                 trig = INTR_TRIGGER_EDGE;
  628                         else if (tolower(buf[0]) == 'l')
  629                                 trig = INTR_TRIGGER_LEVEL;
  630                         else
  631                                 panic(
  632                                 "Invalid trigger %s: must be 'edge' or 'level'",
  633                                     buf);
  634                         printf("MADT: Forcing SCI to %s trigger\n",
  635                             trig == INTR_TRIGGER_EDGE ? "edge" : "level");
  636                 }
  637                 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
  638                         if (tolower(buf[0]) == 'h')
  639                                 pol = INTR_POLARITY_HIGH;
  640                         else if (tolower(buf[0]) == 'l')
  641                                 pol = INTR_POLARITY_LOW;
  642                         else
  643                                 panic(
  644                                 "Invalid polarity %s: must be 'high' or 'low'",
  645                                     buf);
  646                         printf("MADT: Forcing SCI to active %s polarity\n",
  647                             pol == INTR_POLARITY_HIGH ? "high" : "low");
  648                 }
  649         }
  650 
  651         /* Remap the IRQ if it is mapped to a different interrupt vector. */
  652         if (intr->Source != intr->Interrupt) {
  653                 /*
  654                  * If the SCI is remapped to a non-ISA global interrupt,
  655                  * then override the vector we use to setup and allocate
  656                  * the interrupt.
  657                  */
  658                 if (intr->Interrupt > 15 &&
  659                     intr->Source == AcpiGbl_FADT->SciInt)
  660                         acpi_OverrideInterruptLevel(intr->Interrupt);
  661                 else
  662                         ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
  663                 if (madt_find_interrupt(intr->Source, &old_ioapic,
  664                     &old_pin) != 0)
  665                         printf("MADT: Could not find APIC for source IRQ %d\n",
  666                             intr->Source);
  667                 else if (ioapic_get_vector(old_ioapic, old_pin) ==
  668                     intr->Source)
  669                         ioapic_disable_pin(old_ioapic, old_pin);
  670         }
  671 
  672         /* Program the polarity and trigger mode. */
  673         ioapic_set_triggermode(new_ioapic, new_pin, trig);
  674         ioapic_set_polarity(new_ioapic, new_pin, pol);
  675 }
  676 
  677 /*
  678  * Parse an entry for an NMI routed to an IO APIC.
  679  */
  680 static void
  681 madt_parse_nmi(MADT_NMI_SOURCE *nmi)
  682 {
  683         void *ioapic;
  684         u_int pin;
  685 
  686         if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
  687                 printf("MADT: Could not find APIC for vector %d\n",
  688                     nmi->Interrupt);
  689                 return;
  690         }
  691 
  692         ioapic_set_nmi(ioapic, pin);
  693         if (nmi->TriggerMode != TRIGGER_CONFORMS)
  694                 ioapic_set_triggermode(ioapic, pin,
  695                     interrupt_trigger(nmi->TriggerMode, 0));
  696         if (nmi->Polarity != TRIGGER_CONFORMS)
  697                 ioapic_set_polarity(ioapic, pin,
  698                     interrupt_polarity(nmi->Polarity, 0));
  699 }
  700 
  701 /*
  702  * Parse an entry for an NMI routed to a local APIC LVT pin.
  703  */
  704 static void
  705 madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
  706 {
  707         u_int apic_id, pin;
  708 
  709         if (nmi->ProcessorId == 0xff)
  710                 apic_id = APIC_ID_ALL;
  711         else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
  712                 if (bootverbose)
  713                         printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
  714                             nmi->ProcessorId);
  715                 return;
  716         }
  717         if (nmi->Lint == 0)
  718                 pin = LVT_LINT0;
  719         else
  720                 pin = LVT_LINT1;
  721         lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
  722         if (nmi->TriggerMode != TRIGGER_CONFORMS)
  723                 lapic_set_lvt_triggermode(apic_id, pin,
  724                     interrupt_trigger(nmi->TriggerMode, 0));
  725         if (nmi->Polarity != POLARITY_CONFORMS)
  726                 lapic_set_lvt_polarity(apic_id, pin,
  727                     interrupt_polarity(nmi->Polarity, 0));
  728 }
  729 
  730 /*
  731  * Parse interrupt entries.
  732  */
  733 static void
  734 madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
  735 {
  736 
  737         switch (entry->Type) {
  738         case APIC_XRUPT_OVERRIDE:
  739                 madt_parse_interrupt_override(
  740                         (MADT_INTERRUPT_OVERRIDE *)entry);
  741                 break;
  742         case APIC_NMI:
  743                 madt_parse_nmi((MADT_NMI_SOURCE *)entry);
  744                 break;
  745         case APIC_LOCAL_NMI:
  746                 madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
  747                 break;
  748         }
  749 }
  750 
  751 /*
  752  * Setup per-CPU ACPI IDs.
  753  */
  754 static void
  755 madt_set_ids(void *dummy)
  756 {
  757         struct lapic_info *la;
  758         struct pcpu *pc;
  759         u_int i;
  760 
  761         if (madt == NULL)
  762                 return;
  763         for (i = 0; i <= mp_maxid; i++) {
  764                 if (CPU_ABSENT(i))
  765                         continue;
  766                 pc = pcpu_find(i);
  767                 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
  768                 la = &lapics[pc->pc_apic_id];
  769                 if (!la->la_enabled)
  770                         panic("APIC: CPU with APIC ID %u is not enabled",
  771                             pc->pc_apic_id);
  772                 pc->pc_acpi_id = la->la_acpi_id;
  773                 if (bootverbose)
  774                         printf("APIC: CPU %u has ACPI ID %u\n", i,
  775                             la->la_acpi_id);
  776         }
  777 }
  778 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)

Cache object: fda0ac098811bef820ed16065c4c5fee


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