diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-03-10 21:21:09 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-03-10 21:21:09 +0000 |
commit | f34f42fc46e81183449c79fa48c8af5cc22a005f (patch) | |
tree | 73b2c3cfe655d261002175e2d701eeb1f3c877aa /sys/arch | |
parent | 7ac129ebbdfceaafadfa01dcfff6523abf4844b0 (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.c | 17 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/lapic.c | 47 |
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; } |