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",