Module Name:    src
Committed By:   thorpej
Date:           Sat Apr  3 14:56:14 UTC 2021

Modified Files:
        src/sys/arch/alpha/alpha: pmap.c
        src/sys/arch/alpha/include: lock.h
        src/sys/kern: kern_mutex.c

Log Message:
Fix an IPI deadlock scenario that resulted in a TLB shootdown timeout
panic reported by John Klos on port-alpha:

- pmap_tlb_shootnow(): If we acquire a pmap's activation lock, we will
  have raised the IPL on the current CPU to IPL_SCHED until we drop
  the tlb_lock (due to how nested spin mutexes work).  As such, when
  we release the activation lock, forcibly lower our IPL back to IPL_VM
  so that we can receive and process IPIs while waiting for other CPUs
  to process the shootdowns.
- mutex_vector_enter(): Invoke SPINLOCK_SPIN_HOOK while spinning to acquire
  a spin mutex.  This is a nop on most platforms, but it's important on
  the Alpha.  Without this, IPIs (and thus TLB shootdowns) cannot be
  processed if trying to acquire an IPL_SCHED spin mutex such as those
  used by the scheduler.

...and while we're poking around in here:

- Rework the Alpha SPINLOCK_SPIN_HOOK to only check curcpu()->ci_ipis
  if the current CPU's IPL is >= IPL_CLOCK (thus ensuring that preemption
  is disabled and thus guaranteeing that curcpu() is stable).  (Alpha does
  not yet support kernel preemption, but this is now one less thing that
  would need to be fixed.)


To generate a diff of this commit:
cvs rdiff -u -r1.274 -r1.275 src/sys/arch/alpha/alpha/pmap.c
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/alpha/include/lock.h
cvs rdiff -u -r1.96 -r1.97 src/sys/kern/kern_mutex.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/alpha/alpha/pmap.c
diff -u src/sys/arch/alpha/alpha/pmap.c:1.274 src/sys/arch/alpha/alpha/pmap.c:1.275
--- src/sys/arch/alpha/alpha/pmap.c:1.274	Tue Dec 29 17:16:15 2020
+++ src/sys/arch/alpha/alpha/pmap.c	Sat Apr  3 14:56:13 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.274 2020/12/29 17:16:15 thorpej Exp $ */
+/* $NetBSD: pmap.c,v 1.275 2021/04/03 14:56:13 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001, 2007, 2008, 2020
@@ -135,7 +135,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.274 2020/12/29 17:16:15 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.275 2021/04/03 14:56:13 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -962,6 +962,13 @@ pmap_tlb_shootnow(const struct pmap_tlb_
 	if (activation_locked) {
 		KASSERT(tlbctx->t_pmap != NULL);
 		PMAP_ACT_UNLOCK(tlbctx->t_pmap);
+		/*
+		 * When we acquired the activation lock, we
+		 * raised IPL to IPL_SCHED, which blocks out
+		 * IPIs.  Force our IPL back down to IPL_VM
+		 * so that we can receive IPIs.
+		 */
+		alpha_pal_swpipl(IPL_VM);
 	}
 
 	/*

Index: src/sys/arch/alpha/include/lock.h
diff -u src/sys/arch/alpha/include/lock.h:1.30 src/sys/arch/alpha/include/lock.h:1.31
--- src/sys/arch/alpha/include/lock.h:1.30	Fri Nov 29 20:05:07 2019
+++ src/sys/arch/alpha/include/lock.h	Sat Apr  3 14:56:13 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: lock.h,v 1.30 2019/11/29 20:05:07 riastradh Exp $ */
+/* $NetBSD: lock.h,v 1.31 2021/04/03 14:56:13 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -151,26 +151,27 @@ __cpu_simple_unlock(__cpu_simple_lock_t 
 #if defined(MULTIPROCESSOR)
 /*
  * On the Alpha, interprocessor interrupts come in at device priority
- * level.  This can cause some problems while waiting for r/w spinlocks
- * from a high'ish priority level: IPIs that come in will not be processed.
- * This can lead to deadlock.
+ * level (ALPHA_PSL_IPL_CLOCK).  This can cause some problems while
+ * waiting for spin locks from a high'ish priority level (like spin
+ * mutexes used by the scheduler): IPIs that come in will not be
+ * processed. This can lead to deadlock.
  *
- * This hook allows IPIs to be processed while a spinlock's interlock
- * is released.
+ * This hook allows IPIs to be processed while spinning.  Note we only
+ * do the special thing if IPIs are blocked (current IPL >= IPL_CLOCK).
+ * IPIs will be processed in the normal fashion otherwise, and checking
+ * this way ensures that preemption is disabled (i.e. curcpu() is stable).
  */
 #define	SPINLOCK_SPIN_HOOK						\
 do {									\
-	struct cpu_info *__ci = curcpu();				\
-	int __s;							\
+	unsigned long _ipl_ = alpha_pal_rdps() & ALPHA_PSL_IPL_MASK;	\
 									\
-	if (__ci->ci_ipis != 0) {					\
-		/* printf("CPU %lu has IPIs pending\n",			\
-		    __ci->ci_cpuid); */					\
-		__s = splhigh();						\
-		alpha_ipi_process(__ci, NULL);				\
-		splx(__s);						\
+	if (_ipl_ >= ALPHA_PSL_IPL_CLOCK) {				\
+		struct cpu_info *__ci = curcpu();			\
+		if (atomic_load_relaxed(&__ci->ci_ipis) != 0) {		\
+			alpha_ipi_process(__ci, NULL);			\
+		}							\
 	}								\
-} while (0)
+} while (/*CONSTCOND*/0)
 #define	SPINLOCK_BACKOFF_HOOK	(void)nullop((void *)0)
 #endif /* MULTIPROCESSOR */
 

Index: src/sys/kern/kern_mutex.c
diff -u src/sys/kern/kern_mutex.c:1.96 src/sys/kern/kern_mutex.c:1.97
--- src/sys/kern/kern_mutex.c:1.96	Tue Mar  2 01:15:15 2021
+++ src/sys/kern/kern_mutex.c	Sat Apr  3 14:56:14 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_mutex.c,v 1.96 2021/03/02 01:15:15 rin Exp $	*/
+/*	$NetBSD: kern_mutex.c,v 1.97 2021/04/03 14:56:14 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
 #define	__MUTEX_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.96 2021/03/02 01:15:15 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.97 2021/04/03 14:56:14 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -484,6 +484,7 @@ mutex_vector_enter(kmutex_t *mtx)
 		 */
 		do {
 			while (MUTEX_SPINBIT_LOCKED_P(mtx)) {
+				SPINLOCK_SPIN_HOOK;
 				SPINLOCK_BACKOFF(count);
 #ifdef LOCKDEBUG
 				if (SPINLOCK_SPINOUT(spins))

Reply via email to