More set up for using ioapics
authorRonald G. Minnich <rminnich@google.com>
Mon, 3 Mar 2014 22:25:35 +0000 (14:25 -0800)
committerRonald G. Minnich <rminnich@google.com>
Mon, 3 Mar 2014 22:25:35 +0000 (14:25 -0800)
Everything *seems* to be getting done but interrupts still don't happen.
Note we had to change register_dev_interrupt to take a u32; the ioapic
requires it.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/arch/x86/init.c
kern/arch/x86/io.h
kern/arch/x86/ioapic.c
kern/arch/x86/pci.h
kern/arch/x86/trap.c
kern/drivers/dev/acpi.c
kern/drivers/dev/ether.c
kern/include/trap.h

index d7b6b43..ed41d43 100644 (file)
@@ -58,7 +58,7 @@ static void cons_irq_init(void)
        struct cons_dev *i;
        /* Register interrupt handlers for all console devices */
        SLIST_FOREACH(i, &cdev_list, next)
-               register_dev_irq(i->irq, irq_console, i);
+               register_dev_irq(i->irq, irq_console, i, -1);
 }
 
 void arch_init()
index 4ec4cec..38f70eb 100644 (file)
@@ -78,7 +78,7 @@ typedef struct Vctl {
        int     isintr;                 /* interrupt or fault/trap */
 
        struct Vkey;                            /* source-specific key; tbdf for pci */
-       //void  (*f)(Ureg*, void*);     /* handler to call */
+       void    (*f)(void*, void*);     /* handler to call */
        void*   a;                      /* argument to call it with */
        char    name[KNAMELEN];         /* of driver */
        char    *type;
index 553a77d..2fb4b56 100644 (file)
@@ -60,7 +60,8 @@ static spinlock_t idtnolock;
 static int idtno = IdtIOAPIC;
 
 struct apic    xioapic[Napic];
-
+int apiceoi(int);
+int apicisr(int);
 static void
 rtblget(struct apic* apic, int sel, uint32_t* hi, uint32_t* lo)
 {
@@ -128,7 +129,7 @@ ioapicintrinit(int busno, int apicno, int intin, int devno, uint32_t lo)
        }else{
                if(lo != rdt->lo){
                        printd("mutiple irq botch bus %d %d/%d/%d lo %d vs %d\n",
-                               busno, apicno, intin, devno, lo, rdt->lo);
+                              busno, apicno, intin, devno, lo, rdt->lo);
                        return;
                }
                printk("dup rdt %d %d %d %d %.8ux\n", busno, apicno, intin, devno, lo);
@@ -156,16 +157,16 @@ ioapic_route_irq(int irq, int apicno)
        struct Apicst *st;
        uint32_t lo;
        int pol, edge_level;
-
+       printk("%s(%d,%d);\n", __func__, irq, apicno);
        /* find it. */
-       for(st = apics->st; st != NULL; st = st->next)
-               switch(st->type){
-               default: 
-                       continue;
-               case ASintovr:
+       for(st = apics->st; st != NULL; st = st->next){
+               printk("Check %d, ", st->type);
+               if (st->type == ASintovr){
+                       printk("irq of st is %d\n", st->intovr.irq);
                        if (st->intovr.irq == irq)
                                break;
                }
+       }
        if (! st) {
                printk("IRQ %d not found in MADT\n", irq);
                return -1;
@@ -241,7 +242,7 @@ ioapicdump(char *start, char *end)
                if(!apic->useable || apic->addr == 0)
                        continue;
                start = seprintf(start, end, "ioapic %d addr %#p nrdt %d ibase %d\n",
-                       i, apic->addr, apic->nrdt, apic->ibase);
+                                i, apic->addr, apic->nrdt, apic->ibase);
                for(n = 0; n < apic->nrdt; n++){
                        spin_lock(&apic->lock);
                        rtblget(apic, n, &hi, &lo);
@@ -256,9 +257,9 @@ ioapicdump(char *start, char *end)
                for(; rbus != NULL; rbus = rbus->next){
                        rdt = rbus->rdt;
                        start = seprintf(start, end,
-                               " apic %ld devno %#p (%d %d) intin %d lo %#p ref %d\n",
-                               rdt->apic-xioapic, rbus->devno, rbus->devno>>2,
-                               rbus->devno & 0x03, rdt->intin, rdt->lo, rdt->ref);
+                                        " apic %ld devno %#p (%d %d) intin %d lo %#p ref %d\n",
+                                        rdt->apic-xioapic, rbus->devno, rbus->devno>>2,
+                                        rbus->devno & 0x03, rdt->intin, rdt->lo, rdt->ref);
                }
        }
        return start;
@@ -282,7 +283,7 @@ ioapiconline(void)
 }
 
 static int dfpolicy = 0;
