summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2004-08-12 06:11:58 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2004-08-12 06:11:58 +0000
commitea738fcf3d432a4bfc4b3ec529a2fa9193ea4da2 (patch)
tree441865a2d68453fd26398782af124ad673d1f108 /sys/arch
parent093af044ac57a48937832286b3f0e8a5b495ef04 (diff)
Fix the shared irq problem, by allocating a low priority vector
so that the "high" pri interrupt gets blocked by the "low" spl & irq handler, and raise the cpl to the "high" level in the handler, so that no other in fact lower-leveled, interrupts can preempt the handling of the "high" interrupt. This means that the "low" interrupt gets the same quality treatment, thus causing some degradation in performance. Therefore we still issue a diagnostic, so people can try to avoid the situation by tweaking their BIOS settings. Note, there is still issues with dynamically established interrupts which cause irq sharing, we are working on that.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/i386/apicvec.s7
-rw-r--r--sys/arch/i386/i386/ioapic.c18
2 files changed, 12 insertions, 13 deletions
diff --git a/sys/arch/i386/i386/apicvec.s b/sys/arch/i386/i386/apicvec.s
index 4ab84c31def..59f3744052e 100644
--- a/sys/arch/i386/i386/apicvec.s
+++ b/sys/arch/i386/i386/apicvec.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: apicvec.s,v 1.3 2004/06/28 02:00:20 deraadt Exp $ */
+/* $OpenBSD: apicvec.s,v 1.4 2004/08/12 06:11:57 niklas Exp $ */
/* $NetBSD: apicvec.s,v 1.1.2.2 2000/02/21 21:54:01 sommerfeld Exp $ */
/*-
@@ -179,12 +179,13 @@ _C_LABEL(Xintr_/**/name/**/num): \
MAKE_FRAME ;\
pushl CPL ;\
movl _C_LABEL(lapic_ppr),%eax ;\
- movl %eax,CPL ;\
+ orl $num,%eax ;\
+ movl _C_LABEL(apic_maxlevel)(,%eax,4),%ebx ;\
+ movl %ebx,CPL ;\
mask(num) /* mask it in hardware */ ;\
early_ack(num) /* and allow other intrs */ ;\
incl MY_COUNT+V_INTR /* statistical info */ ;\
sti ;\
- orl $num,%eax ;\
incl _C_LABEL(apic_intrcount)(,%eax,4) ;\
movl _C_LABEL(apic_intrhand)(,%eax,4),%ebx /* chain head */ ;\
testl %ebx,%ebx ;\
diff --git a/sys/arch/i386/i386/ioapic.c b/sys/arch/i386/i386/ioapic.c
index 0ec3795e0c4..abb77edfb6e 100644
--- a/sys/arch/i386/i386/ioapic.c
+++ b/sys/arch/i386/i386/ioapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioapic.c,v 1.4 2004/06/28 01:41:53 aaron Exp $ */
+/* $OpenBSD: ioapic.c,v 1.5 2004/08/12 06:11:57 niklas Exp $ */
/* $NetBSD: ioapic.c,v 1.7 2003/07/14 22:32:40 lukem Exp $ */
/*-
@@ -354,6 +354,7 @@ ioapic_attach(struct device *parent, struct device *self, void *aux)
struct intrhand *apic_intrhand[256];
int apic_intrcount[256];
+int apic_maxlevel[256];
/* XXX should check vs. softc max int number */
@@ -459,14 +460,10 @@ apic_vectorset(struct ioapic_softc *sc, int pin, int minlevel, int maxlevel)
pp->ip_maxlevel = 0; /* XXX magic */
pp->ip_vector = 0;
} else if (maxlevel != pp->ip_maxlevel) {
- if (minlevel != maxlevel) {
- printf("%s: WARNING: sharing interrupt "
- "between different IPLs (currently broken)\n",
- sc->sc_dev.dv_xname);
- printf("%s: pin %d, ipls %x..%x\n",
- sc->sc_dev.dv_xname,
- pin, minlevel, maxlevel);
- }
+ if (minlevel != maxlevel)
+ printf("%s: pin %d shares different IPL interrupts "
+ "(%x..%x), degraded performance\n",
+ sc->sc_dev.dv_xname, pin, minlevel, maxlevel);
/*
* Allocate interrupt vector at the *lowest* priority level
@@ -475,7 +472,7 @@ apic_vectorset(struct ioapic_softc *sc, int pin, int minlevel, int maxlevel)
* The interrupt handler will raise ipl higher than this
* as appropriate.
*/
- nvector = idt_vec_alloc(maxlevel, maxlevel+15);
+ nvector = idt_vec_alloc(minlevel, minlevel+15);
if (nvector == 0) {
/*
@@ -486,6 +483,7 @@ apic_vectorset(struct ioapic_softc *sc, int pin, int minlevel, int maxlevel)
panic("%s: can't alloc vector for pin %d at level %x",
sc->sc_dev.dv_xname, pin, maxlevel);
}
+ apic_maxlevel[nvector] = maxlevel;
/*
* XXX want special handler for the maxlevel != minlevel
* case here!