Module Name:    src
Committed By:   matt
Date:           Sat Nov 13 02:23:27 UTC 2010

Modified Files:
        src/sys/arch/vax/include: cpu.h trap.h
        src/sys/arch/vax/vax: genassym.cf lock_stubs.S trap.c

Log Message:
Implement CAS using a RAS for non-MP VAX systems.  This technique uses the
atomicity of indirect addressing for correctness.  It also uses the knowledge
of dereferencing an address outside the page table length will cause a PTELEN
trap.  [Tested on netbsd-5]


To generate a diff of this commit:
cvs rdiff -u -r1.89 -r1.90 src/sys/arch/vax/include/cpu.h
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/vax/include/trap.h
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/vax/vax/genassym.cf
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/vax/vax/lock_stubs.S
cvs rdiff -u -r1.124 -r1.125 src/sys/arch/vax/vax/trap.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/vax/include/cpu.h
diff -u src/sys/arch/vax/include/cpu.h:1.89 src/sys/arch/vax/include/cpu.h:1.90
--- src/sys/arch/vax/include/cpu.h:1.89	Thu Jul  1 19:50:12 2010
+++ src/sys/arch/vax/include/cpu.h	Sat Nov 13 02:23:27 2010
@@ -1,4 +1,4 @@
-/*      $NetBSD: cpu.h,v 1.89 2010/07/01 19:50:12 ragge Exp $      */
+/*      $NetBSD: cpu.h,v 1.90 2010/11/13 02:23:27 matt Exp $      */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden
@@ -145,6 +145,7 @@
 	struct trapframe *ci_ddb_regs;	/* Used by DDB */
 	SIMPLEQ_ENTRY(cpu_info) ci_next; /* next cpu_info */
 #endif
+	uintptr_t ci_cas_addr;		/* current address doing CAS in a RAS */
 };
 #define	CI_MASTERCPU	1		/* Set if master CPU */
 #define	CI_RUNNING	2		/* Set when a slave CPU is running */

Index: src/sys/arch/vax/include/trap.h
diff -u src/sys/arch/vax/include/trap.h:1.22 src/sys/arch/vax/include/trap.h:1.23
--- src/sys/arch/vax/include/trap.h:1.22	Mon Feb 16 23:55:31 2009
+++ src/sys/arch/vax/include/trap.h	Sat Nov 13 02:23:27 2010
@@ -1,4 +1,4 @@
-/*      $NetBSD: trap.h,v 1.22 2009/02/16 23:55:31 christos Exp $     */
+/*      $NetBSD: trap.h,v 1.23 2010/11/13 02:23:27 matt Exp $     */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -73,6 +73,9 @@
 #define	AFLT_FLTDIV	0x9	/* floating divide-by-zero */
 #define	AFLT_FLTUND	0xa	/* floating underflow */
 
+/* Used by RAS to detect an interrupted CAS */
+#define	CASMAGIC	0xBEDABABE /* high end of S0 space */
+
 /* Trap's coming from user mode */
 #define	T_USER	0x100
 

Index: src/sys/arch/vax/vax/genassym.cf
diff -u src/sys/arch/vax/vax/genassym.cf:1.46 src/sys/arch/vax/vax/genassym.cf:1.47
--- src/sys/arch/vax/vax/genassym.cf:1.46	Wed May 12 14:43:48 2010
+++ src/sys/arch/vax/vax/genassym.cf	Sat Nov 13 02:23:27 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.46 2010/05/12 14:43:48 matt Exp $
+#	$NetBSD: genassym.cf,v 1.47 2010/11/13 02:23:27 matt Exp $
 #
 # Copyright (c) 1997 Ludd, University of Lule}, Sweden.
 # All rights reserved.
@@ -99,6 +99,7 @@
 define	CI_MTX_COUNT	offsetof(struct cpu_info, ci_mtx_count)
 define	CI_MTX_OLDSPL	offsetof(struct cpu_info, ci_mtx_oldspl)
 define	CI_SOFTLWPS	offsetof(struct cpu_info, ci_softlwps)
+define	CI_CAS_ADDR	offsetof(struct cpu_info, ci_cas_addr)
 
 # mtpr register numbers
 define	PR_KSP		PR_KSP
@@ -135,6 +136,8 @@
 define	T_ASTFLT	T_ASTFLT
 define	T_KDBTRAP	T_KDBTRAP
 
