x86: misc MP/ACPI fixes
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 27 Mar 2014 19:47:25 +0000 (12:47 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 29 Mar 2014 01:17:05 +0000 (18:17 -0700)
Needed more LVTs on some hardware, needed to scan all xioapics (the
array can be sparse), and when we don't have an IOAPIC, we need to treat
IPIs like the LAPIC.

Conflicts:
kern/arch/x86/ioapic.c

kern/arch/x86/apic.h
kern/arch/x86/ioapic.c
kern/arch/x86/mp.c

index 6fdd924..d1c7eb0 100644 (file)
@@ -267,7 +267,7 @@ struct ioapic {
 struct lapic {
        int machno;                                     /* similar to os_coreid, unused */
 
-       uint32_t lvt[6];
+       uint32_t lvt[8];
        int nlvt;
        int ver;
 };
index 85fd392..fda74f1 100644 (file)
@@ -70,7 +70,10 @@ int pcimsimask(struct pci_device *p, int mask);
 static bool ioapic_exists(void)
 {
        /* not foolproof, if we called this before parsing */
-       return xioapic[0].useable ? TRUE : FALSE;
+       for (int i = 0; i < Napic; i++)
+               if (xioapic[i].useable)
+                       return TRUE;
+       return FALSE;
 }
 
 static void rtblget(struct apic *apic, int sel, uint32_t * hi, uint32_t * lo)
@@ -150,12 +153,14 @@ void ioapicintrinit(int busno, int ioapicno, int intin, int devno, int lo)
                rdt->lo = lo;
                rdt->hi = 0;
        } else {
-               if (lo != rdt->lo) {
+               /* Polarity/trigger check.  Stored lo also has the vector in 0xff */
+               if (lo != (rdt->lo & ~0xff)) {
                        printk("multiple irq botch bus %d %d/%d/%d lo %d vs %d\n",
                                   busno, ioapicno, intin, devno, lo, rdt->lo);
                        return;
                }
        }
+       /* TODO: this shit is racy.  (refcnt, linked list addition) */
        rdt->ref++;
        rbus = kzmalloc(sizeof *rbus, 0);
        rbus->rdt = rdt;
@@ -374,6 +379,7 @@ int nextvec(void)
 
        return vecno;
 }
+
 static struct pci_device *pcimatchtbdf(int tbdf)
 {
        /* don't we have macros for this somewhere? */
@@ -391,6 +397,7 @@ static struct pci_device *pcimatchtbdf(int tbdf)
        }
        return NULL;
 }
