Browse Source

Try to record both devno and fno when recording interrupts

Signed-off-by: Graham MacDonald <grahamamacdonald@gmail.com>
Graham MacDonald 5 years ago
parent
commit
c8c9d8c0e2

+ 2 - 2
sys/src/9/amd64/apic.h

@@ -20,8 +20,8 @@ typedef	struct	Apic	Apic;
 
 struct Ioapic {
 	Lock l;					/* IOAPIC: register access */
-	uint32_t*	addr;				/* IOAPIC: register base */
-	uintptr_t	paddr;				/* physical address */
+	uint32_t*	addr;			/* IOAPIC: register base */
+	uintptr_t	paddr;			/* physical address */
 	int	nrdt;				/* IOAPIC: size of RDT */
 	int	gsib;				/* IOAPIC: global RDT index */
 };

+ 0 - 1
sys/src/9/amd64/fns.h

@@ -244,7 +244,6 @@ extern void apicsipi(int, uintmem);
 extern void apicnmi(int, int, int);
 
 extern void ioapicinit(int, int, uintmem);
-extern void ioapicintrinit(int, int, int, int, uint32_t);
 extern void ioapiconline(void);
 
 /*

+ 22 - 22
sys/src/9/amd64/io.h

@@ -49,9 +49,9 @@ enum {
 };
 
 enum {
-	IdtPIC		= 32,			/* external i8259 interrupts */
+	IdtPIC		= 32,		/* external i8259 interrupts */
 
-	IdtLINT0	= 48,			/* local APIC interrupts */
+	IdtLINT0	= 48,		/* local APIC interrupts */
 	IdtLINT1	= 49,
 	IdtTIMER	= 50,
 	IdtERROR	= 51,
@@ -62,7 +62,7 @@ enum {
 
 	IdtSYSCALL	= 64,
 
-	IdtIOAPIC	= 65,			/* external APIC interrupts */
+	IdtIOAPIC	= 65,		/* external APIC interrupts */
 
 	IdtMAX		= 255,
 };
