1/*- 2 * Copyright (c) 2024 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Nick Hudson 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <machine/asm.h> 31#include "assym.h" 32 33#define UCAS_FRAME_SIZE (FB_LEN + 4 * SZREG) 34#define UCAS_FRAME_A0 (UCAS_FRAME_SIZE - 4 * SZREG) 35#define UCAS_FRAME_A1 (UCAS_FRAME_SIZE - 3 * SZREG) 36#define UCAS_FRAME_S0 (UCAS_FRAME_SIZE - 2 * SZREG) 37#define UCAS_FRAME_RA (UCAS_FRAME_SIZE - 1 * SZREG) 38 39.macro enter_ucas 40 addi sp, sp, -UCAS_FRAME_SIZE 41 REG_S a0, UCAS_FRAME_A0(sp) 42 REG_S a1, UCAS_FRAME_A1(sp) 43 REG_S s0, UCAS_FRAME_S0(sp) 44 REG_S ra, UCAS_FRAME_RA(sp) 45 addi s0, sp, UCAS_FRAME_SIZE 46.endm 47 48.macro exit_ucas 49 REG_L s0, UCAS_FRAME_S0(sp) 50 REG_L ra, UCAS_FRAME_RA(sp) 51 addi sp, sp, UCAS_FRAME_SIZE 52.endm 53 54.macro enter_cpu_onfault 55 // error = cpu_set_onfault(&fb, EFAULT); 56 mv a0, sp 57 li a1, EFAULT 58 call cpu_set_onfault 59 // if (error) goto fail; 60 bnez a0, 9f 61.endm 62 63.macro exit_cpu_onfault 64 // curlwp->l_md.md_onfault = NULL; 65 REG_S zero, L_MD_ONFAULT(tp) 66.endm 67 68.macro set_sum 69 // csr_sstatus_set(SR_SUM); 70 li t1, SR_SUM 71 csrs sstatus, t1 72.endm 73 74.macro clear_sum 75 // csr_sstatus_clear(SR_SUM); 76 li t1, SR_SUM 77 csrc sstatus, t1 78.endm 79 80 81/* 82 * int _ucas_32(volatile uint32_t *ptr, uint32_t old, 83 * uint32_t new, uint32_t *ret) 84 * 85 * Implies release/acquire barriers until someone tells me 86 * otherwise about _ucas_32/64. 87 */ 88ENTRY(_ucas_32) 89 li t0, (VM_MAXUSER_ADDRESS - 4) 90 bltu t0, a0, 3f 91 92 enter_ucas 93 94 enter_cpu_onfault 95 96 REG_L t0, UCAS_FRAME_A0(sp) 97 REG_L a1, UCAS_FRAME_A1(sp) 98 99 set_sum 100 1011: lr.w a0, 0(t0) /* load old value */ 102 bne a0, a1, 2f /* return if different */ 103 sc.w t1, a2, 0(t0) /* store new value */ 104 bnez t1, 1b /* succeed? nope, try again. */ 1052: 106 clear_sum 107 108 sw a0, 0(a3) 109 110 exit_cpu_onfault 111 li a0, 0 // success 1129: 113 exit_ucas 114 ret 1153: 116 li a0, EFAULT 117 ret 118END(_ucas_32) 119 120 121#ifdef _LP64 122/* 123 * int _ucas_64(volatile uint64_t *ptr, uint64_t old, 124 * uint64_t new, uint64_t *ret) 125 * 126 * Implies release/acquire barriers until someone tells me 127 * otherwise about _ucas_32/64. 128 */ 129ENTRY(_ucas_64) 130 li t0, (VM_MAXUSER_ADDRESS - 8) 131 bltu t0, a0, 3f 132 133 enter_ucas 134 135 enter_cpu_onfault 136 137 REG_L t0, (FB_LEN + 0 * SZREG)(sp) 138 REG_L a1, (FB_LEN + 1 * SZREG)(sp) 139 140 set_sum 141 1421: lr.d a0, 0(t0) /* load old value */ 143 bne a1, a0, 2f /* return if different */ 144 sc.d t1, a2, 0(t0) /* store new value */ 145 bnez t1, 1b /* succeed? nope, try again. */ 1462: 147 clear_sum 148 149 sd a0, 0(a3) 150 151 exit_cpu_onfault 152 li a0, 0 // success 1539: 154 exit_ucas 155 ret 1563: 157 li a0, EFAULT 158 ret 159END(_ucas_64) 160#endif 161