Subject: Re: Getting "TLB IPI rendezvous failed..."
To: Stephan Uphoff <ups@tree.com>
From: Frank van der Linden <fvdl@netbsd.org>
List: tech-kern
Date: 01/12/2005 04:59:28
On Tue, Jan 11, 2005 at 03:37:56PM -0500, Stephan Uphoff wrote:
> I think that sending IPIs needs to be protected with splclock() since
> some interrupts may send IPIs.
> x86_broadcast_ipi should also call x86_ipi to benefit from
> i82489_icr_wait.
Good point. splclock should stop IPIs from the clock interrupt as well
as those from interrupt handlers that cause TLB shootdown IPIs by doing
VM operations.
I assume you mean something like.. this (diff obfuscated a little because
I deleted the unused x86_self_ipi function):
Index: ipi.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/ipi.c,v
retrieving revision 1.5
diff -c -r1.5 ipi.c
*** ipi.c 13 Feb 2004 11:36:20 -0000 1.5
--- ipi.c 12 Jan 2005 03:53:15 -0000
***************
*** 55,67 ****
int
x86_send_ipi(struct cpu_info *ci, int ipimask)
{
! int ret;
x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
/* Don't send IPI to CPU which isn't (yet) running. */
! if (!(ci->ci_flags & CPUF_RUNNING))
return ENOENT;
ret = x86_ipi(LAPIC_IPI_VECTOR, ci->ci_apicid, LAPIC_DLMODE_FIXED);
if (ret != 0) {
--- 55,71 ----
int
x86_send_ipi(struct cpu_info *ci, int ipimask)
{
! int ret, s;
!
! s = splclock();
x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
/* Don't send IPI to CPU which isn't (yet) running. */
! if (!(ci->ci_flags & CPUF_RUNNING)) {
! splx(s);
return ENOENT;
+ }
ret = x86_ipi(LAPIC_IPI_VECTOR, ci->ci_apicid, LAPIC_DLMODE_FIXED);
if (ret != 0) {
***************
*** 71,95 ****
ci->ci_dev->dv_xname);
}
! return ret;
! }
! 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)
{
struct cpu_info *ci, *self = curcpu();
! int count = 0;
!
CPU_INFO_ITERATOR cii;
for (CPU_INFO_FOREACH(cii, ci)) {
if (ci == self)
continue;
--- 75,94 ----
ci->ci_dev->dv_xname);
}
! splx(s);
! return ret;
}
void
x86_broadcast_ipi (int ipimask)
{
struct cpu_info *ci, *self = curcpu();
! int count = 0, s;
CPU_INFO_ITERATOR cii;
+ s = splclock();
+
for (CPU_INFO_FOREACH(cii, ci)) {
if (ci == self)
continue;
***************
*** 98,109 ****
x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
count++;
}
! if (!count)
return;
! i82489_writereg(LAPIC_ICRLO,
! LAPIC_IPI_VECTOR | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT |
! LAPIC_DEST_ALLEXCL);
}
void
--- 97,110 ----
x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
count++;
}
! if (!count) {
! splx(s);
return;
+ }
+
+ x86_ipi(LAPIC_IPI_VECTOR, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED);
! splx(s);
}
void