-#if 0
+
 static void
 ioapicintrdd(uint32_t* hi, uint32_t* lo)
 {
@@ -308,7 +309,8 @@ ioapicintrdd(uint32_t* hi, uint32_t* lo)
         */
        switch(dfpolicy){
        default:                                /* noise core 0 */
-               *hi = sys->machptr[0]->apicno<<24;
+#warning "sys->machptr[0]->apicno --- what is this in Akaros?"
+               *hi = 0; //sys->machptr[0]->apicno<<24;
                break;
        case 1:                                 /* round-robin */
                /*
@@ -318,18 +320,22 @@ ioapicintrdd(uint32_t* hi, uint32_t* lo)
                 * thread in a core. But, as usual, Intel make that an onerous
                 * task.
                 */
-               spin_lock(&(&dflock)->lock);
+               spin_lock(&dflock);
                for(;;){
+#if 0
                        i = df++;
                        if(df >= sys->nmach+1)
                                df = 0;
                        if(sys->machptr[i] == NULL || !sys->machptr[i]->online)
                                continue;
                        i = sys->machptr[i]->apicno;
+#endif
+#warning "always picking acpino 0"
+                       i = 0;
                        if(xlapic[i].useable && xlapic[i].addr == 0)
                                break;
                }
-               spin_unlock(&dflock->lock);
+               spin_unlock(&dflock);
 
                *hi = i<<24;
                break;
@@ -342,29 +348,36 @@ nextvec(void)
 {
        unsigned int vecno;
 
-       spin_lock(&idtnolock->lock);
+       spin_lock(&idtnolock);
        vecno = idtno;
        idtno = (idtno+8) % IdtMAX;
        if(idtno < IdtIOAPIC)
                idtno += IdtIOAPIC;
-       spin_unlock(&idtnolock->lock);
+       spin_unlock(&idtnolock);
 
        return vecno;
 }
 
+#warning "no msi mask yet"
 static int
-msimask(Vkey *v, int mask)
+msimask(struct Vkey *v, int mask)
 {
+#if 0
        Pcidev *p;
-
+       
        p = pcimatchtbdf(v->tbdf);
        if(p == NULL)
                return -1;
        return pcimsimask(p, mask);
+#else
+       return -1;
+#endif
 }
 
+#warning "No msi yet"
+#if 0
 static int
-intrenablemsi(Vctl* v, Pcidev *p)
+intrenablemsi(struct vctl* v, Pcidev *p)
 {
        unsigned int vno, lo, hi;
        uint64_t msivec;
@@ -389,7 +402,9 @@ intrenablemsi(Vctl* v, Pcidev *p)
        printk("msiirq: %T: enabling %.16llux %s irq %d vno %d\n", p->tbdf, msivec, v->name, v->irq, vno);
        return vno;
 }
-
+#endif
+#warning "no disable msi yet"
+#if 0
 int
 disablemsi(Vctl*, Pcidev *p)
 {
@@ -397,20 +412,21 @@ disablemsi(Vctl*, Pcidev *p)
                return -1;
        return pcimsimask(p, 1);
 }
-
+#endif
 int
 ioapicintrenable(Vctl* v)
 {
        struct Rbus *rbus;
        struct Rdt *rdt;
        uint32_t hi, lo;
-       int busno, devno, vecno;
+       int busno = 0, devno, vecno;
 
-       /*
       * Bridge between old and unspecified new scheme,
       * the work in progress...
       */
+/*
+ * Bridge between old and unspecified new scheme,
+ * the work in progress...
+ */
        if(v->tbdf == BUSUNKNOWN){
+
                if(v->irq >= IrqLINT0 && v->irq <= MaxIrqLAPIC){
                        if(v->irq != IrqSPURIOUS)
                                v->isr = apiceoi;
@@ -423,11 +439,14 @@ ioapicintrenable(Vctl* v)
                         * Make a busno and devno using the
                         * ISA bus number and the irq.
                         */
+#if 0
                        extern int mpisabusno;
-
+                       
                        if(mpisabusno == -1)
                                panic("no ISA bus allocated");
                        busno = mpisabusno;
+#endif
+                       busno = 0;
                        devno = v->irq<<2;
                }
        }
@@ -436,25 +455,35 @@ ioapicintrenable(Vctl* v)
                 * PCI.
                 * Make a devno from BUSDNO(tbdf) and pcidev->intp.
                 */
+               /* we'll assume it's there. */
+#if 0
                Pcidev *pcidev;
-
+               
                busno = BUSBNO(v->tbdf);
                if((pcidev = pcimatchtbdf(v->tbdf)) == NULL)
                        panic("no PCI dev for tbdf %#8.8ux", v->tbdf);
                if((vecno = intrenablemsi(v, pcidev)) != -1)
                        return vecno;
                disablemsi(v, pcidev);
-               if((devno = pcicfgr8(pcidev, PciINTP)) == 0)
+#endif
+
+               struct pci_device pcidev;
+               
+               explode_tbdf(v->tbdf);
+               devno = pcidev_read8(&pcidev, PciINTP);
+
+               if(devno == 0)
                        panic("no INTP for tbdf %#8.8ux", v->tbdf);
                devno = BUSDNO(v->tbdf)<<2|(devno-1);
-               printk("ioapicintrenable: tbdf %#8.8ux busno %d devno %d\n",
-                       v->tbdf, busno, devno);
+               printk("ioapicintrenable: tbdf %#8.8p busno %d devno %d\n",
+                      v->tbdf, busno, devno);
        }
        else{
-               SET(busno, devno);
-               panic("unknown tbdf %#8.8ux", v->tbdf);
+               //SET(busno, devno);
+               busno = devno = 0;
+               panic("unknown tbdf %#8.8px", v->tbdf);
        }
-
+       
        rdt = NULL;
        for(rbus = rdtbus[busno]; rbus != NULL; rbus = rbus->next)
                if(rbus->devno == devno){
@@ -463,15 +492,16 @@ ioapicintrenable(Vctl* v)
                }
        if(rdt == NULL){
                extern int mpisabusno;
-
+               
                /*
                 * First crack in the smooth exterior of the new code:
-                * some BIOS make an MPS table where the PCI devices are
-                * just defaulted to ISA.
-                * Rewrite this to be cleaner.
-                */
+                * some BIOS make an MPS table where the PCI devices
+                * are just defaulted to ISA.  Rewrite this to be
+                * cleaner.
+                * no MPS table in akaros.
                if((busno = mpisabusno) == -1)
                        return -1;
+                */
                devno = v->irq<<2;
                for(rbus = rdtbus[busno]; rbus != NULL; rbus = rbus->next)
                        if(rbus->devno == devno){
@@ -479,11 +509,11 @@ ioapicintrenable(Vctl* v)
                                break;
                        }
                printk("isa: tbdf %#8.8ux busno %d devno %d %#p\n",
-                       v->tbdf, busno, devno, rdt);
+                      v->tbdf, busno, devno, rdt);
        }
        if(rdt == NULL)
                return -1;
-
+       
        /*
         * Second crack:
         * what to do about devices that intrenable/intrdisable frequently?
@@ -513,7 +543,7 @@ ioapicintrenable(Vctl* v)
        spin_unlock(&rdt->apic->lock);
 
        printk("busno %d devno %d hi %#8.8ux lo %#8.8ux vecno %d\n",
-               busno, devno, hi, lo, vecno);
+              busno, devno, hi, lo, vecno);
        v->isr = apicisr;
        v->eoi = apiceoi;
        v->vno = vecno;
@@ -543,13 +573,68 @@ ioapicintrdisable(int vecno)
                panic("ioapicintrdisable: vecno %d has no rdt", vecno);
                return -1;
        }
-
+       
        spin_lock(&rdt->apic->lock);
        rdt->enabled--;
        if(rdt->enabled == 0)
                rtblput(rdt->apic, rdt->intin, 0, rdt->lo);
        spin_unlock(&rdt->apic->lock);
-
+       
        return 0;
 }
+
+spinlock_t vctllock;
+
+void*
+intrenable(int irq, void (*f)(void*, void*), void* a, int tbdf)
+{
+       int vno;
+       Vctl *v;
+       extern int ioapicintrenable(Vctl*);
+
+       if(f == NULL){
+               printk("intrenable: nil handler for %d, tbdf %p\n",
+                      irq, tbdf);
+               return NULL;
+       }
+
+       v = kzmalloc(sizeof(Vctl), KMALLOC_WAIT);
+       v->isintr = 1;
+       v->irq = irq;
+       v->tbdf = tbdf;
+       v->f = f;
+       v->a = a;
+
+       //spilock(&vctllock);
+       vno = ioapicintrenable(v);
+       if(vno == -1){
+               //iunlock(&vctllock);
+               printk("intrenable: couldn't enable irq %d, tbdf %#ux for %s\n",
+                       irq, tbdf, v->name);
+               kfree(v);
+               return NULL;
+       }
+#if 0
+       if(vctl[vno]){
+               if(vctl[v->vno]->isr != v->isr || vctl[v->vno]->eoi != v->eoi)
+                       panic("intrenable: handler: %s %s %#p %#p %#p %#p",
+                               vctl[v->vno]->name, v->name,
+                               vctl[v->vno]->isr, v->isr, vctl[v->vno]->eoi, v->eoi);
+       }
+
+       v->vno = vno;
+       v->next = vctl[vno];
+       vctl[vno] = v;
 #endif
+       //iunlock(&vctllock);
+
+       if(v->mask)
+               v->mask(v, 0);
+
+       /*
+        * Return the assigned vector so intrdisable can find
+        * the handler; the IRQ is useless in the wonderful world
+        * of the IOAPIC.
+        */
+       return v;
+}
index 3432dc6..ee8096e 100644 (file)
@@ -392,4 +392,9 @@ uint32_t pci_getiobar32(uint32_t bar);
 /* Other common PCI functions */
 void pci_set_bus_master(struct pci_device *pcidev);
 
