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

Cache object: 3855385b2ed85572bcf3b03f8023696a


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