x86: MP table cleanup, multiple IOAPICs
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 13 Mar 2014 04:30:36 +0000 (21:30 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 29 Mar 2014 01:16:11 +0000 (18:16 -0700)
Shuts up the MP table a little, and allows us to handle multiple IOAPICs
without panicing.

kern/arch/x86/ioapic.c
kern/arch/x86/ioapic.h
kern/arch/x86/mp.c
kern/arch/x86/mpacpi.c
kern/arch/x86/trap.c
kern/arch/x86/trap.h
kern/include/acpi.h

index 220c825..6487ca2 100644 (file)
@@ -55,6 +55,7 @@ enum {                                                        /* IOAPIC registers */
 static struct Rdt rdtarray[Nrdt];
 static int nrdtarray;
 static struct Rbus *rdtbus[Nbus];
+/* reverse mapping of IDT vector to the RDT/IOAPIC entry triggering vector */
 static struct Rdt *rdtvecno[IdtMAX + 1];
 
 static spinlock_t idtnolock;
@@ -210,7 +211,7 @@ void ioapicinit(int id, int ibase, uintptr_t pa)
        struct apic *apic;
        static int base;
 
-       assert(pa == IOAPIC_PBASE);
+       assert((IOAPIC_PBASE <= pa) && (pa + PGSIZE <= IOAPIC_PBASE + APIC_SIZE));
        /*
         * Mark the IOAPIC useable if it has a good ID
         * and the registers can be mapped.
@@ -219,7 +220,7 @@ void ioapicinit(int id, int ibase, uintptr_t pa)
                return;
 
        apic = &xioapic[id];
-       apic->addr = IOAPIC_BASE;
+       apic->addr = IOAPIC_BASE + (pa - IOAPIC_PBASE);
        if (apic->useable)
                return;
        apic->useable = 1;
@@ -446,7 +447,6 @@ int bus_irq_enable(struct irq_handler *irq_h)
        struct Rdt *rdt;
        uint32_t hi, lo;
        int busno = 0, devno, vecno;
-       extern int mpisabusno;  // XXX
        struct pci_device pcidev;
 
        if (!ioapic_exists() && (BUSTYPE(irq_h->tbdf) != BusLAPIC)) {
index 4fb84a5..0d5bea6 100644 (file)
@@ -54,6 +54,8 @@ enum {
        IOAPIC_PBASE    = 0xfec00000, /* default *physical* address */
 };
 
+extern int mpisabusno;
+
 void ioapicinit(int id, int ibase, uintptr_t pa);
 void ioapicrdtr(struct apic*, int unused_int, int*, int*);
 void ioapicrdtw(struct apic*, int unused_int, int, int);
index 76d3a77..71f6b34 100644 (file)
@@ -1,3 +1,10 @@
+/* This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file. */
+
 #include <vfs.h>
 #include <kfs.h>
 #include <slab.h>
@@ -54,6 +61,7 @@ static Mpbus mpbusdef[] = {
 
 static Mpbus *mpbus[Nbus];
 int mpisabusno = -1;
+#define MP_VERBOSE_DEBUG 0
 
 static void mpintrprint(char *s, uint8_t * p)
 {
@@ -199,7 +207,7 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                for (i = 0; p < e; i++) {
                                        if (i && ((i & 0x0f) == 0))
                                                printd("\n");
-                                       printd(" %#2.2ux", *p);
+                                       printd(" 0x%#2.2x", *p);
                                        p++;
                                }
                                printd("\n");
@@ -268,8 +276,8 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                 * p[2-3] contains the polarity and trigger mode;
                                 * p[4] is the source bus;
                                 * p[5] is the IRQ on the source bus;
-                                * p[6] is the destination APIC;
-                                * p[7] is the INITIN pin on the destination APIC.
+                                * p[6] is the destination IOAPIC;
+                                * p[7] is the INITIN pin on the destination IOAPIC.
                                 */
                                if (p[6] == 0xff) {
                                        mpintrprint("routed to all IOAPICs", p);
@@ -280,7 +288,7 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                        p += 8;
                                        break;
                                }
-                               if (2)
+                               if (MP_VERBOSE_DEBUG)
                                        mpintrprint(NULL, p);
 
                                /*
@@ -289,6 +297,9 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                 * bus the IRQ is the device number but unencoded.
                                 * May need to handle other buses here in the future
                                 * (but unlikely).
+                                *
+                                * For PCI devices, this field's lowest two bits are INT#A == 0,
+                                * INT#B == 1, etc.  Bits 2-6 are the PCI device number.
                                 */
                                devno = p[5];
                                if (memcmp(mpbus[p[4]]->type, "PCI   ", 6) != 0)
@@ -307,8 +318,8 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                        p += 8;
                                        break;
                                }
-                               if (2)
-                                       mpintrprint(NULL, p);
+                               if (MP_VERBOSE_DEBUG)
+                                       mpintrprint("LINTR", p);
 
                                /*
                                 * Everything was checked in mpmkintr above.
@@ -407,11 +418,13 @@ int mpsinit(int maxcores)
        PCMP *pcmp;
 
        if ((mp = sigsearch("_MP_")) == NULL) {
-               printd("no mp tables\n");
+               printk("No mp tables found, might have issues!\n");
                return ncleft;
        }
+       /* TODO: if an IMCR exists, we should set it to 1, though i've heard that
+        * ACPI-capable HW doesn't have the IMCR anymore. */
 
-       if (2) {
+       if (MP_VERBOSE_DEBUG) {
                printk("_MP_ @ %#p, addr %p length %ud rev %d",
                           mp, l32get(mp->addr), mp->length, mp->revision);
                for (i = 0; i < sizeof(mp->feature); i++)
@@ -438,7 +451,7 @@ int mpsinit(int maxcores)
                vunmap(pcmp, n);
                return ncleft;
        }
-       if (2) {
+       if (MP_VERBOSE_DEBUG) {
                printk("PCMP @ %#p length %p revision %d\n",
                           pcmp, l16get(pcmp->length), pcmp->revision);
                printk(" %20.20s oaddr %p olength %p\n",
index 7c72840..3e7939c 100644 (file)
@@ -1,3 +1,10 @@
+/* This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file. */
+
 #define DEBUG
 #include <vfs.h>
 #include <kfs.h>
@@ -25,6 +32,14 @@ int mpacpi(int ncleft)
        struct apic *apic;
        struct Apicst *st;
 
+       /* If we don't have an mpisabusno yet, it's because the MP tables failed to
+        * parse.  So we'll just take the last one available.  I think we're
+        * supposed to parse the ACPI shit with the AML to figure out the buses and
+        * find a clear one, but fuck that.  Note this busno is just for our own
+        * RDT/Rbus bookkeeping. */
+       if (mpisabusno == -1)
+               mpisabusno = Nbus - 1;
+
        printk("mpacpi ncleft %d\n", ncleft);
        if (apics == NULL)
                return ncleft;
index 3a0067c..88aac3a 100644 (file)
@@ -169,15 +169,15 @@ void idt_init(void)
        pic_mask_all();
 
 #ifdef CONFIG_ENABLE_MPTABLES
-       int ncleft;
+       int ncleft = MAX_NUM_CPUS;
        int mpsinit(int maxcores);
-
-       ncleft = mpsinit(MAX_NUM_CPUS);
-       /* NEVER printd here ... */
-       printk("mpacpi is %d\n", mpacpi(ncleft));
-
        void ioapiconline(void);
        void apiconline(void);
+
+       ncleft = mpsinit(ncleft);
+       ncleft = mpacpi(ncleft);
+       printk("mpacpi is %d\n", ncleft);
+
        apiconline(); /* TODO: do this this for all cores*/
        ioapiconline();
 #else
index bf29eed..ef58885 100644 (file)
@@ -143,16 +143,6 @@ struct irq_handler {
        char name[IRQ_NAME_LEN];
 };
 
-static bool idt_vec_is_pic(int vec)
-{
-       return (IdtPIC <= vec) && (vec <= MaxIdtPIC);
-}
-
-static bool idt_vec_is_lapic(int vec)
-{
-       return (IdtLAPIC <= vec) && (vec <= MaxIdtLAPIC);
-}
-
 /* The kernel's interrupt descriptor table */
 extern gatedesc_t idt[];
 extern pseudodesc_t idt_pd;
index 92f08de..f336c9d 100644 (file)
@@ -7,6 +7,9 @@
  * in the LICENSE file.
  */
 
+#ifndef ROS_KERN_ACPI_H
+#define ROS_KERN_ACPI_H
+
 enum {
 
        Sdthdrsz = 36,                          /* size of SDT header */
@@ -383,3 +386,6 @@ struct Xsdt {
 extern uintptr_t acpimblocksize(uintptr_t, int *);
 
 int acpiinit(void);
+extern struct Madt *apics;
+
+#endif /* ROS_KERN_ACPI_H */