+/* this is quite the Hacke */
+#define explode_tbdf(tbdf) {pcidev.bus = tbdf >> 16;\
+               pcidev.dev = (tbdf>>11)&0x1f;\
+               pcidev.func = (tbdf>>8)&3;}
+
 #endif /* ROS_ARCH_PCI_H */
index 91829bc..2aa63be 100644 (file)
@@ -582,7 +582,10 @@ void unregister_raw_irq(unsigned int vector, isr_t handler, void *data)
        printk("Unregistering not supported\n");
 }
 
-int register_dev_irq(int irq, isr_t handler, void *irq_arg)
+/* The devno is arbitrary data. Normally, however, it will be a
+ * PCI type-bus-dev.func. It is required for ioapics.
+ */
+int register_dev_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf)
 {
        register_raw_irq(KERNEL_IRQ_OFFSET + irq, handler, irq_arg);
 
@@ -592,8 +595,8 @@ int register_dev_irq(int irq, isr_t handler, void *irq_arg)
        /* TODO: this should be for any IOAPIC EOI, not just MPTABLES */
        /* Just sending to core 0 for now */
 #warning "NOT routing the ioapic irq"
-       printk("NOT ROUTING irq %d to core 0!\n", irq);
-       ioapic_route_irq(irq, 0);
+       printk("ROUTING irq %d to core 0!\n", irq);
+       intrenable(irq, handler, irq_arg, tbdf);
 #else
        pic_unmask_irq(irq);
        unmask_lapic_lvt(LAPIC_LVT_LINT0);
index 39edf82..18d978e 100644 (file)
@@ -214,11 +214,6 @@ ioset32(uintptr_t p, uint32_t v, void*unused)
        outl(p, v);
 }
 
