1/****************************************************************************** 2 * Copyright © 2018, VideoLAN and dav1d authors 3 * Copyright © 2023, Nathan Egge 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 *****************************************************************************/ 27 28#define PRIVATE_PREFIX checkasm_ 29 30#include "src/riscv/asm.S" 31 32// max number of args used by any asm function. 33#define MAX_ARGS 15 34 35// + 16 for stack canary reference 36#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15 + 16) 37 38const register_init, align=4 39 .quad 0x68909d060f4a7fdd 40 .quad 0x924f739e310218a1 41 .quad 0xb988385a8254174c 42 .quad 0x4c1110430bf09fd7 43 .quad 0x2b310edf6a5d7ecf 44 .quad 0xda8112e98ddbb559 45 .quad 0x6da5854aa2f84b62 46 .quad 0x72b761199e9b1f38 47 .quad 0x13f27aa74ae5dcdf 48 .quad 0x36a6c12a7380e827 49 .quad 0x5c452889aefc8548 50 .quad 0x6a9ea1ddb236235f 51 .quad 0x0449854bdfc94b1e 52 .quad 0x4f849b7076a156f5 53 .quad 0x1baa4275e734930e 54 .quad 0x77df3503ba3e073d 55 .quad 0x6060e073705a4bf2 56 .quad 0xa7b482508471e44b 57 .quad 0xd296a3158d6da2b9 58 .quad 0x1c0ed711a93d970b 59 .quad 0x9359537fdd79569d 60 .quad 0x2b1dc95c1e232d62 61 .quad 0xab06cd578e2bb5a0 62 .quad 0x4100b4987a0af30f 63 .quad 0x2523e36f9bb1e36f 64 .quad 0xfb0b815930c6d25c 65 .quad 0x89acc810c2902fcf 66 .quad 0xa65854b4c2b381f1 67 .quad 0x78150d69a1accedf 68 .quad 0x057e24868e022de1 69 .quad 0x88f6e79ed4b8d362 70 .quad 0x1f4a420e262c9035 71endconst 72 73const error_message_register 74error_message_rsvd: 75 .asciz "unallocatable register clobbered" 76error_message_sreg: 77 .asciz "callee-saved integer register s%i modified" 78error_message_fsreg: 79 .asciz "callee-saved floating-point register fs%i modified" 80error_message_stack: 81 .asciz "stack clobbered" 82endconst 83 84thread_local saved_regs, quads=29 # 5 + 12 + 12 85 86function checked_call, export=1, ext=v 87 /* Save the function ptr, RA, SP, unallocatable and callee-saved registers */ 88 la.tls.ie t0, saved_regs 89 add t0, tp, t0 90 sd a0, (t0) 91 sd ra, 8(t0) 92 sd sp, 16(t0) 93 sd gp, 24(t0) 94 sd tp, 32(t0) 95.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 96 sd s\n, 40 + 16*\n(t0) 97#ifdef __riscv_float_abi_double 98 fsd fs\n, 48 + 16*\n(t0) 99#endif 100.endr 101 102 /* Check for vector extension */ 103 call dav1d_get_cpu_flags_riscv 104 and a0, a0, 1 # DAV1D_RISCV_CPU_FLAG_RVV 105 beqz a0, 0f 106 107 /* Clobber vector configuration */ 108 vsetvli t0, zero, e32, m8, ta, ma 109 lla t0, register_init 110 ld t0, (t0) 111.irp n, 0, 8, 16, 24 112 vmv.v.x v0, t0 113.endr 114 li t0, -1 << 31 115 vsetvl zero, zero, t0 116 csrwi vxrm, 3 117 csrwi vxsat, 1 118 1190: 120 /* Load the register arguments */ 121.irp n, 0, 1, 2, 3, 4, 5, 6, 7 122 ld a\n, 8*\n(sp) 123.endr 124 125 /* Load the stack arguments */ 126.irp n, 8, 9, 10, 11, 12, 13, 14, 15 127 ld t0, 8*\n(sp) 128 sd t0, 8*(\n - 8) - ARG_STACK(sp) 129.endr 130 131 /* Setup the stack canary */ 132 ld t0, MAX_ARGS*8(sp) 133 addi sp, sp, -ARG_STACK 134 slli t0, t0, 3 135 add t0, t0, sp 136 ld t0, (t0) 137 not t0, t0 138 sd t0, ARG_STACK - 8(sp) 139 140 /* Clobber the stack space right below SP */ 141 lla t0, register_init 142 ld t1, (t0) 143.rept 16 144 addi sp, sp, -16 145 sd t1, (sp) 146 sd t1, 8(sp) 147.endr 148 addi sp, sp, 16*16 149 150 /* Clobber the callee-saved and temporary registers */ 151.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 152.if (\n > 0 && \n < 7) 153 ld t\n, 16*\n(t0) 154.endif 155 ld s\n, 8 + 8*\n(t0) 156#ifdef __riscv_float_abi_double 157 fld ft\n, 16 + 16*\n(t0) 158 fld fs\n, 24 + 8*\n(t0) 159#endif 160.endr 161 162 /* Call the checked function */ 163 la.tls.ie t0, saved_regs 164 add t0, tp, t0 165 ld t0, (t0) 166 jalr t0 167 168 /* Check the value of callee-saved registers */ 169 lla t0, register_init 170.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 171 ld t1, 8 + 8*\n(t0) 172 li a1, \n 173 bne t1, s\n, 2f 174#ifdef __riscv_float_abi_double 175 ld t1, 24 + 8*\n(t0) 176 fmv.x.d t2, fs\n 177 bne t1, t2, 3f 178#endif 179.endr 180 181 /* Check unallocatable register values */ 182 la.tls.ie t0, saved_regs 183 add t0, tp, t0 184 ld t1, 16(t0) 185 addi t1, t1, -ARG_STACK 186 bne t1, sp, 4f 187 ld t1, 24(t0) 188 bne t1, gp, 4f 189 ld t1, 32(t0) 190 bne t1, tp, 4f 191 192 /* Check the stack canary */ 193 ld t0, ARG_STACK + MAX_ARGS*8(sp) 194 slli t0, t0, 3 195 add t0, t0, sp 196 ld t0, (t0) 197 not t0, t0 198 ld t1, ARG_STACK - 8(sp) 199 bne t0, t1, 5f 200 2011: 202 /* Restore RA, SP and callee-saved registers from thread local storage */ 203 la.tls.ie t0, saved_regs 204 add t0, tp, t0 205 ld ra, 8(t0) 206 ld sp, 16(t0) 207.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 208 ld s\n, 40 + 16*\n(t0) 209#ifdef __riscv_float_abi_double 210 fld fs\n, 48 + 16*\n(t0) 211#endif 212.endr 213 ret 214 2152: 216 lla a0, error_message_sreg 217#ifdef PREFIX 218 call _checkasm_fail_func 219#else 220 call checkasm_fail_func 221#endif 222 j 1b 223 224#ifdef __riscv_float_abi_double 2253: 226 lla a0, error_message_fsreg 227#ifdef PREFIX 228 call _checkasm_fail_func 229#else 230 call checkasm_fail_func 231#endif 232 j 1b 233#endif 234 2354: 236 lla a0, error_message_rsvd 237#ifdef PREFIX 238 call _checkasm_fail_func 239#else 240 call checkasm_fail_func 241#endif 242 j 1b 243 2445: 245 lla a0, error_message_stack 246#ifdef PREFIX 247 call _checkasm_fail_func 248#else 249 call checkasm_fail_func 250#endif 251 j 1b 252endfunc 253