summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-03-10 21:21:09 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-03-10 21:21:09 +0000
commitf34f42fc46e81183449c79fa48c8af5cc22a005f (patch)
tree73b2c3cfe655d261002175e2d701eeb1f3c877aa /sys/arch
parent7ac129ebbdfceaafadfa01dcfff6523abf4844b0 (diff)
- Wrap IPI sending in splclock(), since an interrupt at
IPL_CLOCK or lower may cause IPIs. - Make broadcast IPIs go through x86_ipi() as well, so that they wait for the APIC to be ready too. - Introduce a function, i82489_icr_wait, which waits for LAPIC_DLSTAT_BUSY cleared, and use it where appropriate. - Panic if lapic's busy too long and DIAGNOSTIC. From NetBSD Tested on a few amd64 MP systems.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/ipi.c17
-rw-r--r--sys/arch/amd64/amd64/lapic.c47
2 files changed, 32 insertions, 32 deletions
diff --git a/sys/arch/amd64/amd64/ipi.c b/sys/arch/amd64/amd64/ipi.c
index c23a85dd0ed..32dd38f8bd3 100644
--- a/sys/arch/amd64/amd64/ipi.c
+++ b/sys/arch/amd64/amd64/ipi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipi.c,v 1.4 2006/03/10 21:11:08 mickey Exp $ */
+/* $OpenBSD: ipi.c,v 1.5 2006/03/10 21:21:08 brad Exp $ */
/* $NetBSD: ipi.c,v 1.2 2003/03/01 13:05:37 fvdl Exp $ */
/*-
@@ -75,19 +75,10 @@ x86_send_ipi(struct cpu_info *ci, int ipimask)
}
void
-x86_self_ipi (int vector)
-{
- i82489_writereg(LAPIC_ICRLO,
- vector | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT | LAPIC_DEST_SELF);
-}
-
-
-void
-x86_broadcast_ipi (int ipimask)
+x86_broadcast_ipi(int ipimask)
{
struct cpu_info *ci, *self = curcpu();
int count = 0;
-
CPU_INFO_ITERATOR cii;
CPU_INFO_FOREACH(cii, ci) {
@@ -101,9 +92,7 @@ x86_broadcast_ipi (int ipimask)
if (!count)
return;
- i82489_writereg(LAPIC_ICRLO,
- LAPIC_IPI_VECTOR | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT |
- LAPIC_DEST_ALLEXCL);
+ x86_ipi(LAPIC_IPI_VECTOR, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED);
}
void
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
index 69adb4ca073..53fdc7da368 100644
--- a/sys/arch/amd64/amd64/lapic.c
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lapic.c,v 1.5 2006/03/10 21:09:22 mickey Exp $ */
+/* $OpenBSD: lapic.c,v 1.6 2006/03/10 21:21:08 brad Exp $ */
/* $NetBSD: lapic.c,v 1.2 2003/05/08 01:04:35 fvdl Exp $ */
/*-
@@ -405,11 +405,29 @@ lapic_delay(usec)
* XXX the following belong mostly or partly elsewhere..
*/
+static __inline void i82489_icr_wait(void);
+
+static __inline void
+i82489_icr_wait()
+{
+#ifdef DIAGNOSTIC
+ unsigned j = 100000;
+#endif /* DIAGNOSTIC */
+
+ while ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0) {
+ x86_pause();
+#ifdef DIAGNOSTIC
+ j--;
+ if (j == 0)
+ panic("i82489_icr_wait: busy");
+#endif /* DIAGNOSTIC */
+ }
+}
+
int
x86_ipi_init(target)
int target;
{
- unsigned j;
if ((target&LAPIC_DEST_MASK)==0) {
i82489_writereg(LAPIC_ICRHI, target<<LAPIC_ID_SHIFT);
@@ -418,18 +436,14 @@ x86_ipi_init(target)
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_ASSERT );
- for (j=100000; j > 0; j--)
- if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
- break;
+ i82489_icr_wait();
delay(10000);
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_TRIG | LAPIC_LVL_DEASSERT);
- for (j=100000; j > 0; j--)
- if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
- break;
+ i82489_icr_wait();
return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY)?EBUSY:0;
}
@@ -438,13 +452,11 @@ int
x86_ipi(vec,target,dl)
int vec,target,dl;
{
- unsigned j;
- int result;
+ int result, s;
- for (j=100000;
- j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
- j--)
- ;
+ s = splclock();
+
+ i82489_icr_wait();
if ((target & LAPIC_DEST_MASK) == 0)
i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
@@ -452,13 +464,12 @@ x86_ipi(vec,target,dl)
i82489_writereg(LAPIC_ICRLO,
(target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LVL_ASSERT);
- for (j=100000;
- j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
- j--)
- ;
+ i82489_icr_wait();
result = (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
+ splx(s);
+
return result;
}