[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
amd64 IPI diff
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: amd64 IPI diff
- From: Brad <brad_(_at_)_comstyle_(_dot_)_com>
- Date: Sun, 5 Mar 2006 17:33:49 -0500
If you have an amd64 system running the MP kernel then please
try this out..
- 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
Index: lapic.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
retrieving revision 1.4
diff -u -p -r1.4 lapic.c
--- lapic.c 13 Dec 2005 23:33:25 -0000 1.4
+++ lapic.c 29 Jan 2006 04:44:26 -0000
@@ -402,11 +402,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);
@@ -415,18 +433,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;
}
@@ -435,13 +449,11 @@ int
x86_ipi(vec,target,dl)
int vec,target,dl;
{
- unsigned j;
- int result;
+ int result, s;
+
+ s = splclock();
- for (j=100000;
- j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
- j--)
- ;
+ i82489_icr_wait();
if ((target & LAPIC_DEST_MASK) == 0)
i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
@@ -449,12 +461,11 @@ 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;
}
Index: ipi.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/ipi.c,v
retrieving revision 1.2
diff -u -p -r1.2 ipi.c
--- ipi.c 25 Sep 2005 20:48:18 -0000 1.2
+++ ipi.c 29 Jan 2006 04:44:26 -0000
@@ -75,19 +75,10 @@ x86_send_ipi(struct cpu_info *ci, int ip
}
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
Visit your host, monkey.org