Module Name: src Committed By: thorpej Date: Tue Jul 13 01:59:10 UTC 2021
Modified Files: src/sys/arch/alpha/alpha: lock_stubs.s patch.c Log Message: As with membar_producer() and membar_sync(), initialize the fast-path lock stubs with "unop" isns where memory barriers need to be, and if we detect a multiprocessor system, patch those locations with "mb" insns. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/alpha/alpha/lock_stubs.s \ src/sys/arch/alpha/alpha/patch.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/lock_stubs.s diff -u src/sys/arch/alpha/alpha/lock_stubs.s:1.6 src/sys/arch/alpha/alpha/lock_stubs.s:1.7 --- src/sys/arch/alpha/alpha/lock_stubs.s:1.6 Mon Jul 12 15:21:51 2021 +++ src/sys/arch/alpha/alpha/lock_stubs.s Tue Jul 13 01:59:10 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: lock_stubs.s,v 1.6 2021/07/12 15:21:51 thorpej Exp $ */ +/* $NetBSD: lock_stubs.s,v 1.7 2021/07/13 01:59:10 thorpej Exp $ */ /*- * Copyright (c) 2007, 2021 The NetBSD Foundation, Inc. @@ -34,12 +34,16 @@ #include <machine/asm.h> -__KERNEL_RCSID(0, "$NetBSD: lock_stubs.s,v 1.6 2021/07/12 15:21:51 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lock_stubs.s,v 1.7 2021/07/13 01:59:10 thorpej Exp $"); #include "assym.h" #if defined(MULTIPROCESSOR) -#define MB mb +/* + * These 'unop' insns will be patched with 'mb' insns at run-time if + * the system has more than one processor. + */ +#define MB(label) label: unop #else #define MB /* nothing */ #endif @@ -55,11 +59,11 @@ LEAF(_lock_cas, 3) beq t1, 2f stq_c v0, 0(a0) beq v0, 3f - MB + MB(.L__lock_cas_mb_1) RET 2: mov zero, v0 - MB + MB(.L__lock_cas_mb_2) RET 3: br 1b @@ -79,7 +83,7 @@ LEAF(mutex_enter, 1) bne t2, 2f stq_c t1, 0(a0) beq t1, 3f - MB + MB(.L_mutex_enter_mb_1) RET 2: lda t12, mutex_vector_enter @@ -93,7 +97,7 @@ LEAF(mutex_enter, 1) */ LEAF(mutex_exit, 1) LDGP(pv) - MB + MB(.L_mutex_exit_mb_1) GET_CURLWP /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ mov zero, t3 1: @@ -179,7 +183,7 @@ LEAF(mutex_spin_enter, 1); bne t0, 2f /* contended */ stl_c t1, MUTEX_SIMPLELOCK(a1) beq t1, 2f /* STL_C failed; consider contended */ - MB + MB(.L_mutex_spin_enter_mb_1) RET 2: mov a1, a0 /* restore first argument */ @@ -192,7 +196,7 @@ LEAF(mutex_spin_enter, 1); */ LEAF(mutex_spin_exit, 1) LDGP(pv); - MB + MB(.L_mutex_spin_exit_mb_1) /* * STEP 1: __cpu_simple_unlock(&mtx->mtx_lock) @@ -247,7 +251,7 @@ LEAF(rw_enter, 2) bne t1, 4f /* contended */ stq_c t2, 0(a0) beq t2, 2f /* STQ_C failed; retry */ - MB + MB(.L_rw_enter_mb_1) RET 2: br 1b @@ -259,7 +263,7 @@ LEAF(rw_enter, 2) bne t0, 4f /* contended */ stq_c t2, 0(a0) beq t2, 4f /* STQ_C failed; consider it contended */ - MB + MB(.L_rw_enter_mb_2) RET 4: lda pv, rw_vector_enter @@ -284,7 +288,7 @@ LEAF(rw_tryenter, 2) bne t1, 4f /* contended */ stq_c v0, 0(a0) beq v0, 2f /* STQ_C failed; retry */ - MB + MB(.L_rw_tryenter_mb_1) RET /* v0 contains non-zero LOCK_FLAG from STQ_C */ 2: br 1b @@ -302,7 +306,7 @@ LEAF(rw_tryenter, 2) * in the failure case because we expect it to be rare and it saves * a branch-not-taken instruction in the success case. */ - MB + MB(.L_rw_tryenter_mb_2) RET 4: mov zero, v0 /* return 0 (failure) */ @@ -316,7 +320,7 @@ LEAF(rw_tryenter, 2) */ LEAF(rw_exit, 1) LDGP(pv) - MB + MB(.L_rw_exit_mb_1) /* * Check for write-lock release, and get the owner/count field @@ -381,3 +385,27 @@ LEAF(rw_exit, 1) END(rw_exit) #endif /* !LOCKDEBUG */ + +#if defined(MULTIPROCESSOR) +/* + * Table of locations to patch with MB instructions on multiprocessor + * systems. + */ + .section ".rodata" + .globl lock_stub_patch_table +lock_stub_patch_table: + .quad .L__lock_cas_mb_1 + .quad .L__lock_cas_mb_2 +#if !defined(LOCKDEBUG) + .quad .L_mutex_enter_mb_1 + .quad .L_mutex_exit_mb_1 + .quad .L_mutex_spin_enter_mb_1 + .quad .L_mutex_spin_exit_mb_1 + .quad .L_rw_enter_mb_1 + .quad .L_rw_enter_mb_2 + .quad .L_rw_tryenter_mb_1 + .quad .L_rw_tryenter_mb_2 + .quad .L_rw_exit_mb_1 +#endif /* ! LOCKDEBUG */ + .quad 0 /* NULL terminator */ +#endif /* MULTIPROCESSOR */ Index: src/sys/arch/alpha/alpha/patch.c diff -u src/sys/arch/alpha/alpha/patch.c:1.6 src/sys/arch/alpha/alpha/patch.c:1.7 --- src/sys/arch/alpha/alpha/patch.c:1.6 Wed Jul 7 03:30:35 2021 +++ src/sys/arch/alpha/alpha/patch.c Tue Jul 13 01:59:10 2021 @@ -1,7 +1,7 @@ -/* $NetBSD: patch.c,v 1.6 2021/07/07 03:30:35 thorpej Exp $ */ +/* $NetBSD: patch.c,v 1.7 2021/07/13 01:59:10 thorpej Exp $ */ /*- - * Copyright (c) 2007 The NetBSD Foundation, Inc. + * Copyright (c) 2007, 2021 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.6 2021/07/07 03:30:35 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.7 2021/07/13 01:59:10 thorpej Exp $"); #include "opt_multiprocessor.h" @@ -47,6 +47,8 @@ __KERNEL_RCSID(0, "$NetBSD: patch.c,v 1. #include <machine/alpha.h> #include <machine/intr.h> +#include <alpha/alpha/db_instruction.h> + void _membar_producer(void); void _membar_producer_end(void); void _membar_producer_mp(void); @@ -60,7 +62,32 @@ void _membar_sync_mp_end(void); extern char alpha_copystr_bwx[], alpha_copystr_bwx_end[]; extern char alpha_copystr[], alpha_copystr_end[]; -static void __attribute__((__unused__)) +#if defined(MULTIPROCESSOR) +extern uint32_t *lock_stub_patch_table[]; + +static void +patch_lock_stubs(void) +{ + alpha_instruction insn = { + .mem_format = { + .opcode = op_special, + .displacement = op_mb, + }, + }; + int i, s; + + s = splhigh(); + + for (i = 0; lock_stub_patch_table[i] != NULL; i++) { + *lock_stub_patch_table[i] = insn.bits; + } + alpha_pal_imb(); + + splx(s); +} +#endif /* MULTIPROCESSOR */ + +static void patchfunc(void *from_s, void *from_e, void *to_s, void *to_e) { int s; @@ -98,6 +125,8 @@ alpha_patch(bool is_mp) KASSERT(curcpu()->ci_flags & CPUF_PRIMARY); KASSERT((cpus_running & ~(1UL << cpu_number())) == 0); + patch_lock_stubs(); + patchfunc(_membar_producer_mp, _membar_producer_mp_end, _membar_producer, _membar_producer_end); patchfunc(_membar_sync_mp, _membar_sync_mp_end,