-#define explode_tbdf(tbdf) {pcidev.bus = tbdf >> 16;\
-               pcidev.dev = (tbdf>>11)&0x1f;\
-               pcidev.func = (tbdf>>8)&3;}
-
-
 static uint8_t
 cfgget8(uintptr_t p, void* r)
 {
index 2dfa58d..ff00f7e 100644 (file)
@@ -26,7 +26,7 @@
 #include <pmap.h>
 #include <smp.h>
 #include <ip.h>
-
+#include <arch/io.h>
 enum {
        Type8021Q = 0x8100,                     /* value of type field for 802.1[pQ] tags */
 };
@@ -682,7 +682,7 @@ static void etherreset(void)
                        snprintf(name, sizeof(name), "ether%d", ctlrno);
 
                        if (ether->interrupt != NULL)
-                               register_dev_irq(ether->irq, ether->interrupt, ether);
+                               register_dev_irq(ether->irq, ether->interrupt, ether, BUSUNKNOWN);
 
                        i = snprintf(buf, sizeof(buf),
                                                 "#l%d: %s: %dMbps port 0x%x irq %u", ctlrno,
index 0b7b0c7..e814b92 100644 (file)
@@ -20,7 +20,7 @@ struct irq_handler {
 void idt_init(void);
 void register_raw_irq(unsigned int vector, isr_t handler, void *data);
 void unregister_raw_irq(unsigned int vector, isr_t handler, void *data);
-int register_dev_irq(int irq, isr_t handler, void *irq_arg);
+int register_dev_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf);
 void print_trapframe(struct hw_trapframe *hw_tf);
 void print_user_ctx(struct user_context *ctx);
 /* Generic per-core timer interrupt handler.  set_percore_timer() will fire the