+define	CASMAGIC	CASMAGIC
+
 define	USPACE		USPACE
 define	TRAPFRAMELEN	sizeof(struct trapframe)
 define	CALLSFRAMELEN	sizeof(struct callsframe)

Index: src/sys/arch/vax/vax/lock_stubs.S
diff -u src/sys/arch/vax/vax/lock_stubs.S:1.16 src/sys/arch/vax/vax/lock_stubs.S:1.17
--- src/sys/arch/vax/vax/lock_stubs.S:1.16	Thu Jul  1 19:50:12 2010
+++ src/sys/arch/vax/vax/lock_stubs.S	Sat Nov 13 02:23:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: lock_stubs.S,v 1.16 2010/07/01 19:50:12 ragge Exp $	*/
+/*	$NetBSD: lock_stubs.S,v 1.17 2010/11/13 02:23:27 matt Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc.
@@ -61,6 +61,9 @@
 #endif
 	clrl	%r2			/* set old value (zero) */
 	mfpr	$PR_SSP, %r3		/* set new value (curlwp) */
+#ifndef MULTIPROCESSOR
+	addl3	$CI_CAS_ADDR, L_CPU(%r3), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bsbw	_do_cas+2		/* do the compare-and-swap */
 	tstl	%r0			/* is the old value what we wanted? */
 	beql	2f			/*  yep, just branch to the return */
@@ -78,6 +81,9 @@
 #endif
 	mfpr	$PR_SSP, %r2		/* get curlwp (old) */
 	clrl	%r3			/* get zero (new) */
+#ifndef MULTIPROCESSOR
+	addl3	$CI_CAS_ADDR, L_CPU(%r2), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bsbw	_do_cas+2		/* do the compare-and-swap */
 	cmpl	%r0,%r2			/* return == old? */
 	beql	2f			/*   yes, branch to return */
@@ -160,6 +166,10 @@
 						/* write active or pending? */
 	bneq	3f				/*   yep, go slow */
 	addl3	$RW_READ_INCR, %r2, %r3		/* incr. reader count (new) */
+#ifndef MULTIPROCESSOR
+	mfpr	$PR_SSP, %r4
+	addl3	$CI_CAS_ADDR, L_CPU(%r4), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 1:	bsbw	_do_cas+2			/* do the compare-and-swap */
 	cmpl	%r0, %r2			/* did it succeed? */
 	bneq	3f				/*   nope, go slow */
@@ -167,6 +177,9 @@
 
 2:	clrl	%r2				/* get old value (zero) */
 	mfpr	$PR_SSP, %r3			/* get new value (curlwp) */
+#ifndef MULTIPROCESSOR
+	addl3	$CI_CAS_ADDR, L_CPU(%r3), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bisl2	$RW_WRITE_LOCKED, %r3		/* show that it's a write */
 	brb	1b				/* do the compare-and-swap */
 
@@ -185,12 +198,19 @@
 	blbs	%r2, 3f				/* RW_HAS_WAITERS mbz */
 	subl3	$RW_READ_INCR, %r2, %r3		/* decr. reader count (new) */
 	blss	3f				/* if less then 0, go slow */
+#ifndef MULTIPROCESSOR
+	mfpr	$PR_SSP, %r4			/* get curlwp */
+	addl3	$CI_CAS_ADDR, L_CPU(%r4), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 1:	bsbw	_do_cas+2			/* do the compare-and-swap */
 	cmpl	%r0, %r2			/* did it succeed? */
 	bneq	3f				/*   nope, go slow */
 	ret					/*   yes, return */
 
 2:	mfpr	$PR_SSP, %r2			/* get old (curlwp) */
+#ifndef MULTIPROCESSOR
+	addl3	$CI_CAS_ADDR, L_CPU(%r2), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bisl2	$RW_WRITE_LOCKED, %r2		/* show that it's a write */
 	clrl	%r3				/* get new (zero) */
 	brb	1b				/* do the compare-and-swap */
@@ -211,6 +231,10 @@
 						/* write active or pending? */
 	bneq	2f				/*   yes, return failure */
 	addl3	$RW_READ_INCR, %r2, %r3		/* incr reader count (new) */
