[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

amd64 IPI diff



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