From 029ca905663a72af60c92296a74f89fa612791ce Mon Sep 17 00:00:00 2001 From: fvdl Date: Mon, 28 Jun 2004 09:13:11 +0000 Subject: [PATCH] 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. --- sys/arch/amd64/amd64/spl.S | 6 +----- sys/arch/amd64/amd64/vector.S | 11 ++++++----- sys/arch/i386/i386/spl.S | 6 +----- sys/arch/i386/i386/vector.S | 11 ++++++----- sys/arch/x86/include/intr.h | 21 +++++++++++++-------- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/sys/arch/amd64/amd64/spl.S b/sys/arch/amd64/amd64/spl.S index 44ebb25e82e7..e8144c28a4f5 100644 --- a/sys/arch/amd64/amd64/spl.S +++ b/sys/arch/amd64/amd64/spl.S @@ -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. */ diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S index 3e6f2e2aab3f..96a56b1e4972 100644 --- a/sys/arch/amd64/amd64/vector.S +++ b/sys/arch/amd64/amd64/vector.S @@ -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) diff --git a/sys/arch/i386/i386/spl.S b/sys/arch/i386/i386/spl.S index b547fac27d5c..6f3c6efa92db 100644 --- a/sys/arch/i386/i386/spl.S +++ b/sys/arch/i386/i386/spl.S @@ -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. */ diff --git a/sys/arch/i386/i386/vector.S b/sys/arch/i386/i386/vector.S index 977581b3d2b8..0dfc281479e8 100644 --- a/sys/arch/i386/i386/vector.S +++ b/sys/arch/i386/i386/vector.S @@ -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) diff --git a/sys/arch/x86/include/intr.h b/sys/arch/x86/include/intr.h index f649860c7c1e..7ee2398820da 100644 --- a/sys/arch/x86/include/intr.h +++ b/sys/arch/x86/include/intr.h @@ -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); + } } /*