+#ifndef MULTIPROCESSOR
+	mfpr	$PR_SSP, %r4
+	addl3	$CI_CAS_ADDR, L_CPU(%r4), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 1:	bsbw	_do_cas+2			/* do the compare-and-swap */
 	cmpl	%r0, %r2			/* did it succeed? */
 	bneq	2f				/*   no, we failed. */
@@ -221,6 +245,9 @@
 
 3:	clrl	%r2				/* set old value (0) */
 	mfpr	$PR_SSP, %r3			/* set new value (curlwp) */
+#ifndef MULTIPROCESSOR
+	addl3	$CI_CAS_ADDR, L_CPU(%r3), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bisl2	$RW_WRITE_LOCKED, %r3		/* show that it's a write */
 	brb	1b				/* do the compare-and-swap */
 #endif /* LOCKDEBUG */
@@ -231,6 +258,10 @@
 ENTRY(_atomic_cas_32, 0)
 	movq	4(%ap), %r1		/* cache ptr, old */
 	movl	12(%ap), %r3		/* cache new */
+#ifndef MULTIPROCESSOR
+	mfpr	$PR_SSP, %r4
+	addl3	$CI_CAS_ADDR, L_CPU(%r4), %r4 /* r4 == &curcpu()->ci_cas_addr */
+#endif
 	bsbw	_do_cas+2		/* do it */
 	ret
 
@@ -257,15 +288,28 @@
 4:
 	rsb				/* return */
 #else
-	mfpr	$PR_IPL, %r5		/* save IPL */
-	mtpr	$IPL_SCHED, $PR_IPL	/* block interrupts */
-	movl	(%r1), %r0		/* get current value */
-	cmpl	%r2, %r0		/* does it equal old value? */
-	bneq	1f			/*   no, don't update */
-	movl	%r3, (%r1)		/* yes, update */
-1:	mtpr	%r5, $PR_IPL		/* drop/restore IPL */
-	rsb				/* return */
-#endif
+/*
+ * entry:
+ *	r1 = address to be CAS'ed
+ *	r2 = old value
+ *	r3 = new value
+ *	r4 = global cell to hold CAS address (common to all callers)
+ *	     e.g. address of curcpu()->ci_cas_addr
+ * exit:
+ *	r0 = old value
+ */
+	.globl	cas32_ras_start, cas32_ras_end
+cas32_ras_start:
+	movl	%r1, (%r4)
+	movl	*(%r4), %r0
+	cmpl	%r2, %r0
+	bneq	1f
+	movl	%r3, *(%r4)
+cas32_ras_end:
+1:
+	movl	$CASMAGIC, (%r4)
+	rsb
+#endif /* !MULTIPROCESSOR */
 STRONG_ALIAS(atomic_cas_ptr,_atomic_cas_32)
 STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32)
 STRONG_ALIAS(atomic_cas_uint,_atomic_cas_32)

Index: src/sys/arch/vax/vax/trap.c
diff -u src/sys/arch/vax/vax/trap.c:1.124 src/sys/arch/vax/vax/trap.c:1.125
--- src/sys/arch/vax/vax/trap.c:1.124	Fri Apr 23 19:18:10 2010
+++ src/sys/arch/vax/vax/trap.c	Sat Nov 13 02:23:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.124 2010/04/23 19:18:10 rmind Exp $     */
+/*	$NetBSD: trap.c,v 1.125 2010/11/13 02:23:27 matt Exp $     */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -33,7 +33,7 @@
  /* All bugs are subject to removal without further notice */
 		
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.124 2010/04/23 19:18:10 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.125 2010/11/13 02:23:27 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -179,6 +179,25 @@
 		}
 
 	case T_PTELEN:
+#ifndef MULTIPROCESSOR
+		/*
+		 * If we referred to an address beyond the end of the system
+		 * page table, it may be due to a failed CAS
+		 * restartable-atomic-sequence.  If it is, restart it at the
+		 * beginning and restart.
+		 */
+		{
+			extern const uint8_t cas32_ras_start[], cas32_ras_end[];
+			if (frame->code == CASMAGIC
+			    && frame->pc >= (uintptr_t) cas32_ras_start
+			    && frame->pc < (uintptr_t) cas32_ras_end) {
+				frame->pc = (uintptr_t) cas32_ras_start;
+				trapsig = false;
+				break;
+			}
+		}
+		/* FALLTHROUGH */
+#endif
 	case T_ACCFLT:
 #ifdef TRAPDEBUG
 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",

Reply via email to