+
 static int msimask(struct vkey *v, int mask)
 {
        int pcimsimask(struct pci_device *p, int mask);
@@ -537,19 +544,25 @@ int bus_irq_setup(struct irq_handler *irq_h)
 {
        struct Rbus *rbus;
        struct Rdt *rdt;
-       int busno = 0, devno, vecno;
+       int busno, devno, vecno;
        struct pci_device pcidev;
        struct pci_device *msidev;
 
-       if (!ioapic_exists() && (BUSTYPE(irq_h->tbdf) != BusLAPIC)) {
-               irq_h->check_spurious = pic_check_spurious;
-               irq_h->eoi = pic_send_eoi;
-               irq_h->mask = pic_mask_irq;
-               irq_h->unmask = pic_unmask_irq;
-               irq_h->route_irq = 0;
-               irq_h->type = "pic";
-               /* PIC devices have vector = irq + 32 */
-               return irq_h->dev_irq + IdtPIC;
+       if (!ioapic_exists()) {
+               switch (BUSTYPE(irq_h->tbdf)) {
+                       case BusLAPIC:
+                       case BusIPI:
+                               break;
+                       default:
+                               irq_h->check_spurious = pic_check_spurious;
+                               irq_h->eoi = pic_send_eoi;
+                               irq_h->mask = pic_mask_irq;
+                               irq_h->unmask = pic_unmask_irq;
+                               irq_h->route_irq = 0;
+                               irq_h->type = "pic";
+                               /* PIC devices have vector = irq + 32 */
+                               return irq_h->dev_irq + IdtPIC;
+               }
        }
        switch (BUSTYPE(irq_h->tbdf)) {
                case BusLAPIC:
@@ -585,19 +598,26 @@ int bus_irq_setup(struct irq_handler *irq_h)
                case BusPCI:
                        /* TODO: we'll assume it's there.  (fix when adding MSI) */
 
+                       /* temp disable MSI til we get ACPI and such sorted */
+                       #if 0
                        if ((msidev = pcimatchtbdf(irq_h->tbdf)) == NULL) {
                                printk("no PCI dev for tbdf %p", irq_h->tbdf);
                                if ((vecno = intrenablemsi(irq_h, msidev)) != -1)
                                        return vecno;
                                disablemsi(irq_h, msidev);
                        }
+                       #endif
                        busno = BUSBNO(irq_h->tbdf);
                        explode_tbdf(irq_h->tbdf);
                        devno = pcidev_read8(&pcidev, PciINTP);
 
+                       /* this might not be a big deal - some PCI devices have no INTP.  if
+                        * so, change our devno - 1 below. */
                        if (devno == 0)
                                panic("no INTP for tbdf %p", irq_h->tbdf);
-                       /* remember, devno is the device shifted with irq pin in bits 0-1 */
+                       /* remember, devno is the device shifted with irq pin in bits 0-1.
+                        * we subtract 1, since the PCI intp maps 1 -> INTA, 2 -> INTB, etc,
+                        * and the MP spec uses 0 -> INTA, 1 -> INTB, etc. */
                        devno = BUSDNO(irq_h->tbdf) << 2 | (devno - 1);
                        break;
                default:
index 6961c29..dd8e0e5 100644 (file)
@@ -233,12 +233,12 @@ static int mpparse(PCMP * pcmp, int maxcores)
                        case 1: /* bus */
                                printd("mpparse: bus: %d type %6.6s\n", p[1], (char *)p + 2);
                                if (p[1] >= Nbus) {
-                                       printd("mpparse: bus %d out of range\n", p[1]);
+                                       printk("mpparse: bus %d out of range\n", p[1]);
                                        p += 8;
                                        break;
                                }
                                if (mpbus[p[1]] != NULL) {
-                                       printd("mpparse: bus %d already allocated\n", p[1]);
+                                       printk("mpparse: bus %d already allocated\n", p[1]);
                                        p += 8;
                                        break;
                                }
@@ -247,7 +247,7 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                                continue;
                                        if (memcmp(p + 2, "ISA   ", 6) == 0) {
                                                if (mpisabusno != -1) {
-                                                       printd("mpparse: bus %d already have ISA bus %d\n",
+                                                       printk("mpparse: bus %d already have ISA bus %d\n",
                                                                   p[1], mpisabusno);
                                                        continue;
                                                }
@@ -257,8 +257,8 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                        break;
                                }
                                if (mpbus[p[1]] == NULL)
-                                       printd("mpparse: bus %d type %6.6s unknown\n",
-                                                  p[1], (char *unused_char_p_t)p + 2);
+                                       printk("mpparse: bus %d type %6.6s unknown\n",
+                                                  p[1], (char *)p + 2);
 
                                p += 8;
                                break;
@@ -287,11 +287,13 @@ static int mpparse(PCMP * pcmp, int maxcores)
                                        break;
                                }
                                if ((lo = mpmkintr(p)) == 0) {
+                                       if (MP_VERBOSE_DEBUG)
+                                               mpintrprint("iointr skipped", p);
                                        p += 8;
                                        break;
                                }
                                if (MP_VERBOSE_DEBUG)
-                                       mpintrprint(NULL, p);
+                                       mpintrprint("iointr", p);
 
                                /*
                                 * Always present the device number in the style