Updaing ci_ilevel and testing ci_ipending must be done with all interrupts

off, or priority inversion can occur, which can lead to IPI deadlocks.
Leaves interrupts off for a bit longer, sadly, but with no noticeable
effects on the systems I tested on.

From YAMAMOTO Takashi.
This commit is contained in:
fvdl 2004-06-28 09:13:11 +00:00
parent 2a4235ed84
commit 029ca90566
5 changed files with 27 additions and 28 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: spl.S,v 1.2 2003/08/20 21:48:48 fvdl Exp $ */
/* $NetBSD: spl.S,v 1.3 2004/06/28 09:13:11 fvdl Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@ -136,10 +136,8 @@ IDTVEC(spllower)
cli
andl CPUVAR(IPENDING),%eax # any non-masked bits left?
jz 2f
sti
bsrl %eax,%eax
btrl %eax,CPUVAR(IPENDING)
jnc 1b
movq CPUVAR(ISOURCES)(,%rax,8),%rax
jmp *IS_RECURSE(%rax)
2:
@ -166,10 +164,8 @@ IDTVEC(doreti)
cli
andl CPUVAR(IPENDING),%eax
jz 2f
sti
bsrl %eax,%eax # slow, but not worth optimizing
btrl %eax,CPUVAR(IPENDING)
jnc 1b # some intr cleared the in-memory bit
movq CPUVAR(ISOURCES)(,%rax, 8),%rax
jmp *IS_RESUME(%rax)
2: /* Check for ASTs on exit to user mode. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vector.S,v 1.4 2004/06/15 11:28:23 fvdl Exp $ */
/* $NetBSD: vector.S,v 1.5 2004/06/28 09:13:11 fvdl Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -298,8 +298,6 @@ IDTVEC(recurse_lapic_ipi)
pushq $0
pushq $T_ASTFLT
INTRENTRY
IDTVEC(resume_lapic_ipi)
cli
jmp 1f
IDTVEC(intr_lapic_ipi)
pushq $0
@ -309,6 +307,7 @@ IDTVEC(intr_lapic_ipi)
movl CPUVAR(ILEVEL),%ebx
cmpl $IPL_IPI,%ebx
jae 2f
IDTVEC(resume_lapic_ipi)
1:
incl CPUVAR(IDEPTH)
movl $IPL_IPI,CPUVAR(ILEVEL)
@ -346,8 +345,6 @@ IDTVEC(recurse_lapic_ltimer)
pushq $0
pushq $T_ASTFLT
INTRENTRY
IDTVEC(resume_lapic_ltimer)
cli
jmp 1f
IDTVEC(intr_lapic_ltimer)
pushq $0
@ -357,6 +354,7 @@ IDTVEC(intr_lapic_ltimer)
movl CPUVAR(ILEVEL),%ebx
cmpl $IPL_CLOCK,%ebx
jae 2f
IDTVEC(resume_lapic_ltimer)
1:
incl CPUVAR(IDEPTH)
movl $IPL_CLOCK,CPUVAR(ILEVEL)
@ -757,6 +755,7 @@ _C_LABEL(eintrcnt):
IDTVEC(softserial)
movl $IPL_SOFTSERIAL, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)
@ -773,6 +772,7 @@ IDTVEC(softserial)
IDTVEC(softnet)
movl $IPL_SOFTNET, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)
@ -802,6 +802,7 @@ IDTVEC(softnet)
IDTVEC(softclock)
movl $IPL_SOFTCLOCK, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)

View File

@ -1,4 +1,4 @@
/* $NetBSD: spl.S,v 1.10 2004/05/13 12:27:38 yamt Exp $ */
/* $NetBSD: spl.S,v 1.11 2004/06/28 09:13:12 fvdl Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -109,10 +109,8 @@ IDTVEC(spllower)
cli
andl CPUVAR(IPENDING),%eax # any non-masked bits left?
jz 2f
sti
bsrl %eax,%eax
btrl %eax,CPUVAR(IPENDING)
jnc 1b
movl CPUVAR(ISOURCES)(,%eax,4),%eax
jmp *IS_RECURSE(%eax)
2:
@ -143,10 +141,8 @@ IDTVEC(doreti)
cli
andl CPUVAR(IPENDING),%eax
jz 2f
sti
bsrl %eax,%eax # slow, but not worth optimizing
btrl %eax,CPUVAR(IPENDING)
jnc 1b # some intr cleared the in-memory bit
movl CPUVAR(ISOURCES)(,%eax, 4),%eax
jmp *IS_RESUME(%eax)
2: /* Check for ASTs on exit to user mode. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vector.S,v 1.14 2004/04/20 11:59:20 yamt Exp $ */
/* $NetBSD: vector.S,v 1.15 2004/06/28 09:13:12 fvdl Exp $ */
/*
* Copyright 2002 (c) Wasabi Systems, Inc.
@ -156,8 +156,6 @@ IDTVEC(recurse_lapic_ipi)
pushl $0
pushl $T_ASTFLT
INTRENTRY
IDTVEC(resume_lapic_ipi)
cli
jmp 1f
IDTVEC(intr_lapic_ipi)
pushl $0
@ -167,6 +165,7 @@ IDTVEC(intr_lapic_ipi)
movl CPUVAR(ILEVEL),%ebx
cmpl $IPL_IPI,%ebx
jae 2f
IDTVEC(resume_lapic_ipi)
1:
incl CPUVAR(IDEPTH)
movl $IPL_IPI,CPUVAR(ILEVEL)
@ -208,8 +207,6 @@ IDTVEC(recurse_lapic_ltimer)
pushl $0
pushl $T_ASTFLT
INTRENTRY
IDTVEC(resume_lapic_ltimer)
cli
jmp 1f
IDTVEC(intr_lapic_ltimer)
pushl $0
@ -219,6 +216,7 @@ IDTVEC(intr_lapic_ltimer)
movl CPUVAR(ILEVEL),%ebx
cmpl $IPL_CLOCK,%ebx
jae 2f
IDTVEC(resume_lapic_ltimer)
1:
incl CPUVAR(IDEPTH)
movl $IPL_CLOCK,CPUVAR(ILEVEL)
@ -624,6 +622,7 @@ _C_LABEL(eintrcnt):
IDTVEC(softserial)
movl $IPL_SOFTSERIAL, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)
@ -642,6 +641,7 @@ IDTVEC(softserial)
IDTVEC(softnet)
movl $IPL_SOFTNET, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)
@ -673,6 +673,7 @@ IDTVEC(softnet)
IDTVEC(softclock)
movl $IPL_SOFTCLOCK, CPUVAR(ILEVEL)
sti
incl CPUVAR(IDEPTH)
#ifdef MULTIPROCESSOR
call _C_LABEL(x86_softintlock)

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.12 2004/03/04 19:10:10 dbj Exp $ */
/* $NetBSD: intr.h,v 1.13 2004/06/28 09:13:12 fvdl Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@ -156,16 +156,21 @@ static __inline void
spllower(int nlevel)
{
struct cpu_info *ci = curcpu();
u_int32_t imask;
u_long psl;
__splbarrier();
/*
* Since this should only lower the interrupt level,
* the XOR below should only show interrupts that
* are being unmasked.
*/
ci->ci_ilevel = nlevel;
if (ci->ci_ipending & IUNMASK(ci,nlevel))
imask = IUNMASK(ci, nlevel);
psl = read_psl();
disable_intr();
if (ci->ci_ipending & imask) {
Xspllower(nlevel);
/* Xspllower does enable_intr() */
} else {
ci->ci_ilevel = nlevel;
write_psl(psl);
}
}
/*