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/amd64/amd64/mptable.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  * Copyright (c) 1996, by Steve Passe
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. The name of the developer may NOT be used to endorse or promote products
   12  *    derived from this software without specific prior written permission.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/5.2/sys/amd64/amd64/mptable.c 122849 2003-11-17 08:58:16Z peter $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 
   36 #include <vm/vm.h>
   37 #include <vm/vm_param.h>
   38 #include <vm/pmap.h>
   39 
   40 #include <machine/apicreg.h>
   41 #include <machine/frame.h>
   42 #include <machine/intr_machdep.h>
   43 #include <machine/apicvar.h>
   44 #include <machine/md_var.h>
   45 #include <machine/mptable.h>
   46 #include <machine/specialreg.h>
   47 
   48 #include <dev/pci/pcivar.h>
   49 
   50 /* EISA Edge/Level trigger control registers */
   51 #define ELCR0   0x4d0                   /* eisa irq 0-7 */
   52 #define ELCR1   0x4d1                   /* eisa irq 8-15 */
   53 
   54 /* string defined by the Intel MP Spec as identifying the MP table */
   55 #define MP_SIG                  0x5f504d5f      /* _MP_ */
   56 
   57 #define NAPICID                 32      /* Max number of I/O APIC's */
   58 
   59 #define BIOS_BASE               (0xf0000)
   60 #define BIOS_SIZE               (0x10000)
   61 #define BIOS_COUNT              (BIOS_SIZE/4)
   62 
   63 typedef void mptable_entry_handler(u_char *entry, void *arg);
   64 
   65 static basetable_entry basetable_entry_types[] =
   66 {
   67         {0, 20, "Processor"},
   68         {1, 8, "Bus"},
   69         {2, 8, "I/O APIC"},
   70         {3, 8, "I/O INT"},
   71         {4, 8, "Local INT"}
   72 };
   73 
   74 typedef struct BUSDATA {
   75         u_char  bus_id;
   76         enum busTypes bus_type;
   77 }       bus_datum;
   78 
   79 typedef struct INTDATA {
   80         u_char  int_type;
   81         u_short int_flags;
   82         u_char  src_bus_id;
   83         u_char  src_bus_irq;
   84         u_char  dst_apic_id;
   85         u_char  dst_apic_int;
   86         u_char  int_vector;
   87 }       io_int, local_int;
   88 
   89 typedef struct BUSTYPENAME {
   90         u_char  type;
   91         char    name[7];
   92 }       bus_type_name;
   93 
   94 /* From MP spec v1.4, table 4-8. */
   95 static bus_type_name bus_type_table[] =
   96 {
   97         {UNKNOWN_BUSTYPE, "CBUS  "},
   98         {UNKNOWN_BUSTYPE, "CBUSII"},
   99         {EISA, "EISA  "},
  100         {UNKNOWN_BUSTYPE, "FUTURE"},
  101         {UNKNOWN_BUSTYPE, "INTERN"},
  102         {ISA, "ISA   "},
  103         {UNKNOWN_BUSTYPE, "MBI   "},
  104         {UNKNOWN_BUSTYPE, "MBII  "},
  105         {MCA, "MCA   "},
  106         {UNKNOWN_BUSTYPE, "MPI   "},
  107         {UNKNOWN_BUSTYPE, "MPSA  "},
  108         {UNKNOWN_BUSTYPE, "NUBUS "},
  109         {PCI, "PCI   "},
  110         {UNKNOWN_BUSTYPE, "PCMCIA"},
  111         {UNKNOWN_BUSTYPE, "TC    "},
  112         {UNKNOWN_BUSTYPE, "VL    "},
  113         {UNKNOWN_BUSTYPE, "VME   "},
  114         {UNKNOWN_BUSTYPE, "XPRESS"}
  115 };
  116 
  117 /* From MP spec v1.4, table 5-1. */
  118 static int default_data[7][5] =
  119 {
  120 /*   nbus, id0, type0, id1, type1 */
  121         {1, 0, ISA, 255, NOBUS},
  122         {1, 0, EISA, 255, NOBUS},
  123         {1, 0, EISA, 255, NOBUS},
  124         {1, 0, MCA, 255, NOBUS},
  125         {2, 0, ISA, 1, PCI},
  126         {2, 0, EISA, 1, PCI},
  127         {2, 0, MCA, 1, PCI}
  128 };
  129 
  130 struct pci_probe_table_args {
  131         u_char bus;
  132         u_char found;
  133 };
  134 
  135 struct pci_route_interrupt_args {
  136         u_char bus;             /* Source bus. */
  137         u_char irq;             /* Source slot:pin. */
  138         int vector;             /* Return value. */
  139 };
  140 
  141 static mpfps_t mpfps;
  142 static mpcth_t mpct;
  143 static void *ioapics[NAPICID];
  144 static bus_datum *busses;
  145 static int mptable_nioapics, mptable_nbusses, mptable_maxbusid;
  146 static int pci0 = -1;
  147 
  148 MALLOC_DEFINE(M_MPTABLE, "MP Table", "MP Table Items");
  149 
  150 static u_char   conforming_polarity(u_char src_bus);
  151 static u_char   conforming_trigger(u_char src_bus, u_char src_bus_irq);
  152 static u_char   intentry_polarity(int_entry_ptr intr);
  153 static u_char   intentry_trigger(int_entry_ptr intr);
  154 static int      lookup_bus_type(char *name);
  155 static void     mptable_count_items(void);
  156 static void     mptable_count_items_handler(u_char *entry, void *arg);
  157 #ifdef MPTABLE_FORCE_HTT
  158 static void     mptable_hyperthread_fixup(u_int id_mask);
  159 #endif
  160 static void     mptable_parse_apics_and_busses(void);
  161 static void     mptable_parse_apics_and_busses_handler(u_char *entry,
  162     void *arg);
  163 static void     mptable_parse_ints(void);
  164 static void     mptable_parse_ints_handler(u_char *entry, void *arg);
  165 static void     mptable_parse_io_int(int_entry_ptr intr);
  166 static void     mptable_parse_local_int(int_entry_ptr intr);
  167 static void     mptable_pci_probe_table_handler(u_char *entry, void *arg);
  168 static void     mptable_pci_route_interrupt_handler(u_char *entry, void *arg);
  169 static void     mptable_pci_setup(void);
  170 static int      mptable_probe(void);
  171 static int      mptable_probe_cpus(void);
  172 static void     mptable_probe_cpus_handler(u_char *entry, void *arg __unused);
  173 static void     mptable_register(void *dummy);
  174 static int      mptable_setup_local(void);
  175 static int      mptable_setup_io(void);
  176 static void     mptable_walk_table(mptable_entry_handler *handler, void *arg);
  177 static int      search_for_sig(u_int32_t target, int count);
  178 
  179 static struct apic_enumerator mptable_enumerator = {
  180         "MPTable",
  181         mptable_probe,
  182         mptable_probe_cpus,
  183         mptable_setup_local,
  184         mptable_setup_io
  185 };
  186 
  187 /*
  188  * look for the MP spec signature
  189  */
  190 
  191 static int
  192 search_for_sig(u_int32_t target, int count)
  193 {
  194         int     x;
  195         u_int32_t *addr = (u_int32_t *) (KERNBASE + target);
  196 
  197         for (x = 0; x < count; x += 4)
  198                 if (addr[x] == MP_SIG)
  199                         /* make array index a byte index */
  200                         return (target + (x * sizeof(u_int32_t)));
  201         return (-1);
  202 }
  203 
  204 static int
  205 lookup_bus_type(char *name)
  206 {
  207         int     x;
  208 
  209         for (x = 0; x < MAX_BUSTYPE; ++x)
  210                 if (strncmp(bus_type_table[x].name, name, 6) == 0)
  211                         return (bus_type_table[x].type);
  212 
  213         return (UNKNOWN_BUSTYPE);
  214 }
  215 
  216 /*
  217  * Look for an Intel MP spec table (ie, SMP capable hardware).
  218  */
  219 static int
  220 mptable_probe(void)
  221 {
  222         int     x;
  223         u_int32_t segment;
  224         u_int32_t target;
  225 
  226         /* see if EBDA exists */
  227         segment = (u_int32_t) *(u_short *)(KERNBASE + 0x40e);
  228         if (segment != 0) {
  229                 /* search first 1K of EBDA */
  230                 target = (u_int32_t) (segment << 4);
  231                 if ((x = search_for_sig(target, 1024 / 4)) >= 0)
  232                         goto found;
  233         } else {
  234                 /* last 1K of base memory, effective 'top of base' passed in */
  235                 target = (u_int32_t) ((basemem * 1024) - 0x400);
  236                 if ((x = search_for_sig(target, 1024 / 4)) >= 0)
  237                         goto found;
  238         }
  239 
  240         /* search the BIOS */
  241         target = (u_int32_t) BIOS_BASE;
  242         if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
  243                 goto found;
  244 
  245         /* nothing found */
  246         return (ENXIO);
  247 
  248 found:
  249         mpfps = (mpfps_t)(KERNBASE + x);
  250 
  251         /* Map in the configuration table if it exists. */
  252         if (mpfps->config_type != 0)
  253                 mpct = NULL;
  254         else {
  255                 if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
  256                         printf("%s: Unable to map MP Configuration Table\n",
  257                             __func__);
  258                         return (ENXIO);
  259                 }
  260                 mpct = (mpcth_t)(KERNBASE + (uintptr_t)mpfps->pap);
  261                 if (mpct->base_table_length + (uintptr_t)mpfps->pap >=
  262                     1024 * 1024) {
  263                         printf("%s: Unable to map end of MP Config Table\n",
  264                             __func__);
  265                         return (ENXIO);
  266                 }
  267                 if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' ||
  268                     mpct->signature[2] != 'M' || mpct->signature[3] != 'P') {
  269                         printf("%s: MP Config Table has bad signature: %c%c%c%c\n",
  270                             __func__, mpct->signature[0], mpct->signature[1],
  271                             mpct->signature[2], mpct->signature[3]);
  272                         return (ENXIO);
  273                 }
  274                 if (bootverbose)
  275                         printf(
  276                         "MP Configuration Table version 1.%d found at %p\n",
  277                             mpct->spec_rev, mpct);
  278         }
  279 
  280         return (-100);
  281 }
  282 
  283 /*
  284  * Run through the MP table enumerating CPUs.
  285  */
  286 static int
  287 mptable_probe_cpus(void)
  288 {
  289         u_int cpu_mask;
  290 
  291         /* Is this a pre-defined config? */
  292         if (mpfps->config_type != 0) {
  293                 lapic_create(0, 1);
  294                 lapic_create(1, 0);
  295         } else {
  296                 cpu_mask = 0;
  297                 mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask);
  298 #ifdef MPTABLE_FORCE_HTT
  299                 mptable_hyperthread_fixup(cpu_mask);
  300 #endif
  301         }
  302         return (0);
  303 }
  304 
  305 /*
  306  * Initialize the local APIC on the BSP.
  307  */
  308 static int
  309 mptable_setup_local(void)
  310 {
  311 
  312         /* Is this a pre-defined config? */
  313         printf("MPTable: <");
  314         if (mpfps->config_type != 0) {
  315                 lapic_init(DEFAULT_APIC_BASE);
  316                 printf("Preset Config %d", mpfps->config_type);
  317         } else {
  318                 lapic_init((uintptr_t)mpct->apic_address);
  319                 printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
  320                     (int)sizeof(mpct->product_id), mpct->product_id);
  321         }
  322         printf(">\n");
  323         return (0);
  324 }
  325 
  326 /*
  327  * Run through the MP table enumerating I/O APICs.
  328  */
  329 static int
  330 mptable_setup_io(void)
  331 {
  332         int i;
  333         u_char byte;
  334 
  335         /* First, we count individual items and allocate arrays. */
  336         mptable_count_items();
  337         busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE,
  338             M_WAITOK);
  339         for (i = 0; i <= mptable_maxbusid; i++)
  340                 busses[i].bus_type = NOBUS;
  341 
  342         /* Second, we run through adding I/O APIC's and busses. */
  343         mptable_parse_apics_and_busses();       
  344 
  345         /* Third, we run through the table tweaking interrupt sources. */
  346         mptable_parse_ints();
  347 
  348         /* Fourth, we register all the I/O APIC's. */
  349         for (i = 0; i < NAPICID; i++)
  350                 if (ioapics[i] != NULL)
  351                         ioapic_register(ioapics[i]);
  352 
  353         /* Fifth, we setup data structures to handle PCI interrupt routing. */
  354         mptable_pci_setup();
  355 
  356         /* Finally, we throw the switch to enable the I/O APIC's. */
  357         if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) {
  358                 outb(0x22, 0x70);       /* select IMCR */
  359                 byte = inb(0x23);       /* current contents */
  360                 byte |= 0x01;           /* mask external INTR */
  361                 outb(0x23, byte);       /* disconnect 8259s/NMI */
  362         }
  363 
  364         return (0);
  365 }
  366 
  367 static void
  368 mptable_register(void *dummy __unused)
  369 {
  370 
  371         apic_register_enumerator(&mptable_enumerator);
  372 }
  373 SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,
  374     mptable_register, NULL)
  375 
  376 /*
  377  * Call the handler routine for each entry in the MP config table.
  378  */
  379 static void
  380 mptable_walk_table(mptable_entry_handler *handler, void *arg)
  381 {
  382         u_int i;
  383         u_char *entry;
  384 
  385         entry = (u_char *)(mpct + 1);
  386         for (i = 0; i < mpct->entry_count; i++) {
  387                 switch (*entry) {
  388                 case MPCT_ENTRY_PROCESSOR:
  389                 case MPCT_ENTRY_IOAPIC:
  390                 case MPCT_ENTRY_BUS:
  391                 case MPCT_ENTRY_INT:
  392                 case MPCT_ENTRY_LOCAL_INT:
  393                         break;
  394                 default:
  395                         panic("%s: Unknown MP Config Entry %d\n", __func__,
  396                             (int)*entry);
  397                 }
  398                 handler(entry, arg);
  399                 entry += basetable_entry_types[*entry].length;
  400         }
  401 }
  402 
  403 static void
  404 mptable_probe_cpus_handler(u_char *entry, void *arg)
  405 {
  406         proc_entry_ptr proc;
  407         u_int *cpu_mask;
  408 
  409         switch (*entry) {
  410         case MPCT_ENTRY_PROCESSOR:
  411                 proc = (proc_entry_ptr)entry;
  412                 if (proc->cpu_flags & PROCENTRY_FLAG_EN) {
  413                         lapic_create(proc->apic_id, proc->cpu_flags &
  414                             PROCENTRY_FLAG_BP);
  415                         cpu_mask = (u_int *)arg;
  416                         *cpu_mask |= (1 << proc->apic_id);
  417                 }
  418                 break;
  419         }
  420 }
  421 
  422 static void
  423 mptable_count_items_handler(u_char *entry, void *arg __unused)
  424 {
  425         io_apic_entry_ptr apic;
  426         bus_entry_ptr bus;
  427 
  428         switch (*entry) {
  429         case MPCT_ENTRY_BUS:
  430                 bus = (bus_entry_ptr)entry;
  431                 mptable_nbusses++;
  432                 if (bus->bus_id > mptable_maxbusid)
  433                         mptable_maxbusid = bus->bus_id;
  434                 break;
  435         case MPCT_ENTRY_IOAPIC:
  436                 apic = (io_apic_entry_ptr)entry;
  437                 if (apic->apic_flags & IOAPICENTRY_FLAG_EN)
  438                         mptable_nioapics++;
  439                 break;
  440         }
  441 }
  442 
  443 /*
  444  * Count items in the table.
  445  */
  446 static void
  447 mptable_count_items(void)
  448 {
  449 
  450         /* Is this a pre-defined config? */
  451         if (mpfps->config_type != 0) {
  452                 mptable_nioapics = 1;
  453                 switch (mpfps->config_type) {
  454                 case 1:
  455                 case 2:
  456                 case 3:
  457                 case 4:
  458                         mptable_nbusses = 1;
  459                         break;
  460                 case 5:
  461                 case 6:
  462                 case 7:
  463                         mptable_nbusses = 2;
  464                         break;
  465                 default:
  466                         panic("Unknown pre-defined MP Table config type %d",
  467                             mpfps->config_type);
  468                 }
  469                 mptable_maxbusid = mptable_nbusses - 1;
  470         } else
  471                 mptable_walk_table(mptable_count_items_handler, NULL);
  472 }
  473 
  474 /*
  475  * Add a bus or I/O APIC from an entry in the table.
  476  */
  477 static void
  478 mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused)
  479 {
  480         io_apic_entry_ptr apic;
  481         bus_entry_ptr bus;
  482         enum busTypes bus_type;
  483         int i;
  484 
  485 
  486         switch (*entry) {
  487         case MPCT_ENTRY_BUS:
  488                 bus = (bus_entry_ptr)entry;
  489                 bus_type = lookup_bus_type(bus->bus_type);
  490                 if (bus_type == UNKNOWN_BUSTYPE) {
  491                         printf("MPTable: Unknown bus %d type \"", bus->bus_id);
  492                         for (i = 0; i < 6; i++)
  493                                 printf("%c", bus->bus_type[i]);
  494                         printf("\"\n");
  495                 }
  496                 busses[bus->bus_id].bus_id = bus->bus_id;
  497                 busses[bus->bus_id].bus_type = bus_type;
  498                 break;
  499         case MPCT_ENTRY_IOAPIC:
  500                 apic = (io_apic_entry_ptr)entry;
  501                 if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN))
  502                         break;
  503                 if (apic->apic_id >= NAPICID)
  504                         panic("%s: I/O APIC ID %d too high", __func__,
  505                             apic->apic_id);
  506                 if (ioapics[apic->apic_id] != NULL)
  507                         panic("%s: Double APIC ID %d", __func__,
  508                             apic->apic_id);
  509                 ioapics[apic->apic_id] = ioapic_create(
  510                         (uintptr_t)apic->apic_address, apic->apic_id, -1);
  511                 break;
  512         default:
  513                 break;
  514         }
  515 }
  516 
  517 /*
  518  * Enumerate I/O APIC's and busses.
  519  */
  520 static void
  521 mptable_parse_apics_and_busses(void)
  522 {
  523 
  524         /* Is this a pre-defined config? */
  525         if (mpfps->config_type != 0) {
  526                 ioapics[0] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0);
  527                 busses[0].bus_id = 0;
  528                 busses[0].bus_type = default_data[mpfps->config_type][2];
  529                 if (mptable_nbusses > 1) {
  530                         busses[1].bus_id = 1;
  531                         busses[1].bus_type =
  532                             default_data[mpfps->config_type][4];
  533                 }
  534         } else
  535                 mptable_walk_table(mptable_parse_apics_and_busses_handler,
  536                     NULL);
  537 }
  538 
  539 /*
  540  * Determine conforming polarity for a given bus type.
  541  */
  542 static u_char
  543 conforming_polarity(u_char src_bus)
  544 {
  545 
  546         KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
  547         switch (busses[src_bus].bus_type) {
  548         case ISA:
  549         case EISA:
  550                 /* Active Hi */
  551                 return (1);
  552         case PCI:
  553                 /* Active Lo */
  554                 return (0);
  555         default:
  556                 panic("%s: unknown bus type %d", __func__,
  557                     busses[src_bus].bus_type);
  558         }
  559 }
  560 
  561 /*
  562  * Determine conforming trigger for a given bus type.
  563  */
  564 static u_char
  565 conforming_trigger(u_char src_bus, u_char src_bus_irq)
  566 {
  567         static int eisa_int_control = -1;
  568 
  569         KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
  570         switch (busses[src_bus].bus_type) {
  571         case ISA:
  572                 /* Edge Triggered */
  573                 return (1);
  574         case PCI:
  575                 /* Level Triggered */
  576                 return (0);
  577         case EISA:
  578                 KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq));
  579                 if (eisa_int_control == -1)
  580                         eisa_int_control = inb(ELCR1) << 8 | inb(ELCR0);
  581                 if (eisa_int_control & (1 << src_bus_irq))
  582                         /* Level Triggered */
  583                         return (0);
  584                 else
  585                         /* Edge Triggered */
  586                         return (1);
  587         default:
  588                 panic("%s: unknown bus type %d", __func__,
  589                     busses[src_bus].bus_type);
  590         }
  591 }
  592 
  593 static u_char
  594 intentry_polarity(int_entry_ptr intr)
  595 {
  596 
  597         switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) {
  598         case INTENTRY_FLAGS_POLARITY_CONFORM:
  599                 return (conforming_polarity(intr->src_bus_id));
  600         case INTENTRY_FLAGS_POLARITY_ACTIVEHI:
  601                 return (1);
  602         case INTENTRY_FLAGS_POLARITY_ACTIVELO:
  603                 return (0);
  604         default:
  605                 panic("Bogus interrupt flags");
  606         }
  607 }
  608 
  609 static u_char
  610 intentry_trigger(int_entry_ptr intr)
  611 {
  612 
  613         switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) {
  614         case INTENTRY_FLAGS_TRIGGER_CONFORM:
  615                 return (conforming_trigger(intr->src_bus_id,
  616                             intr->src_bus_irq));
  617         case INTENTRY_FLAGS_TRIGGER_EDGE:
  618                 return (1);
  619         case INTENTRY_FLAGS_TRIGGER_LEVEL:
  620                 return (0);
  621         default:
  622                 panic("Bogus interrupt flags");
  623         }
  624 }
  625 
  626 /*
  627  * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC.
  628  */
  629 static void
  630 mptable_parse_io_int(int_entry_ptr intr)
  631 {
  632         void *ioapic;
  633         u_int pin;
  634 
  635         if (intr->dst_apic_id == 0xff) {
  636                 printf("MPTable: Ignoring global interrupt entry for pin %d\n",
  637                     intr->dst_apic_int);
  638                 return;
  639         }
  640         if (intr->dst_apic_id >= NAPICID) {
  641                 printf("MPTable: Ignoring interrupt entry for ioapic%d\n",
  642                     intr->dst_apic_id);
  643                 return;
  644         }
  645         ioapic = ioapics[intr->dst_apic_id];
  646         if (ioapic == NULL) {
  647                 printf(
  648         "MPTable: Ignoring interrupt entry for missing ioapic%d\n",
  649                     intr->dst_apic_id);
  650                 return;
  651         }
  652         pin = intr->dst_apic_int;
  653         switch (intr->int_type) {
  654         case INTENTRY_TYPE_INT:
  655                 if (busses[intr->src_bus_id].bus_type == NOBUS)
  656                         panic("interrupt from missing bus");
  657                 if (busses[intr->src_bus_id].bus_type == ISA &&
  658                     intr->src_bus_irq != pin) {
  659                         ioapic_remap_vector(ioapic, pin, intr->src_bus_irq);
  660                         if (ioapic_get_vector(ioapic, intr->src_bus_irq) ==
  661                             intr->src_bus_irq)
  662                                 ioapic_disable_pin(ioapic, intr->src_bus_irq);
  663                 }
  664                 break;
  665         case INTENTRY_TYPE_NMI:
  666                 ioapic_set_nmi(ioapic, pin);
  667                 break;
  668         case INTENTRY_TYPE_SMI:
  669                 ioapic_set_smi(ioapic, pin);
  670                 break;
  671         case INTENTRY_TYPE_EXTINT:
  672                 ioapic_set_extint(ioapic, pin);
  673                 break;
  674         default:
  675                 panic("%s: invalid interrupt entry type %d\n", __func__,
  676                     intr->int_type);
  677         }
  678         if (intr->int_type == INTENTRY_TYPE_INT ||
  679             (intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
  680             INTENTRY_FLAGS_TRIGGER_CONFORM)
  681                 ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr));
  682         if (intr->int_type == INTENTRY_TYPE_INT ||
  683             (intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
  684             INTENTRY_FLAGS_POLARITY_CONFORM)
  685                 ioapic_set_polarity(ioapic, pin, intentry_polarity(intr));
  686 }
  687 
  688 /*
  689  * Parse an interrupt entry for a local APIC LVT pin.
  690  */
  691 static void
  692 mptable_parse_local_int(int_entry_ptr intr)
  693 {
  694         u_int apic_id, pin;
  695 
  696         if (intr->dst_apic_id == 0xff)
  697                 apic_id = APIC_ID_ALL;
  698         else
  699                 apic_id = intr->dst_apic_id;
  700         if (intr->dst_apic_int == 0)
  701                 pin = LVT_LINT0;
  702         else
  703                 pin = LVT_LINT1;
  704         switch (intr->int_type) {
  705         case INTENTRY_TYPE_INT:
  706 #if 1
  707                 printf(
  708         "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n",
  709                     intr->dst_apic_int, intr->src_bus_irq);
  710                 return;
  711 #else
  712                 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED);
  713                 break;
  714 #endif
  715         case INTENTRY_TYPE_NMI:
  716                 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
  717                 break;
  718         case INTENTRY_TYPE_SMI:
  719                 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI);
  720                 break;
  721         case INTENTRY_TYPE_EXTINT:
  722                 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT);
  723                 break;
  724         default:
  725                 panic("%s: invalid interrupt entry type %d\n", __func__,
  726                     intr->int_type);
  727         }
  728         if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
  729             INTENTRY_FLAGS_TRIGGER_CONFORM)
  730                 lapic_set_lvt_triggermode(apic_id, pin,
  731                     intentry_trigger(intr));
  732         if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
  733             INTENTRY_FLAGS_POLARITY_CONFORM)
  734                 lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr));
  735 }
  736 
  737 /*
  738  * Parse interrupt entries.
  739  */
  740 static void
  741 mptable_parse_ints_handler(u_char *entry, void *arg __unused)
  742 {
  743         int_entry_ptr intr;
  744 
  745         intr = (int_entry_ptr)entry;
  746         switch (*entry) {
  747         case MPCT_ENTRY_INT:
  748                 mptable_parse_io_int(intr);
  749                 break;
  750         case MPCT_ENTRY_LOCAL_INT:
  751                 mptable_parse_local_int(intr);
  752                 break;
  753         }
  754 }
  755         
  756 /*
  757  * Configure the interrupt pins
  758  */
  759 static void
  760 mptable_parse_ints(void)
  761 {
  762 
  763         /* Is this a pre-defined config? */
  764         if (mpfps->config_type != 0) {
  765                 /* Configure LINT pins. */
  766                 lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT0, APIC_LVT_DM_EXTINT);
  767                 lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI);
  768 
  769                 /* Configure I/O APIC pins. */
  770                 if (mpfps->config_type != 7)
  771                         ioapic_set_extint(ioapics[0], 0);
  772                 else
  773                         ioapic_disable_pin(ioapics[0], 0);
  774                 if (mpfps->config_type != 2)
  775                         ioapic_remap_vector(ioapics[0], 2, 0);
  776                 else
  777                         ioapic_disable_pin(ioapics[0], 2);
  778                 if (mpfps->config_type == 2)
  779                         ioapic_disable_pin(ioapics[0], 13);
  780         } else
  781                 mptable_walk_table(mptable_parse_ints_handler, NULL);
  782 }
  783 
  784 #ifdef MPTABLE_FORCE_HTT
  785 /*
  786  * Perform a hyperthreading "fix-up" to enumerate any logical CPU's
  787  * that aren't already listed in the table.
  788  *
  789  * XXX: We assume that all of the physical CPUs in the
  790  * system have the same number of logical CPUs.
  791  *
  792  * XXX: We assume that APIC ID's are allocated such that
  793  * the APIC ID's for a physical processor are aligned
  794  * with the number of logical CPU's in the processor.
  795  */
  796 static void
  797 mptable_hyperthread_fixup(u_int id_mask)
  798 {
  799         u_int i, id, logical_cpus;
  800 
  801         /* Nothing to do if there is no HTT support. */
  802         if ((cpu_feature & CPUID_HTT) == 0)
  803                 return;
  804         logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
  805         if (logical_cpus <= 1)
  806                 return;
  807 
  808         /*
  809          * For each APIC ID of a CPU that is set in the mask,
  810          * scan the other candidate APIC ID's for this
  811          * physical processor.  If any of those ID's are
  812          * already in the table, then kill the fixup.
  813          */
  814         for (id = 0; id <= MAXCPU; id++) {
  815                 if ((id_mask & 1 << id) == 0)
  816                         continue;
  817                 /* First, make sure we are on a logical_cpus boundary. */
  818                 if (id % logical_cpus != 0)
  819                         return;
  820                 for (i = id + 1; i < id + logical_cpus; i++)
  821                         if ((id_mask & 1 << i) != 0)
  822                                 return;
  823         }
  824 
  825         /*
  826          * Ok, the ID's checked out, so perform the fixup by
  827          * adding the logical CPUs.
  828          */
  829         while ((id = ffs(id_mask)) != 0) {
  830                 id--;
  831                 for (i = id + 1; i < id + logical_cpus; i++) {
  832                         if (bootverbose)
  833                                 printf(
  834                         "MPTable: Adding logical CPU %d from main CPU %d\n",
  835                                     i, id);
  836                         lapic_create(i, 0);
  837                 }
  838                 id_mask &= ~(1 << id);
  839         }
  840 }
  841 #endif /* MPTABLE_FORCE_HTT */
  842 
  843 /*
  844  * Support code for routing PCI interrupts using the MP Table.
  845  */
  846 static void
  847 mptable_pci_setup(void)
  848 {
  849         int i;
  850 
  851         /*
  852          * Find the first pci bus and call it 0.  Panic if pci0 is not
  853          * bus zero and there are multiple PCI busses.
  854          */
  855         for (i = 0; i <= mptable_maxbusid; i++)
  856                 if (busses[i].bus_type == PCI) {
  857                         if (pci0 == -1)
  858                                 pci0 = i;
  859                         else if (pci0 != 0)
  860                                 panic(
  861                 "MPTable contains multiple PCI busses but no PCI bus 0");
  862                 }
  863 }
  864 
  865 static void
  866 mptable_pci_probe_table_handler(u_char *entry, void *arg)
  867 {
  868         struct pci_probe_table_args *args;
  869         int_entry_ptr intr;
  870 
  871         if (*entry != MPCT_ENTRY_INT)
  872                 return;
  873         intr = (int_entry_ptr)entry;
  874         args = (struct pci_probe_table_args *)arg;
  875         KASSERT(args->bus <= mptable_maxbusid,
  876             ("bus %d is too big", args->bus));
  877         KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus"));
  878         if (intr->src_bus_id == args->bus)
  879                 args->found = 1;
  880 }
  881 
  882 int
  883 mptable_pci_probe_table(int bus)
  884 {
  885         struct pci_probe_table_args args;
  886 
  887         if (bus < 0)
  888                 return (EINVAL);
  889         if (pci0 == -1 || pci0 + bus > mptable_maxbusid)
  890                 return (ENXIO);
  891         if (busses[pci0 + bus].bus_type != PCI)
  892                 return (ENXIO);
  893         args.bus = pci0 + bus;
  894         args.found = 0;
  895         mptable_walk_table(mptable_pci_probe_table_handler, &args);
  896         if (args.found == 0)
  897                 return (ENXIO);
  898         return (0);
  899 }
  900 
  901 static void
  902 mptable_pci_route_interrupt_handler(u_char *entry, void *arg)
  903 {
  904         struct pci_route_interrupt_args *args;
  905         int_entry_ptr intr;
  906         int vector;
  907 
  908         if (*entry != MPCT_ENTRY_INT)
  909                 return;
  910         intr = (int_entry_ptr)entry;
  911         args = (struct pci_route_interrupt_args *)arg;
  912         if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq)
  913                 return;
  914 
  915         /* Make sure the APIC maps to a known APIC. */
  916         KASSERT(ioapics[intr->dst_apic_id] != NULL,
  917             ("No I/O APIC %d to route interrupt to", intr->dst_apic_id));
  918 
  919         /*
  920          * Look up the vector for this APIC / pin combination.  If we
  921          * have previously matched an entry for this PCI IRQ but it
  922          * has the same vector as this entry, just return.  Otherwise,
  923          * we use the vector for this APIC / pin combination.
  924          */
  925         vector = ioapic_get_vector(ioapics[intr->dst_apic_id],
  926             intr->dst_apic_int);
  927         if (args->vector == vector)
  928                 return;
  929         KASSERT(args->vector == -1,
  930             ("Multiple entries for PCI IRQ %d", args->vector));
  931         args->vector = vector;
  932 }
  933 
  934 int
  935 mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
  936 {
  937         struct pci_route_interrupt_args args;
  938         int slot;
  939 
  940         /* Like ACPI, pin numbers are 0-3, not 1-4. */
  941         pin--;
  942         KASSERT(pci0 != -1, ("do not know how to route PCI interrupts"));
  943         args.bus = pci_get_bus(dev) + pci0;
  944         slot = pci_get_slot(dev);
  945 
  946         /*
  947          * PCI interrupt entries in the MP Table encode both the slot and
  948          * pin into the IRQ with the pin being the two least significant
  949          * bits, the slot being the next five bits, and the most significant
  950          * bit being reserved.
  951          */
  952         args.irq = slot << 2 | pin;
  953         args.vector = -1;
  954         mptable_walk_table(mptable_pci_route_interrupt_handler, &args);
  955         if (args.vector < 0) {
  956                 device_printf(pcib, "unable to route slot %d INT%c\n", slot,
  957                     'A' + pin);
  958                 return (PCI_INVALID_IRQ);
  959         }
  960         device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 'A' + pin,
  961             args.vector);
  962         return (args.vector);
  963 }

Cache object: d8bc22b3e0996a4001a497283c3083db


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