Add two workarounds for broken MP tables:

- Attempt to handle PCI devices where the interrupt is
	  an ISA/EISA interrupt according to the mp table.

	- Attempt to handle multiple IO APIC pins connected to
	  the same PCI or ISA/EISA interrupt source.  Print a
	  warning if this happens, since performance is suboptimal.
	  This workaround is only used for PCI devices.

With these two workarounds, the -SMP kernel is capable of running on
my Asus P/I-P65UP5 motherboard when version 1.4 of the MP table is disabled.
This commit is contained in:
Tor Egge 1998-04-01 21:07:37 +00:00
parent 300e9a7696
commit 5758c2de94
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=34990
14 changed files with 442 additions and 43 deletions

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: smp.h,v 1.40 1998/03/07 21:34:59 dyson Exp $
* $Id: smp.h,v 1.41 1998/04/01 20:38:28 tegge Exp $
*
*/
@ -112,6 +112,7 @@ void mp_announce __P((void));
u_int isa_apic_mask __P((u_int));
int isa_apic_pin __P((int));
int pci_apic_pin __P((int, int, int));
int next_apic_pin __P((int));
int undirect_isa_irq __P((int));
int undirect_pci_irq __P((int));
int apic_bus_type __P((int));

View File

@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: pci.c,v 1.80 1997/11/07 08:53:28 phk Exp $
* $Id: pci.c,v 1.81 1998/01/24 02:54:47 eivind Exp $
*
*/
@ -340,9 +340,25 @@ pci_readcfg(pcicfgregs *probe)
int airq;
airq = pci_apic_pin(cfg->bus, cfg->slot, cfg->intpin);
if ((airq >= 0) && (airq != cfg->intline)) {
undirect_pci_irq(cfg->intline);
cfg->intline = airq;
if (airq >= 0) {
/* PCI specific entry found in MP table */
if (airq != cfg->intline) {
undirect_pci_irq(cfg->intline);
cfg->intline = airq;
}
} else {
/*
* PCI interrupts might be redirected to the
* ISA bus according to some MP tables. Use the
* same methods as used by the ISA devices
* devices to find the proper IOAPIC int pin.
*/
airq = isa_apic_pin(cfg->intline);
if ((airq >= 0) && (airq != cfg->intline)) {
/* XXX: undirect_pci_irq() ? */
undirect_isa_irq(cfg->intline);
cfg->intline = airq;
}
}
}
#endif /* APIC_IO */

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mpapic.c,v 1.27 1997/12/08 18:36:02 fsmp Exp $
* $Id: mpapic.c,v 1.28 1998/03/03 19:54:49 tegge Exp $
*/
#include "opt_smp.h"
@ -164,7 +164,7 @@ io_apic_setup(int apic)
if (apic == 0) {
maxpin = REDIRCNT_IOAPIC(apic); /* pins in APIC */
for (pin = 0; pin < maxpin; ++pin) {
int bus, bustype;
int bus;
/* we only deal with vectored INTs here */
if (apic_int_type(apic, pin) != 0)
@ -174,21 +174,12 @@ io_apic_setup(int apic)
bus = apic_src_bus_id(apic, pin);
if (bus == -1)
continue;
bustype = apic_bus_type(bus);
/* the "ISA" type INTerrupts */
if ((bustype == ISA) || (bustype == EISA)) {
flags = DEFAULT_ISA_FLAGS;
}
/* PCI or other bus */
else {
flags = DEFAULT_FLAGS;
level = trigger(apic, pin, &flags);
if (level == 1)
apic_pin_trigger[apic] |= (1 << pin);
polarity(apic, pin, &flags, level);
}
flags = DEFAULT_FLAGS;
level = trigger(apic, pin, &flags);
if (level == 1)
apic_pin_trigger[apic] |= (1 << pin);
polarity(apic, pin, &flags, level);
/* program the appropriate registers */
select = pin * 2 + IOAPIC_REDTBL0; /* register */

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: smp.h,v 1.40 1998/03/07 21:34:59 dyson Exp $
* $Id: smp.h,v 1.41 1998/04/01 20:38:28 tegge Exp $
*
*/
@ -112,6 +112,7 @@ void mp_announce __P((void));
u_int isa_apic_mask __P((u_int));
int isa_apic_pin __P((int));
int pci_apic_pin __P((int, int, int));
int next_apic_pin __P((int));
int undirect_isa_irq __P((int));
int undirect_pci_irq __P((int));
int apic_bus_type __P((int));

View File

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.69 1998/03/03 22:56:24 tegge Exp $
* $Id: mp_machdep.c,v 1.70 1998/03/07 20:16:49 tegge Exp $
*/
#include "opt_smp.h"
@ -1199,7 +1199,6 @@ isa_apic_pin(int isa_irq)
}
return -1; /* NOT found */
}
#undef SRCBUSIRQ
/*
@ -1225,9 +1224,57 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt)
return -1; /* NOT found */
}
int
next_apic_pin(int pin)
{
int intr, ointr;
int bus, bustype;
bus = 0;
bustype = 0;
for (intr = 0; intr < nintrs; intr++) {
if (INTPIN(intr) != pin || INTTYPE(intr) != 0)
continue;
bus = SRCBUSID(intr);
bustype = apic_bus_type(bus);
if (bustype != ISA &&
bustype != EISA &&
bustype != PCI)
continue;
break;
}
if (intr >= nintrs) {
return -1;
}
for (ointr = intr + 1; ointr < nintrs; ointr++) {
if (INTTYPE(ointr) != 0)
continue;
if (bus != SRCBUSID(ointr))
continue;
if (bustype == PCI) {
if (SRCBUSDEVICE(intr) != SRCBUSDEVICE(ointr))
continue;
if (SRCBUSLINE(intr) != SRCBUSLINE(ointr))
continue;
}
if (bustype == ISA || bustype == EISA) {
if (SRCBUSIRQ(intr) != SRCBUSIRQ(ointr))
continue;
}
if (INTPIN(intr) == INTPIN(ointr))
continue;
break;
}
if (ointr >= nintrs) {
return -1;
}
return INTPIN(ointr);
}
#undef SRCBUSLINE
#undef SRCBUSDEVICE
#undef SRCBUSID
#undef SRCBUSIRQ
#undef INTPIN
#undef INTTYPE