@@ -98,25 +98,25 @@ typedef struct ACVctl {
 
 enum {
 	BusCBUS		= 0,	/* Corollary CBUS */
-	BusCBUSII,			/* Corollary CBUS II */
-	BusEISA,			/* Extended ISA */
-	BusFUTURE,			/* IEEE Futurebus */
-	BusINTERN,			/* Internal bus */
-	BusISA,				/* Industry Standard Architecture */
-	BusMBI,				/* Multibus I */
-	BusMBII,			/* Multibus II */
-	BusMCA,				/* Micro Channel Architecture */
-	BusMPI,				/* MPI */
-	BusMPSA,			/* MPSA */
-	BusNUBUS,			/* Apple Macintosh NuBus */
-	BusPCI,				/* Peripheral Component Interconnect */
-	BusPCMCIA,			/* PC Memory Card International Association */
-	BusTC,				/* DEC TurboChannel */
-	BusVL,				/* VESA Local bus */
-	BusVME,				/* VMEbus */
-	BusXPRESS,			/* Express System Bus */
-	BusLAPIC,	/* Local APIC, fake type */
-	BusIPI,	/* IPIs, fake type like the LAPIC */
+	BusCBUSII,		/* Corollary CBUS II */
+	BusEISA,		/* Extended ISA */
+	BusFUTURE,		/* IEEE Futurebus */
+	BusINTERN,		/* Internal bus */
+	BusISA,			/* Industry Standard Architecture */
+	BusMBI,			/* Multibus I */
+	BusMBII,		/* Multibus II */
+	BusMCA,			/* Micro Channel Architecture */
+	BusMPI,			/* MPI */
+	BusMPSA,		/* MPSA */
+	BusNUBUS,		/* Apple Macintosh NuBus */
+	BusPCI,			/* Peripheral Component Interconnect */
+	BusPCMCIA,		/* PC Memory Card International Association */
+	BusTC,			/* DEC TurboChannel */
+	BusVL,			/* VESA Local bus */
+	BusVME,			/* VMEbus */
+	BusXPRESS,		/* Express System Bus */
+	BusLAPIC,		/* Local APIC, fake type */
+	BusIPI,			/* IPIs, fake type like the LAPIC */
 };
 
 #define MKBUS(t,b,d,f)	(((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))

+ 50 - 34
sys/src/9/amd64/ioapic.c

@@ -28,20 +28,24 @@ typedef struct Rdt Rdt;
 extern Atable *apics; 		/* APIC info */
 int mpisabusno = -1;
 
+/* Rbus chains, one for each device bus: each rbus matches a device to an rdt */
 struct Rbus {
 	Rbus	*next;
 	int	devno;
+	int	fno;
 	Rdt	*rdt;
 };
 
+
+/* Each rdt describes an ioapic input pin (intin, from the bus/device) */
 struct Rdt {
-	Apic	*apic;
-	int	intin;
+	Apic		*apic;
+	int		intin;
 	uint32_t	lo;
 	uint32_t	hi;
 
-	int	ref;				/* could map to multiple busses */
-	int	enabled;				/* times enabled */
+	int		ref;			/* could map to multiple busses */
+	int		enabled;		/* times enabled */
 };
 
 enum {						/* IOAPIC registers */
@@ -136,7 +140,7 @@ rtblput(Apic* apic, int sel, uint32_t hi, uint32_t lo)
 	ioapicwrite(apic, sel, lo);
 }
 
-Rdt*
+static Rdt*
 rdtlookup(Apic *apic, int intin)
 {
 	int i;
@@ -150,7 +154,8 @@ rdtlookup(Apic *apic, int intin)
 	return nil;
 }
 
-int compatible(uint32_t new, uint32_t old)
+static int
+compatible(uint32_t new, uint32_t old)
 {
 	uint32_t newtop = new & ~0xff;
 	uint32_t oldtop = old & ~0xff;
@@ -165,8 +170,9 @@ int compatible(uint32_t new, uint32_t old)
 	print("REALLY not the same\n");
 	return 0;
 }
-void
-ioapicintrinit(int busno, int apicno, int intin, int devno, uint32_t lo)
+
+static void
+ioapicintrinit(int busno, int apicno, int intin, int devno, int fno, uint32_t lo)
 {
 	Rbus *rbus;
 	Rdt *rdt;
@@ -196,29 +202,31 @@ ioapicintrinit(int busno, int apicno, int intin, int devno, uint32_t lo)
 	}
 
 	rdt = rdtlookup(apic, intin);
-	if(rdt == nil){
+	if (rdt == nil) {
 		rdt = &rdtarray[nrdtarray++];
 		rdt->apic = apic;
 		rdt->intin = intin;
 		rdt->lo = lo;
-	}else{
-		if(! compatible(lo, rdt->lo)){
+	} else {
+		if (!compatible(lo, rdt->lo)) {
 			print("ioapicintrinit: multiple irq botch bus %d %d/%d/%d lo %d vs %d\n",
 				busno, apicno, intin, devno, lo, rdt->lo);
 			return;
 		}
-		print("dup rdt %d %d %d %d %.8x\n", busno, apicno, intin, devno, lo);
+		print("ioapicintrinit: dup rdt %d %d %d %d %.8x\n", busno, apicno, intin, devno, lo);
 	}
 	rdt->ref++;
 	rbus = malloc(sizeof *rbus);
 	rbus->rdt = rdt;
 	rbus->devno = devno;
+	rbus->fno = fno;
 	rbus->next = rdtbus[busno];
 	rdtbus[busno] = rbus;
 	print("%s: success\n", __func__);
 }
 
-static int acpi_irq2ioapic(int irq)
+static int
+acpi_irq2ioapic(int irq)
 {
 	int ioapic_idx = 0;
 	Apic *apic;
@@ -256,7 +264,8 @@ static int acpi_irq2ioapic(int irq)
  *		like implementing a motherboard driver for each different motherboard,
  *		or some complex auto-detection scheme, or just configure PCI devices to
  *		use MSI instead). */
-static int acpi_make_rdt(Vctl *v, int tbdf, int irq, int busno, int devno)
+static int
+acpi_make_rdt(Vctl *v, int irq, int bustype, int busno, int devno, int fno)
 {
 	Atable *at;
 	Apicst *st, *lst;
@@ -291,14 +300,14 @@ static int acpi_make_rdt(Vctl *v, int tbdf, int irq, int busno, int devno)
 		lo = pol | edge_level;
 		gsi_irq = st->intovr.intr;
 	} else {
-		if (BUSTYPE(tbdf) == BusISA) {
+		if (bustype == BusISA) {
 			lo = IPhigh | TMedge;
 			gsi_irq = irq;
 		} else {
 			/* Need to query ACPI at some point to handle this */
 			print("Non-ISA IRQ %d not found in MADT, aborting\n", irq);
-			print("Bustype: %d\n", BUSTYPE(tbdf));
-			print("todo[%d] b:%d d:%d f:%d\n", todoidx, BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+			print("Bustype: %d\n", bustype);
+			print("todo[%d] b:%d d:%d f:%d\n", todoidx, busno, devno, fno);
 			todo[todoidx].v = *v;
 			todo[todoidx].lo = lo | TMlevel | IPlow | Im;
 			todo[todoidx].valid = 1;
@@ -313,7 +322,7 @@ static int acpi_make_rdt(Vctl *v, int tbdf, int irq, int busno, int devno)
 		return -1;
 	}
 	ioapicintrinit(busno, ioapic_nr, gsi_irq - xioapic[ioapic_nr].Ioapic.gsib,
-	               devno, lo);
+	               devno, fno, lo);
 	return 0;
 }
 
@@ -385,9 +394,9 @@ ioapicdump(void)
 		print("iointr bus %d:\n", i);
 		for(; rbus != nil; rbus = rbus->next){
 			rdt = rbus->rdt;
-			print(" apic %ld devno %#x (%d %d) intin %d lo %#x ref %d\n",
+			print(" apic %ld devno %#x (%d %d) fno %d intin %d lo %#x ref %d\n",
 				rdt->apic-xioapic, rbus->devno, rbus->devno>>2,
-				rbus->devno & 0x03, rdt->intin, rdt->lo, rdt->ref);
+				rbus->devno & 0x03, rbus->fno, rdt->intin, rdt->lo, rdt->ref);
 		}
 	}
 }
@@ -489,7 +498,7 @@ ioapicintrdd(uint32_t* hi, uint32_t* lo)
 	*lo |= Pm|MTf;
 }
 
