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                 if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
  486                         printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
  487                         break;
  488                 }
  489                 ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
  490                     apic->Id, apic->GlobalIrqBase);
  491                 ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
  492                 break;
  493         default:
  494                 break;
  495         }
  496 }
  497 
  498 /*
  499  * Determine properties of an interrupt source.  Note that for ACPI these
  500  * functions are only used for ISA interrupts, so we assume ISA bus values
  501  * (Active Hi, Edge Triggered) for conforming values except for the ACPI
  502  * SCI for which we use Active Lo, Level Triggered.
  503  */
  504 static enum intr_polarity
  505 interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
  506 {
  507 
  508         switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
  509         case ACPI_MADT_POLARITY_CONFORMS:
  510                 if (Source == AcpiGbl_FADT.SciInterrupt)
  511                         return (INTR_POLARITY_LOW);
  512                 else
  513                         return (INTR_POLARITY_HIGH);
  514         case ACPI_MADT_POLARITY_ACTIVE_HIGH:
  515                 return (INTR_POLARITY_HIGH);
  516         case ACPI_MADT_POLARITY_ACTIVE_LOW:
  517                 return (INTR_POLARITY_LOW);
  518         default:
  519                 panic("Bogus Interrupt Polarity");
  520         }
  521 }
  522 
  523 static enum intr_trigger
  524 interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
  525 {
  526 
  527         switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
  528         case ACPI_MADT_TRIGGER_CONFORMS:
  529                 if (Source == AcpiGbl_FADT.SciInterrupt)
  530                         return (INTR_TRIGGER_LEVEL);
  531                 else
  532                         return (INTR_TRIGGER_EDGE);
  533         case ACPI_MADT_TRIGGER_EDGE:
  534                 return (INTR_TRIGGER_EDGE);
  535         case ACPI_MADT_TRIGGER_LEVEL:
  536                 return (INTR_TRIGGER_LEVEL);
  537         default:
  538                 panic("Bogus Interrupt Trigger Mode");
  539         }
  540 }
  541 
  542 /*
  543  * Find the local APIC ID associated with a given ACPI Processor ID.
  544  */
  545 static int
  546 madt_find_cpu(u_int acpi_id, u_int *apic_id)
  547 {
  548         int i;
  549 
  550         for (i = 0; i <= MAX_APIC_ID; i++) {
  551                 if (!lapics[i].la_enabled)
  552                         continue;
  553                 if (lapics[i].la_acpi_id != acpi_id)
  554                         continue;
  555                 *apic_id = i;
  556                 return (0);
  557         }
  558         return (ENOENT);
  559 }
  560 
  561 /*
  562  * Find the IO APIC and pin on that APIC associated with a given global
  563  * interrupt.
  564  */
  565 static int
  566 madt_find_interrupt(int intr, void **apic, u_int *pin)
  567 {
  568         int i, best;
  569 
  570         best = -1;
  571         for (i = 0; i <= MAX_APIC_ID; i++) {
  572                 if (ioapics[i].io_apic == NULL ||
  573                     ioapics[i].io_vector > intr)
  574                         continue;
  575                 if (best == -1 ||
  576                     ioapics[best].io_vector < ioapics[i].io_vector)
  577                         best = i;
  578         }
  579         if (best == -1)
  580                 return (ENOENT);
  581         *apic = ioapics[best].io_apic;
  582         *pin = intr - ioapics[best].io_vector;
  583         if (*pin > 32)
  584                 printf("WARNING: Found intpin of %u for vector %d\n", *pin,
  585                     intr);
  586         return (0);
  587 }
  588 
  589 /*
  590  * Parse an interrupt source override for an ISA interrupt.
  591  */
  592 static void
  593 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
  594 {
  595         void *new_ioapic, *old_ioapic;
  596         u_int new_pin, old_pin;
  597         enum intr_trigger trig;
  598         enum intr_polarity pol;
  599         char buf[64];
  600 
  601         if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
  602             intr->GlobalIrq == 2) {
  603                 if (bootverbose)
  604                         printf("MADT: Skipping timer override\n");
  605                 return;
  606         }
  607         if (bootverbose)
  608                 printf("MADT: Interrupt override: source %u, irq %u\n",
  609                     intr->SourceIrq, intr->GlobalIrq);
  610         KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
  611         if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
  612                 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
  613                     intr->GlobalIrq, intr->SourceIrq);
  614                 return;
  615         }
  616 
  617         /*
  618          * Lookup the appropriate trigger and polarity modes for this
  619          * entry.
  620          */
  621         trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
  622         pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
  623         
  624         /*
  625          * If the SCI is identity mapped but has edge trigger and
  626          * active-hi polarity or the force_sci_lo tunable is set,
  627          * force it to use level/lo.
  628          */
  629         if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
  630                 madt_found_sci_override = 1;
  631                 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
  632                         if (tolower(buf[0]) == 'e')
  633                                 trig = INTR_TRIGGER_EDGE;
  634                         else if (tolower(buf[0]) == 'l')
  635                                 trig = INTR_TRIGGER_LEVEL;
  636                         else
  637                                 panic(
  638                                 "Invalid trigger %s: must be 'edge' or 'level'",
  639                                     buf);
  640                         printf("MADT: Forcing SCI to %s trigger\n",
  641                             trig == INTR_TRIGGER_EDGE ? "edge" : "level");
  642                 }
  643                 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
  644                         if (tolower(buf[0]) == 'h')
  645                                 pol = INTR_POLARITY_HIGH;
  646                         else if (tolower(buf[0]) == 'l')
  647                                 pol = INTR_POLARITY_LOW;
  648                         else
  649                                 panic(
  650                                 "Invalid polarity %s: must be 'high' or 'low'",
  651                                     buf);
  652                         printf("MADT: Forcing SCI to active %s polarity\n",
  653                             pol == INTR_POLARITY_HIGH ? "high" : "low");
  654                 }
  655         }
  656 
  657         /* Remap the IRQ if it is mapped to a different interrupt vector. */
  658         if (intr->SourceIrq != intr->GlobalIrq) {
  659                 /*
  660                  * If the SCI is remapped to a non-ISA global interrupt,
  661                  * then override the vector we use to setup and allocate
  662                  * the interrupt.
  663                  */
  664                 if (intr->GlobalIrq > 15 &&
  665                     intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
  666                         acpi_OverrideInterruptLevel(intr->GlobalIrq);
  667                 else
  668                         ioapic_remap_vector(new_ioapic, new_pin,
  669                             intr->SourceIrq);
  670                 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
  671                     &old_pin) != 0)
  672                         printf("MADT: Could not find APIC for source IRQ %u\n",
  673                             intr->SourceIrq);
  674                 else if (ioapic_get_vector(old_ioapic, old_pin) ==
  675                     intr->SourceIrq)
  676                         ioapic_disable_pin(old_ioapic, old_pin);
  677         }
  678 
  679         /* Program the polarity and trigger mode. */
  680         ioapic_set_triggermode(new_ioapic, new_pin, trig);
  681         ioapic_set_polarity(new_ioapic, new_pin, pol);
  682 }
  683 
  684 /*
  685  * Parse an entry for an NMI routed to an IO APIC.
  686  */
  687 static void
  688 madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
  689 {
  690         void *ioapic;
  691         u_int pin;
  692 
  693         if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
  694                 printf("MADT: Could not find APIC for vector %u\n",
  695                     nmi->GlobalIrq);
  696                 return;
  697         }
  698 
  699         ioapic_set_nmi(ioapic, pin);
  700         if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
  701                 ioapic_set_triggermode(ioapic, pin,
  702                     interrupt_trigger(nmi->IntiFlags, 0));
  703         if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
  704                 ioapic_set_polarity(ioapic, pin,
  705                     interrupt_polarity(nmi->IntiFlags, 0));
  706 }
  707 
  708 /*
  709  * Parse an entry for an NMI routed to a local APIC LVT pin.
  710  */
  711 static void
  712 madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
  713 {
  714         u_int apic_id, pin;
  715 
  716         if (nmi->ProcessorId == 0xff)
  717                 apic_id = APIC_ID_ALL;
  718         else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
  719                 if (bootverbose)
  720                         printf("MADT: Ignoring local NMI routed to "
  721                             "ACPI CPU %u\n", nmi->ProcessorId);
  722                 return;
  723         }
  724         if (nmi->Lint == 0)
  725                 pin = LVT_LINT0;
  726         else
  727                 pin = LVT_LINT1;
  728         lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
  729         if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
  730                 lapic_set_lvt_triggermode(apic_id, pin,
  731                     interrupt_trigger(nmi->IntiFlags, 0));
  732         if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
  733                 lapic_set_lvt_polarity(apic_id, pin,
  734                     interrupt_polarity(nmi->IntiFlags, 0));
  735 }
  736 
  737 /*
  738  * Parse interrupt entries.
  739  */
  740 static void
  741 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
  742 {
  743 
  744         switch (entry->Type) {
  745         case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
  746                 madt_parse_interrupt_override(
  747                         (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
  748                 break;
  749         case ACPI_MADT_TYPE_NMI_SOURCE:
  750                 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
  751                 break;
  752         case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
  753                 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
  754                 break;
  755         }
  756 }
  757 
  758 /*
  759  * Setup per-CPU ACPI IDs.
  760  */
  761 static void
  762 madt_set_ids(void *dummy)
  763 {
  764         struct lapic_info *la;
  765         struct pcpu *pc;
  766         u_int i;
  767 
  768         if (madt == NULL)
  769                 return;
  770         for (i = 0; i <= mp_maxid; i++) {
  771                 if (CPU_ABSENT(i))
  772                         continue;
  773                 pc = pcpu_find(i);
  774                 KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
  775                 la = &lapics[pc->pc_apic_id];
  776                 if (!la->la_enabled)
  777                         panic("APIC: CPU with APIC ID %u is not enabled",
  778                             pc->pc_apic_id);
  779                 pc->pc_acpi_id = la->la_acpi_id;
  780                 if (bootverbose)
  781                         printf("APIC: CPU %u has ACPI ID %u\n", i,
  782                             la->la_acpi_id);
  783         }
  784 }
  785 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL);

Cache object: e9ef8551ecad4c97b0319a0416fc4c62


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