View File

@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: pci.c,v 1.80 1997/11/07 08:53:28 phk Exp $
* $Id: pci.c,v 1.81 1998/01/24 02:54:47 eivind Exp $
*
*/
@ -340,9 +340,25 @@ pci_readcfg(pcicfgregs *probe)
int airq;
airq = pci_apic_pin(cfg->bus, cfg->slot, cfg->intpin);
if ((airq >= 0) && (airq != cfg->intline)) {
undirect_pci_irq(cfg->intline);
cfg->intline = airq;
if (airq >= 0) {
/* PCI specific entry found in MP table */
if (airq != cfg->intline) {
undirect_pci_irq(cfg->intline);
cfg->intline = airq;
}
} else {
/*
* PCI interrupts might be redirected to the
* ISA bus according to some MP tables. Use the
* same methods as used by the ISA devices
* devices to find the proper IOAPIC int pin.
*/
airq = isa_apic_pin(cfg->intline);
if ((airq >= 0) && (airq != cfg->intline)) {
/* XXX: undirect_pci_irq() ? */
undirect_isa_irq(cfg->intline);
cfg->intline = airq;
}
}
}
#endif /* APIC_IO */

View File

@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: pci_compat.c,v 1.5 1997/08/21 07:05:48 fsmp Exp $
* $Id: pci_compat.c,v 1.6 1997/08/21 08:42:59 fsmp Exp $
*
*/
@ -164,13 +164,57 @@ int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
int
pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr)
{
int error;
#ifdef APIC_IO
int nextpin, muxcnt;
#endif
if (cfg->intpin != 0) {
int irq = cfg->intline;
void *dev_instance = (void *)-1; /* XXX use cfg->devdata */
void *idesc;
idesc = intr_create(dev_instance, irq, func, arg, maskptr, 0);
return (intr_connect(idesc) == 0);
error = intr_connect(idesc);
if (error != 0)
return 0;
#ifdef APIC_IO
nextpin = next_apic_pin(irq);
if (nextpin < 0)
return 1;
/*
* Attempt handling of some broken mp tables.
*
* It's OK to yell (since the mp tables are broken).
*
* Hanging in the boot is not OK
*/
muxcnt = 2;
nextpin = next_apic_pin(nextpin);
while (muxcnt < 5 && nextpin >= 0) {
muxcnt++;
nextpin = next_apic_pin(nextpin);
}
if (muxcnt >= 5) {
printf("bogus MP table, more than 4 IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n");
return 0;
}
printf("bogus MP table, %d IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n", muxcnt);
nextpin = next_apic_pin(irq);
while (nextpin >= 0) {
idesc = intr_create(dev_instance, nextpin, func, arg,
maskptr, 0);
error = intr_connect(idesc);
if (error != 0)
return 0;
printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
nextpin = next_apic_pin(nextpin);
}
#endif
}
return (1);
}

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: smp.h,v 1.40 1998/03/07 21:34:59 dyson Exp $
* $Id: smp.h,v 1.41 1998/04/01 20:38:28 tegge Exp $
*
*/
@ -112,6 +112,7 @@ void mp_announce __P((void));
u_int isa_apic_mask __P((u_int));
int isa_apic_pin __P((int));
int pci_apic_pin __P((int, int, int));
int next_apic_pin __P((int));
int undirect_isa_irq __P((int));
int undirect_pci_irq __P((int));
int apic_bus_type __P((int));