[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SMP interrupt fixups



re
here we start to apply some magic to some brokem mpbios
implementations. this diff in particular solves two
pravlems with mpbios interrupt tables.
missing pci pin mappings are thus routed thru "fixed"
isa pins (via pci intr router). for rcc osb chipsets
we can also assume isa routing for some specially
wired interrupts irregardless of pci mappings.

functionally equal diff had been in snapshots
for past two weeks but those who have not tried
their SMP machines please do now.

10x
cu

-- 
    paranoic mickey       (my employers have changed but, the name has remained)

Index: i386/mpbios.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/mpbios.c,v
retrieving revision 1.5
diff -u -r1.5 mpbios.c
--- i386/mpbios.c	13 Nov 2005 14:23:26 -0000	1.5
+++ i386/mpbios.c	22 Nov 2005 09:54:29 -0000
@@ -175,7 +175,7 @@
 void	mpbios_cpu(const u_int8_t *, struct device *);
 void	mpbios_bus(const u_int8_t *, struct device *);
 void	mpbios_ioapic(const u_int8_t *, struct device *);
-void	mpbios_int(const u_int8_t *, int, struct mp_intr_map *);
+void	mpbios_int(const u_int8_t *, struct mp_intr_map *);
 
 const void *mpbios_map(paddr_t, int, struct mp_map *);
 static __inline void mpbios_unmap(struct mp_map *);
@@ -457,6 +457,7 @@
 struct mp_bus *mp_busses;
 int mp_nbus;
 struct mp_intr_map *mp_intrs;
+int mp_nintrs;
 
 struct mp_intr_map *lapic_ints[2]; /* XXX */
 int mp_isa_bus = -1;		/* XXX */
@@ -506,7 +507,7 @@
 	const u_int8_t 	*position, *end;
 	int		count;
 	int		type;
-	int		intr_cnt, cur_intr;
+	int		intr_cnt;
 	paddr_t		lapic_base;
 
 	printf("%s: Intel MP Specification ", self->dv_xname);
@@ -580,7 +581,7 @@
 		position += sizeof(*mp_cth);
 
 		count = mp_cth->entry_count;
-		intr_cnt = 0;
+		intr_cnt = 15;	/* presume all isa irqs being missing */
 
 		while ((count--) && (position < end)) {
 			type = *position;
@@ -626,7 +627,7 @@
 		/* re-walk the table, recording info of interest */
 		position = (const u_int8_t *)mp_cth + sizeof(*mp_cth);
 		count = mp_cth->entry_count;
-		cur_intr = 0;
+		mp_nintrs = 0;
 
 		while ((count--) && (position < end)) {
 			switch (type = *(u_char *)position) {
@@ -641,9 +642,7 @@
 				break;
 			case MPS_MCT_IOINT:
 			case MPS_MCT_LINT:
-				mpbios_int(position, type,
-				    &mp_intrs[cur_intr]);
-				cur_intr++;
+				mpbios_int(position, &mp_intrs[mp_nintrs++]);
 				break;
 			default:
 				printf("%s: unknown entry type %x "
@@ -669,6 +668,38 @@
 	}
 }
 
+int
+mpbios_invent(int irq, int type, int bus)
+{
+	struct mp_intr_map *mip;
+	struct mpbios_int e;
+
+	e.type = MPS_MCT_IOINT;
+	e.int_type = MPS_INTTYPE_INT;
+	switch (type) {
+	case IST_EDGE:
+		e.int_flags = MPS_INT(MPS_INTPO_ACTHI, MPS_INTTR_EDGE);
+		break;
+
+	case IST_LEVEL:
+		e.int_flags = MPS_INT(MPS_INTPO_ACTLO, MPS_INTTR_LEVEL);
+		break;
+
+	case IST_NONE:
+	case IST_PULSE:
+		e.int_flags = MPS_INT(MPS_INTPO_DEF, MPS_INTTR_DEF);
+		break;
+	}
+	e.src_bus_id = bus;
+	e.src_bus_irq = irq;
+	e.dst_apic_id = mp_busses[bus].mb_intrs->ioapic->sc_apicid;
+	e.dst_apic_int = irq;
+
+	mpbios_int((const u_int8_t *)&e, (mip = &mp_intrs[mp_nintrs++]));
+
+	return (mip->ioapic_ih | irq);
+}
+
 void
 mpbios_cpu(ent, self)
 	const u_int8_t *ent;
@@ -1005,9 +1036,8 @@
 		"f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
 
 void
-mpbios_int(ent, enttype, mpi)
+mpbios_int(ent, mpi)
 	const u_int8_t *ent;
-	int enttype;
 	struct mp_intr_map *mpi;
 {
 	const struct mpbios_int *entry = (const struct mpbios_int *)ent;
@@ -1059,7 +1089,7 @@
 
 	(*mpb->mb_intr_cfg)(&rw_entry, &mpi->redir);
 
-	if (enttype == MPS_MCT_IOINT) {
+	if (entry->type == MPS_MCT_IOINT) {
 		sc = ioapic_find(id);
 		if (sc == NULL) {
 			printf("mpbios: can't find ioapic %d\n", id);
Index: include/i82093var.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/include/i82093var.h,v
retrieving revision 1.3
diff -u -r1.3 i82093var.h
--- include/i82093var.h	23 Jun 2004 17:14:31 -0000	1.3
+++ include/i82093var.h	22 Nov 2005 09:44:14 -0000
@@ -81,6 +81,7 @@
 #define APIC_INT_APIC_SHIFT	16
 #define APIC_INT_PIN_MASK	0x0000ff00
 #define APIC_INT_PIN_SHIFT	8
+#define APIC_INT_LINE_MASK	0x000000ff
 
 #define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT)
 #define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT)
Index: include/mpbiosreg.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/include/mpbiosreg.h,v
retrieving revision 1.2
diff -u -r1.2 mpbiosreg.h
--- include/mpbiosreg.h	13 Jun 2004 21:49:16 -0000	1.2
+++ include/mpbiosreg.h	22 Nov 2005 09:56:27 -0000
@@ -70,11 +70,18 @@
 #define MPS_INTPO_DEF		0
 #define MPS_INTPO_ACTHI		1
 #define MPS_INTPO_ACTLO		3
+#define MPS_INTPO_SHIFT		0
+#define MPS_INTPO_MASK		3
 
 #define MPS_INTTR_DEF		0
 #define MPS_INTTR_EDGE		1
 #define MPS_INTTR_LEVEL		3
+#define MPS_INTTR_SHIFT		2
+#define MPS_INTTR_MASK		3
 
+#define MPS_INT(p,t) \
+    ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \
+     (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT))
 
 /* MP Floating Pointer Structure */
 struct mpbios_fps {
Index: include/mpbiosvar.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/include/mpbiosvar.h,v
retrieving revision 1.2
diff -u -r1.2 mpbiosvar.h
--- include/mpbiosvar.h	13 Jun 2004 21:49:16 -0000	1.2
+++ include/mpbiosvar.h	22 Nov 2005 09:44:14 -0000
@@ -81,6 +81,7 @@
 
 void mpbios_scan(struct device *);
 int mpbios_probe(struct device *);
+int mpbios_invent(int, int, int);
 #endif
 
 #endif
Index: isa/isa_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/isa/isa_machdep.c,v
retrieving revision 1.51
diff -u -r1.51 isa_machdep.c
--- isa/isa_machdep.c	29 Nov 2004 20:15:40 -0000	1.51
+++ isa/isa_machdep.c	22 Nov 2005 09:44:14 -0000
@@ -558,9 +558,11 @@
 				}
 			}
 		}
+
+		/* no MP mapping found -- invent! */
  		if (mip == NULL)
-			printf("isa_intr_establish: no MP mapping found\n");
- 		else
+			airq = mpbios_invent(irq, type, mp_isa_bus);
+
 			return (apic_intr_establish(airq, type, level, ih_fun,
 			    ih_arg, ih_what));
  	}
Index: pci/pci_intr_fixup.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/pci_intr_fixup.c,v
retrieving revision 1.48
diff -u -r1.48 pci_intr_fixup.c
--- pci/pci_intr_fixup.c	21 Nov 2005 22:28:13 -0000	1.48
+++ pci/pci_intr_fixup.c	22 Nov 2005 09:44:14 -0000
@@ -101,6 +101,7 @@
 #include <machine/bus.h>
 #include <machine/intr.h>
 #include <machine/i8259.h>
+#include <machine/i82093var.h>
 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
@@ -535,15 +536,15 @@
 {
 	struct pciintr_link_map *l;
 	pcireg_t intr;
-	int rv = 1;
+	int irq, rv = 1;
 	char *p = NULL;
 
 	if (pcibios_flags & PCIBIOS_INTR_FIXUP)
 		return 1;
 
-	if (ihp->line != 0 &&
-	    ihp->line != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
-		pcibios_pir_header.exclusive_irq |= (1 << ihp->line);
+	irq = ihp->line & APIC_INT_LINE_MASK;
+	if (irq != 0 && irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
+		pcibios_pir_header.exclusive_irq |= 1 << irq;
 
 	l = ihp->link;
 	if (!l || pciintr_icu_tag == NULL)
@@ -584,13 +585,13 @@
 	 * IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
 	 * with them.
 	 */
-	if (ihp->line == 14 || ihp->line == 15)
+	if (irq == 14 || irq == 15)
 		return (1);
 
 	intr = pci_conf_read(pc, ihp->tag, PCI_INTERRUPT_REG);
-	if (ihp->line != PCI_INTERRUPT_LINE(intr)) {
+	if (irq != PCI_INTERRUPT_LINE(intr)) {
 		intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
-		intr |= (ihp->line << PCI_INTERRUPT_LINE_SHIFT);
+		intr |= irq << PCI_INTERRUPT_LINE_SHIFT;
 		pci_conf_write(pc, ihp->tag, PCI_INTERRUPT_REG, intr);
 	}
 
@@ -651,7 +652,7 @@
 	if (pcibios_flags & PCIBIOS_INTR_FIXUP)
 		return 1;
 
-	irq = ihp->line;
+	irq = ihp->line & APIC_INT_LINE_MASK;
 	ihp->link = NULL;
 	ihp->tag = tag;
 	pci_decompose_tag(pc, tag, &bus, &device, &function);
@@ -666,7 +667,7 @@
 		/*
 		 * No link map entry.
 		 * Probably pciintr_icu_getclink() or pciintr_icu_get_intr()
-		 * was failed.
+		 * has failed.
 		 */
 		if (pcibios_flags & PCIBIOS_INTRDEBUG)
 			printf("pci_intr_header_fixup: no entry for link "
@@ -682,8 +683,8 @@
 	} else if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
 
 		/* Appropriate interrupt was not found. */
-		if (pciintr_icu_tag == NULL && ihp->line != 0 &&
-		    ihp->line != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
+		if (pciintr_icu_tag == NULL && irq != 0 &&
+		    irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
 			/*
 			 * Do not print warning,
 			 * if no compatible PCI ICU found,
@@ -695,17 +696,17 @@
 	} else if (irq == 0 || irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
 
 		p = " fixed up";
-		ihp->line = l->irq;
+		ihp->line = irq = l->irq;
 
 	} else if (pcibios_flags & PCIBIOS_FIXUP_FORCE) {
 		/* routed by BIOS, but inconsistent */
 		/* believe PCI IRQ Routing table */
 		p = " WARNING: overriding";
-		ihp->line = l->irq;
+		ihp->line = irq = l->irq;
 	} else {
 		/* believe PCI Interrupt Configuration Register (default) */
 		p = " WARNING: preserving";
-		ihp->line = l->irq = irq;
+		ihp->line = (l->irq = irq) | (l->clink & PCI_INT_VIA_ISA);
 	}
 
 	if (pcibios_flags & PCIBIOS_INTRDEBUG) {
Index: pci/pci_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.c,v
retrieving revision 1.29
diff -u -r1.29 pci_machdep.c
--- pci/pci_machdep.c	28 Jul 2005 17:22:28 -0000	1.29
+++ pci/pci_machdep.c	22 Nov 2005 10:50:30 -0000
@@ -107,8 +107,8 @@
 
 #include "ioapic.h"
 
-#if NIOAPIC > 0
 #include <machine/i82093var.h>
+#if NIOAPIC > 0
 #include <machine/mpbiosvar.h>
 #endif
 
@@ -510,7 +510,7 @@
 	ihp->pin = pin;
 #if NPCIBIOS > 0
 	pci_intr_header_fixup(pc, intrtag, ihp);
-	line = ihp->line;
+	line = ihp->line & APIC_INT_LINE_MASK;
 #endif
 
 	/*
@@ -543,7 +543,7 @@
 #if NIOAPIC > 0
 	pci_decompose_tag (pc, intrtag, &bus, &dev, &func);
 
-	if (mp_busses != NULL) {
+	if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
 		/*
 		 * Assumes 1:1 mapping between PCI bus numbers and
 		 * the numbers given by the MP bios.
@@ -597,20 +597,20 @@
 	pci_intr_handle_t ih;
 {
 	static char irqstr[64];
+	int line = ih.line & APIC_INT_LINE_MASK;
 
-	if (ih.line == 0 || (ih.line  & 0xff) >= ICU_LEN || ih.line == 2)
-		panic("pci_intr_string: bogus handle 0x%x", ih.line);
+	if (line == 0 || line >= ICU_LEN || line == 2)
+		panic("pci_intr_string: bogus handle 0x%x", line);
 
 #if NIOAPIC > 0
 	if (ih.line & APIC_INT_VIA_APIC) {
 		snprintf(irqstr, sizeof irqstr, "apic %d int %d (irq %d)",
-		     APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line),
-		     ih.line & 0xff);
+		     APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line), line);
 		return (irqstr);
 	}
 #endif
 
-	snprintf(irqstr, sizeof irqstr, "irq %d", ih.line);
+	snprintf(irqstr, sizeof irqstr, "irq %d", line);
 	return (irqstr);
 }
 
@@ -623,17 +623,17 @@
 	char *what;
 {
 	void *ret;
+	int l = ih.line & APIC_INT_LINE_MASK;
 
 #if NIOAPIC > 0
-	if (ih.line != -1 && ih.line & APIC_INT_VIA_APIC)
+	if (l != -1 && ih.line & APIC_INT_VIA_APIC)
 		return (apic_intr_establish(ih.line, IST_LEVEL, level, func, 
 		    arg, what));
 #endif
-	if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
-		panic("pci_intr_establish: bogus handle 0x%x", ih.line);
+	if (l == 0 || l >= ICU_LEN || l == 2)
+		panic("pci_intr_establish: bogus handle 0x%x", l);
 
-	ret = isa_intr_establish(NULL, ih.line, IST_LEVEL, level, func, arg,
-	    what);
+	ret = isa_intr_establish(NULL, l, IST_LEVEL, level, func, arg, what);
 #if NPCIBIOS > 0
 	if (ret)
 		pci_intr_route_link(pc, &ih);
Index: pci/pcibiosvar.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/pcibiosvar.h,v
retrieving revision 1.14
diff -u -r1.14 pcibiosvar.h
--- pci/pcibiosvar.h	26 Sep 2004 20:17:42 -0000	1.14
+++ pci/pcibiosvar.h	22 Nov 2005 09:44:15 -0000
@@ -146,6 +146,8 @@
 #define	PCIADDR_SEARCH_MEM	1
 struct extent *pciaddr_search(int, bus_addr_t *, bus_size_t);
 
+#define	PCI_INT_VIA_ISA		0x20000000 /* XXX see APIC_INT_VIA_APIC */
+
 int  pci_intr_fixup(struct pcibios_softc *, pci_chipset_tag_t, bus_space_tag_t);
 int  pci_bus_fixup(pci_chipset_tag_t, int);
 void pci_addr_fixup(struct pcibios_softc *, pci_chipset_tag_t, int);
Index: pci/rccosb4.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/rccosb4.c,v
retrieving revision 1.3
diff -u -r1.3 rccosb4.c
--- pci/rccosb4.c	10 Nov 2005 15:14:09 -0000	1.3
+++ pci/rccosb4.c	22 Nov 2005 10:58:40 -0000
@@ -98,6 +98,8 @@
 {
 	if (OSB4_LEGAL_LINK(link - 1)) {
 		*clinkp = link;
+ 		if (link <= OSB4_PISP)
+			*clinkp |= PCI_INT_VIA_ISA;
 		return (0);
 	}
 
@@ -108,11 +110,12 @@
 osb4_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
 {
 	struct osb4_handle *ph = v;
+	int link = clink & 0xff;
 
-	if (!OSB4_LEGAL_LINK(clink))
+	if (!OSB4_LEGAL_LINK(link))
 		return (1);
 
-	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, clink);
+	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
 	*irqp = bus_space_read_1(ph->osb4_iot, ph->osb4_ioh, 1) & 0xf;
 	if (*irqp == 0)
 		*irqp = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
@@ -124,11 +127,12 @@
 osb4_set_intr(pciintr_icu_handle_t v, int clink, int irq)
 {
 	struct osb4_handle *ph = v;
+	int link = clink & 0xff;
 
-	if (!OSB4_LEGAL_LINK(clink) || !OSB4_LEGAL_IRQ(irq & 0xf))
+	if (!OSB4_LEGAL_LINK(link) || !OSB4_LEGAL_IRQ(irq & 0xf))
 		return (1);
 
-	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, clink);
+	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
 	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 1, irq & 0xf);
 
 	return (0);



Visit your host, monkey.org