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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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.2/sys/i386/acpica/madt.c 158448 2006-05-11 17:41:00Z njl $");
   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 #define NIOAPICS                32      /* Max number of I/O APICs */
   57 #define NLAPICS                 32      /* Max number of local APICs */
   58 
   59 typedef void madt_entry_handler(APIC_HEADER *entry, void *arg);
   60 
   61 /* These two arrays are indexed by APIC IDs. */
   62 struct ioapic_info {
   63         void *io_apic;
   64         UINT32 io_vector;
   65 } ioapics[NIOAPICS];
   66 
   67 struct lapic_info {
   68         u_int la_enabled:1;
   69         u_int la_acpi_id:8;
   70 } lapics[NLAPICS];
   71 
   72 static int madt_found_sci_override;
   73 static MULTIPLE_APIC_TABLE *madt;
   74 static vm_paddr_t madt_physaddr;
   75 static vm_offset_t madt_length;
   76 
   77 MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
   78 
   79 static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
   80 static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
   81 static int      madt_find_cpu(u_int acpi_id, u_int *apic_id);
   82 static int      madt_find_interrupt(int intr, void **apic, u_int *pin);
   83 static void     *madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
   84 static void     *madt_map_table(vm_paddr_t pa, int offset, const char *sig);
   85 static void     madt_parse_apics(APIC_HEADER *entry, void *arg);
   86 static void     madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
   87 static void     madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
   88 static void     madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
   89 static void     madt_parse_nmi(MADT_NMI_SOURCE *nmi);
   90 static int      madt_probe(void);
   91 static int      madt_probe_cpus(void);
   92 static void     madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
   93 static int      madt_probe_table(vm_paddr_t address);
   94 static void     madt_register(void *dummy);
   95 static int      madt_setup_local(void);
   96 static int      madt_setup_io(void);
   97 static void     madt_unmap(void *data, vm_offset_t length);
   98 static void     madt_unmap_table(void *table);
   99 static void     madt_walk_table(madt_entry_handler *handler, void *arg);
  100 
  101 static struct apic_enumerator madt_enumerator = {
  102         "MADT",
  103         madt_probe,
  104         madt_probe_cpus,
  105         madt_setup_local,
  106         madt_setup_io
  107 };
  108 
  109 /*
  110  * Code to abuse the crashdump map to map in the tables for the early
  111  * probe.  We cheat and make the following assumptions about how we
  112  * use this KVA: page 0 is used to map in the first page of each table
  113  * found via the RSDT or XSDT and pages 1 to n are used to map in the
  114  * RSDT or XSDT.  The offset is in pages; the length is in bytes.
  115  */
  116 static void *
  117 madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
  118 {
  119         vm_offset_t va, off;
  120         void *data;
  121 
  122         off = pa & PAGE_MASK;
  123         length = roundup(length + off, PAGE_SIZE);
  124         pa = pa & PG_FRAME;
  125         va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
  126             (offset * PAGE_SIZE);
  127         data = (void *)(va + off);
  128         length -= PAGE_SIZE;
  129         while (length > 0) {
  130                 va += PAGE_SIZE;
  131                 pa += PAGE_SIZE;
  132                 length -= PAGE_SIZE;
  133                 pmap_kenter(va, pa);
  134                 invlpg(va);
  135         }
  136         return (data);
  137 }
  138 
  139 static void
  140 madt_unmap(void *data, vm_offset_t length)
  141 {
  142         vm_offset_t va, off;
  143 
  144         va = (vm_offset_t)data;
  145         off = va & PAGE_MASK;
  146         length = roundup(length + off, PAGE_SIZE);
  147         va &= ~PAGE_MASK;
  148         while (length > 0) {
  149                 pmap_kremove(va);
  150                 invlpg(va);
  151                 va += PAGE_SIZE;
  152                 length -= PAGE_SIZE;
  153         }
  154 }
  155 
  156 static void *
  157 madt_map_table(vm_paddr_t pa, int offset, const char *sig)
  158 {
  159         ACPI_TABLE_HEADER *header;
  160         vm_offset_t length;
  161         void *table;
  162 
  163         header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
  164         if (strncmp(header->Signature, sig, 4) != 0) {
  165                 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  166                 return (NULL);
  167         }
  168         length = header->Length;
  169         madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
  170         table = madt_map(pa, offset, length);
  171         if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
  172                 if (bootverbose)
  173                         printf("MADT: Failed checksum for table %s\n", sig);
  174                 madt_unmap(table, length);
  175                 return (NULL);
  176         }
  177         return (table);
  178 }
  179 
  180 static void
  181 madt_unmap_table(void *table)
  182 {
  183         ACPI_TABLE_HEADER *header;
  184 
  185         header = (ACPI_TABLE_HEADER *)table;
  186         madt_unmap(table, header->Length);
  187 }
  188 
  189 /*
  190  * Look for an ACPI Multiple APIC Description Table ("APIC")
  191  */
  192 static int
  193 madt_probe(void)
  194 {
  195         ACPI_POINTER rsdp_ptr;
  196         RSDP_DESCRIPTOR *rsdp;
  197         RSDT_DESCRIPTOR *rsdt;
  198         XSDT_DESCRIPTOR *xsdt;
  199         int i, count;
  200 
  201         if (resource_disabled("acpi", 0))
  202                 return (ENXIO);
  203 
  204         /*
  205          * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
  206          * calls pmap_mapdev() to find the RSDP, we assume that we can use
  207          * pmap_mapdev() to map the RSDP.
  208          */
  209         if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
  210                 return (ENXIO);
  211 #ifdef __i386__
  212         KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
  213 #endif
  214         rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
  215         if (rsdp == NULL) {
  216                 if (bootverbose)
  217                         printf("MADT: Failed to map RSDP\n");
  218                 return (ENXIO);
  219         }
  220 
  221         /*
  222          * For ACPI >= 2.0, use the XSDT if it is available.
  223          * Otherwise, use the RSDT.  We map the XSDT or RSDT at page 1
  224          * in the crashdump area.  Page 0 is used to map in the
  225          * headers of candidate ACPI tables.
  226          */
  227         if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
  228                 /*
  229                  * AcpiOsGetRootPointer only verifies the checksum for
  230                  * the version 1.0 portion of the RSDP.  Version 2.0 has
  231                  * an additional checksum that we verify first.
  232                  */
  233                 if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
  234                         if (bootverbose)
  235                                 printf("MADT: RSDP failed extended checksum\n");
  236                         return (ENXIO);
  237                 }
  238                 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
  239                 if (xsdt == NULL) {
  240                         if (bootverbose)
  241                                 printf("MADT: Failed to map XSDT\n");
  242                         return (ENXIO);
  243                 }
  244                 count = (xsdt->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, 1, RSDT_SIG);
  252                 if (rsdt == NULL) {
  253                         if (bootverbose)
  254                                 printf("MADT: Failed to map RSDT\n");
  255                         return (ENXIO);
  256                 }
  257                 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
  258                     sizeof(UINT32);
  259                 for (i = 0; i < count; i++)
  260                         if (madt_probe_table(rsdt->TableOffsetEntry[i]))
  261                                 break;
  262                 madt_unmap_table(rsdt);
  263         }
  264         pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
  265         if (madt_physaddr == 0) {
  266                 if (bootverbose)
  267                         printf("MADT: No MADT table found\n");
  268                 return (ENXIO);
  269         }
  270         if (bootverbose)
  271                 printf("MADT: Found table at 0x%jx\n",
  272                     (uintmax_t)madt_physaddr);
  273 
  274         /*
  275          * Verify that we can map the full table and that its checksum is
  276          * correct, etc.
  277          */
  278         madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
  279         if (madt == NULL)
  280                 return (ENXIO);
  281         madt_unmap_table(madt);
  282         madt = NULL;
  283 
  284         return (0);
  285 }
  286 
  287 /*
  288  * See if a given ACPI table is the MADT.
  289  */
  290 static int
  291 madt_probe_table(vm_paddr_t address)
  292 {
  293         ACPI_TABLE_HEADER *table;
  294 
  295         table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
  296         if (table == NULL) {
  297                 if (bootverbose)
  298                         printf("MADT: Failed to map table at 0x%jx\n",
  299                             (uintmax_t)address);
  300                 return (0);
  301         }
  302         if (bootverbose)
  303                 printf("Table '%.4s' at 0x%jx\n", table->Signature,
  304                     (uintmax_t)address);
  305 
  306         if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
  307                 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  308                 return (0);
  309         }
  310         madt_physaddr = address;
  311         madt_length = table->Length;
  312         madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
  313         return (1);
  314 }
  315 
  316 /*
  317  * Run through the MP table enumerating CPUs.
  318  */
  319 static int
  320 madt_probe_cpus(void)
  321 {
  322 
  323         madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
  324         KASSERT(madt != NULL, ("Unable to re-map MADT"));
  325         madt_walk_table(madt_probe_cpus_handler, NULL);
  326         madt_unmap_table(madt);
  327         madt = NULL;
  328         return (0);
  329 }
  330 
  331 /*
  332  * Initialize the local APIC on the BSP.
  333  */
  334 static int
  335 madt_setup_local(void)
  336 {
  337 
  338         madt = pmap_mapdev(madt_physaddr, madt_length);
  339         lapic_init((uintptr_t)madt->LocalApicAddress);
  340         printf("ACPI APIC Table: <%.*s %.*s>\n",
  341             (int)sizeof(madt->OemId), madt->OemId,
  342             (int)sizeof(madt->OemTableId), madt->OemTableId);
  343 
  344         /*
  345          * We ignore 64-bit local APIC override entries.  Should we
  346          * perhaps emit a warning here if we find one?
  347          */
  348         return (0);
  349 }
  350 
  351 /*
  352  * Enumerate I/O APICs and setup interrupt sources.
  353  */
  354 static int
  355 madt_setup_io(void)
  356 {
  357         void *ioapic;
  358         u_int pin;
  359         int i;
  360 
  361         /* Try to initialize ACPI so that we can access the FADT. */
  362         i = acpi_Startup();
  363         if (ACPI_FAILURE(i)) {
  364                 printf("MADT: ACPI Startup failed with %s\n",
  365                     AcpiFormatException(i));
  366                 printf("Try disabling either ACPI or apic support.\n");
  367                 panic("Using MADT but ACPI doesn't work");
  368         }
  369                     
  370         /* First, we run through adding I/O APIC's. */
  371         madt_walk_table(madt_parse_apics, NULL);
  372 
  373         /* Second, we run through the table tweaking interrupt sources. */
  374         madt_walk_table(madt_parse_ints, NULL);
  375 
  376         /*
  377          * If there was not an explicit override entry for the SCI,
  378          * force it to use level trigger and active-low polarity.
  379          */
  380         if (!madt_found_sci_override) {
  381                 if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
  382                     != 0)
  383                         printf("MADT: Could not find APIC for SCI IRQ %d\n",
  384                             AcpiGbl_FADT->SciInt);
  385                 else {
  386                         printf(
  387         "MADT: Forcing active-low polarity and level trigger for SCI\n");
  388                         ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
  389                         ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
  390                 }
  391         }
  392 
  393         /* Third, we register all the I/O APIC's. */
  394         for (i = 0; i < NIOAPICS; i++)
  395                 if (ioapics[i].io_apic != NULL)
  396                         ioapic_register(ioapics[i].io_apic);
  397 
  398         /* Finally, we throw the switch to enable the I/O APIC's. */
  399         acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
  400 
  401         return (0);
  402 }
  403 
  404 static void
  405 madt_register(void *dummy __unused)
  406 {
  407 
  408         apic_register_enumerator(&madt_enumerator);
  409 }
  410 SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
  411 
  412 /*
  413  * Call the handler routine for each entry in the MADT table.
  414  */
  415 static void
  416 madt_walk_table(madt_entry_handler *handler, void *arg)
  417 {
  418         APIC_HEADER *entry;
  419         u_char *p, *end;
  420 
  421         end = (u_char *)(madt) + madt->Length;
  422         for (p = (u_char *)(madt + 1); p < end; ) {
  423                 entry = (APIC_HEADER *)p;
  424                 handler(entry, arg);
  425                 p += entry->Length;
  426         }
  427 }
  428 
  429 static void
  430 madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
  431 {
  432         MADT_PROCESSOR_APIC *proc;
  433         struct lapic_info *la;
  434 
  435         switch (entry->Type) {
  436         case APIC_PROCESSOR:
  437                 /*
  438                  * The MADT does not include a BSP flag, so we have to
  439                  * let the MP code figure out which CPU is the BSP on
  440                  * its own.
  441                  */
  442                 proc = (MADT_PROCESSOR_APIC *)entry;
  443                 if (bootverbose)
  444                         printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
  445                             proc->LocalApicId, proc->ProcessorId,
  446                             proc->ProcessorEnabled ? "enabled" : "disabled");
  447                 if (!proc->ProcessorEnabled)
  448                         break;
  449                 if (proc->LocalApicId >= NLAPICS)
  450                         panic("%s: CPU ID %d too high", __func__,
  451                             proc->LocalApicId);
  452                 la = &lapics[proc->LocalApicId];
  453                 KASSERT(la->la_enabled == 0,
  454                     ("Duplicate local APIC ID %d", proc->LocalApicId));
  455                 la->la_enabled = 1;
  456                 la->la_acpi_id = proc->ProcessorId;
  457                 lapic_create(proc->LocalApicId, 0);
  458                 break;
  459         }
  460 }
  461 
  462 
  463 /*
  464  * Add an I/O APIC from an entry in the table.
  465  */
  466 static void
  467 madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
  468 {
  469         MADT_IO_APIC *apic;
  470 
  471         switch (entry->Type) {
  472         case APIC_IO:
  473                 apic = (MADT_IO_APIC *)entry;
  474                 if (bootverbose)
  475                         printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
  476                             apic->IoApicId, apic->Interrupt,
  477                             (void *)(uintptr_t)apic->Address);
  478                 if (apic->IoApicId >= NIOAPICS)
  479                         panic("%s: I/O APIC ID %d too high", __func__,
  480                             apic->IoApicId);
  481                 if (ioapics[apic->IoApicId].io_apic != NULL)
  482                         panic("%s: Double APIC ID %d", __func__,
  483                             apic->IoApicId);
  484                 ioapics[apic->IoApicId].io_apic = ioapic_create(
  485                         (uintptr_t)apic->Address, apic->IoApicId,
  486                             apic->Interrupt);
  487                 ioapics[apic->IoApicId].io_vector = apic->Interrupt;
  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 Polarity, UINT8 Source)
  502 {
  503 
  504         switch (Polarity) {
  505         case POLARITY_CONFORMS:
  506                 if (Source == AcpiGbl_FADT->SciInt)
  507                         return (INTR_POLARITY_LOW);
  508                 else
  509                         return (INTR_POLARITY_HIGH);
  510         case POLARITY_ACTIVE_HIGH:
  511                 return (INTR_POLARITY_HIGH);
  512         case 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 TriggerMode, UINT8 Source)
  521 {
  522 
  523         switch (TriggerMode) {
  524         case TRIGGER_CONFORMS:
  525                 if (Source == AcpiGbl_FADT->SciInt)
  526                         return (INTR_TRIGGER_LEVEL);
  527                 else
  528                         return (INTR_TRIGGER_EDGE);
  529         case TRIGGER_EDGE:
  530                 return (INTR_TRIGGER_EDGE);
  531         case 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 < NLAPICS; 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 < NIOAPICS; 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(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->Source == 0 &&
  598             intr->Interrupt == 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->Source, intr->Interrupt);
  606         KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
  607         if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
  608             &new_pin) != 0) {
  609                 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
  610                     intr->Interrupt, intr->Source);
  611                 return;
  612         }
  613 
  614         /*
  615          * Lookup the appropriate trigger and polarity modes for this
  616          * entry.
  617          */
  618         trig = interrupt_trigger(intr->TriggerMode, intr->Source);
  619         pol = interrupt_polarity(intr->Polarity, intr->Source);
  620         
  621         /*
  622          * If the SCI is identity mapped but has edge trigger and
  623          * active-hi polarity or the force_sci_lo tunable is set,
  624          * force it to use level/lo.
  625          */
  626         if (intr->Source == AcpiGbl_FADT->SciInt) {
  627                 madt_found_sci_override = 1;
  628                 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
  629                         if (tolower(buf[0]) == 'e')
  630                                 trig = INTR_TRIGGER_EDGE;
  631                         else if (tolower(buf[0]) == 'l')
  632                                 trig = INTR_TRIGGER_LEVEL;
  633                         else
  634                                 panic(
  635                                 "Invalid trigger %s: must be 'edge' or 'level'",
  636                                     buf);
  637                         printf("MADT: Forcing SCI to %s trigger\n",
  638                             trig == INTR_TRIGGER_EDGE ? "edge" : "level");
  639                 }
  640                 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
  641                         if (tolower(buf[0]) == 'h')
  642                                 pol = INTR_POLARITY_HIGH;
  643                         else if (tolower(buf[0]) == 'l')
  644                                 pol = INTR_POLARITY_LOW;
  645                         else
  646                                 panic(
  647                                 "Invalid polarity %s: must be 'high' or 'low'",
  648                                     buf);
  649                         printf("MADT: Forcing SCI to active %s polarity\n",
  650                             pol == INTR_POLARITY_HIGH ? "high" : "low");
  651                 }
  652         }
  653 
  654         /* Remap the IRQ if it is mapped to a different interrupt vector. */
  655         if (intr->Source != intr->Interrupt) {
  656                 /*
  657                  * If the SCI is remapped to a non-ISA global interrupt,
  658                  * then override the vector we use to setup and allocate
  659                  * the interrupt.
  660                  */
  661                 if (intr->Interrupt > 15 &&
  662                     intr->Source == AcpiGbl_FADT->SciInt)
  663                         acpi_OverrideInterruptLevel(intr->Interrupt);
  664                 else
  665                         ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
  666                 if (madt_find_interrupt(intr->Source, &old_ioapic,
  667                     &old_pin) != 0)
  668                         printf("MADT: Could not find APIC for source IRQ %d\n",
  669                             intr->Source);
  670                 else if (ioapic_get_vector(old_ioapic, old_pin) ==
  671                     intr->Source)
  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(MADT_NMI_SOURCE *nmi)
  685 {
  686         void *ioapic;
  687         u_int pin;
  688 
  689         if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
  690                 printf("MADT: Could not find APIC for vector %d\n",
  691                     nmi->Interrupt);
  692                 return;
  693         }
  694 
  695         ioapic_set_nmi(ioapic, pin);
  696         if (nmi->TriggerMode != TRIGGER_CONFORMS)
  697                 ioapic_set_triggermode(ioapic, pin,
  698                     interrupt_trigger(nmi->TriggerMode, 0));
  699         if (nmi->Polarity != TRIGGER_CONFORMS)
  700                 ioapic_set_polarity(ioapic, pin,
  701                     interrupt_polarity(nmi->Polarity, 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(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 ACPI CPU %u\n",
  717                             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->TriggerMode != TRIGGER_CONFORMS)
  726                 lapic_set_lvt_triggermode(apic_id, pin,
  727                     interrupt_trigger(nmi->TriggerMode, 0));
  728         if (nmi->Polarity != POLARITY_CONFORMS)
  729                 lapic_set_lvt_polarity(apic_id, pin,
  730                     interrupt_polarity(nmi->Polarity, 0));
  731 }
  732 
  733 /*
  734  * Parse interrupt entries.
  735  */
  736 static void
  737 madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
  738 {
  739 
  740         switch (entry->Type) {
  741         case APIC_XRUPT_OVERRIDE:
  742                 madt_parse_interrupt_override(
  743                         (MADT_INTERRUPT_OVERRIDE *)entry);
  744                 break;
  745         case APIC_NMI:
  746                 madt_parse_nmi((MADT_NMI_SOURCE *)entry);
  747                 break;
  748         case APIC_LOCAL_NMI:
  749                 madt_parse_local_nmi((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 %d", 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: 7120f66704f86bbe31ad042f80cb2f87


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