-int
+static int
 nextvec(void)
 {
 	uint vecno;
@@ -582,7 +591,8 @@ ioapicintrdisable(int vecno)
 }
 
 /* From Akaros, not sure we want this but for now ... */
-static int ioapic_exists(void)
+static int
+ioapic_exists(void)
 {
 	/* not foolproof, if we called this before parsing */
 	for (int i = 0; i < Napic; i++)
@@ -591,12 +601,14 @@ static int ioapic_exists(void)
 	return 0;
 }
 
-Rdt *rbus_get_rdt(int busno, int devno)
+static Rdt *
+rbus_get_rdt(int busno, int devno, int fno)
 {
 	Rbus *rbus;
 	for (rbus = rdtbus[busno]; rbus != nil; rbus = rbus->next) {
-		if (rbus->devno == devno)
+		if (rbus->devno == devno && rbus->fno == fno) {
 			return rbus->rdt;
+		}
 	}
 	return 0;
 }
@@ -617,16 +629,18 @@ Rdt *rbus_get_rdt(int busno, int devno)
  * In plan9, this was ioapicintrenable(), which also unmasked.  We don't have a
  * deinit/disable method that would tear down the route yet.  All the plan9 one
  * did was dec enabled and mask the entry. */
-int bus_irq_setup(Vctl *v)
+int
+bus_irq_setup(Vctl *v)
 {
 	//Rbus *rbus;
 	Rdt *rdt;
-	int busno = -1, devno = -1, vno;
+	int bustype = BUSTYPE(v->Vkey.tbdf);
+	int busno = -1, devno = -1, fno = 0, vno;
 	Pcidev *p;
 
        	if (!ioapic_exists()) {
 		panic("%s: no ioapics?", __func__);
-		switch (BUSTYPE(v->Vkey.tbdf)) {
+		switch (bustype) {
 			//case BusLAPIC:
 			//case BusIPI:
 			//break;
@@ -641,7 +655,7 @@ int bus_irq_setup(Vctl *v)
 			return -1; //irq_h->dev_irq + IdtPIC;
 		}
 	}
-	switch (BUSTYPE(v->Vkey.tbdf)) {
+	switch (bustype) {
 	case BusLAPIC:
 		/* nxm used to set the initial 'isr' method (i think equiv to our
 		 * check_spurious) to apiceoi for non-spurious lapic vectors.  in
@@ -692,19 +706,20 @@ int bus_irq_setup(Vctl *v)
 		 * 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(v->Vkey.tbdf) << 2 | (devno - 1);
+		fno = BUSFNO(v->Vkey.tbdf);
 		break;
 	default:
 		panic("Unknown bus type, TBDF %p", v->Vkey.tbdf);
 	}
 	/* busno and devno are set, regardless of the bustype, enough to find rdt.
 	 * these may differ from the values in tbdf. */
-	rdt = rbus_get_rdt(busno, devno);
+	rdt = rbus_get_rdt(busno, devno, fno);
 	if (!rdt) {
 		/* second chance.  if we didn't find the item the first time, then (if
 		 * it exists at all), it wasn't in the MP tables (or we had no tables).
 		 * So maybe we can figure it out via ACPI. */
-		acpi_make_rdt(v, v->Vkey.tbdf, v->Vkey.irq, busno, devno);
-		rdt = rbus_get_rdt(busno, devno);
+		acpi_make_rdt(v, v->Vkey.irq, bustype, busno, devno, fno);
+		rdt = rbus_get_rdt(busno, devno, fno);
 	}
 	if (!rdt) {
 		print("Unable to build IOAPIC route for irq %d\n", v->Vkey.irq);
@@ -748,7 +763,8 @@ int bus_irq_setup(Vctl *v)
 	return vno;
 }
 
-int acpiirq(uint32_t tbdf, int gsi)
+int
+acpiirq(uint32_t tbdf, int gsi)
 {
 	Proc *up = externup();
 	int ioapic_nr;
@@ -776,7 +792,7 @@ int acpiirq(uint32_t tbdf, int gsi)
 		}
 	}
 
-	print("acpiirq: vinfotodo b:%d d:%d f:%d\n", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+	print("acpiirq: vinfotodo b:%d d:%d f:%d gsi:%d\n", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf), gsi);
 
 	if (vinfotodo == nil)
 		error("Unknown tbdf");
@@ -804,7 +820,7 @@ int acpiirq(uint32_t tbdf, int gsi)
 	}
 	//ioapicdump();
 	ioapicintrinit(busno, ioapic_nr, gsi - xioapic[ioapic_nr].Ioapic.gsib,
-	               devno, vinfotodo->lo);
+	               devno, BUSFNO(tbdf), vinfotodo->lo);
 	//if (DBGFLG)
 		print("ioapicinrinit seems to have worked\n");
 	poperror();

+ 1 - 0
sys/src/9/amd64/main.c

@@ -621,6 +621,7 @@ if (1){	acpiinit(); hi("	acpiinit();\n");}
 	trapinit();
 	printinit();
 	apiconline();
+	ioapiconline();
 	/* Forcing to single core if desired */
 	if(!nosmp) {
 		sipi();

+ 7 - 6
sys/src/9/amd64/mpacpi.c

@@ -16,6 +16,7 @@
 
 extern int mpisabusno;
 
+// Initialise all local and IO APICs
 int mpacpi(int ncleft)
 {
 	char *already;
@@ -58,8 +59,9 @@ int mpacpi(int ncleft)
 				} else if (ncleft != 0) {
 					ncleft--;
 					apicinit(st->lapic.id, mt->lapicpa, bp);
-				} else
+				} else {
 					already = "(off)";
+				}
 
 				print("apic proc %d/%d apicid %d %s\n", np - 1, apic->Lapic.machno,
 					   st->lapic.id, already);
@@ -73,14 +75,13 @@ int mpacpi(int ncleft)
 				apic = xioapic + st->ioapic.id;
 				if (apic->useable) {
 					already = "(mp)";
-					goto pr1;
+				} else {
+					ioapicinit(st->ioapic.id, st->ioapic.ibase, st->ioapic.addr);
 				}
-				ioapicinit(st->ioapic.id, st->ioapic.ibase, st->ioapic.addr);
-pr1:
+
 				apic->Ioapic.gsib = st->ioapic.ibase;
 				print("ioapic %d ", st->ioapic.id);
-				print("addr %p ibase %d %s\n", st->ioapic.addr, st->ioapic.ibase,
-					   already);
+				print("addr %p ibase %d %s\n", st->ioapic.addr, st->ioapic.ibase, already);
 				break;
 		}
 	}

+ 1 - 0
sys/src/9/amd64/trap.c

@@ -54,6 +54,7 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
 {
 	int vno;
 	Vctl *v;
+
 	if(f == nil){
 		print("intrenable: nil handler for %d, tbdf %#x for %s\n",
 			irq, tbdf, name);

+ 0 - 2
sys/src/9/riscv/fns.h

@@ -216,8 +216,6 @@ extern void apicpri(int);
 extern void apicsipi(int, uintmem);
 
 extern void ioapicinit(int, uintmem);
-extern void ioapicintrinit(int, int, int, int, uint32_t);
-extern void ioapiconline(void);
 
 /*
  * archamd64.c