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 get_vlenb, export=1 87 csrr a0, vlenb 88 ret 89endfunc 90 91function checked_call, export=1, ext=v 92 /* Save the function ptr, RA, SP, unallocatable and callee-saved registers */ 93 la.tls.ie t0, saved_regs 94 add t0, tp, t0 95 sd a0, (t0) 96 sd ra, 8(t0) 97 sd sp, 16(t0) 98 sd gp, 24(t0) 99 sd tp, 32(t0) 100.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 101 sd s\n, 40 + 16*\n(t0) 102#ifdef __riscv_float_abi_double 103 fsd fs\n, 48 + 16*\n(t0) 104#endif 105.endr 106 107 /* Check for vector extension */ 108 call dav1d_get_cpu_flags_riscv 109 and a0, a0, 1 # DAV1D_RISCV_CPU_FLAG_RVV 110 beqz a0, 0f 111 112 /* Clobber vector configuration */ 113 vsetvli t0, zero, e32, m8, ta, ma 114 lla t0, register_init 115 ld t0, (t0) 116.irp n, 0, 8, 16, 24 117 vmv.v.x v0, t0 118.endr 119 li t0, -1 << 31 120 vsetvl zero, zero, t0 121 csrwi vxrm, 3 122 csrwi vxsat, 1 123 1240: 125 /* Load the register arguments */ 126.irp n, 0, 1, 2, 3, 4, 5, 6, 7 127 ld a\n, 8*\n(sp) 128.endr 129 130 /* Load the stack arguments */ 131.irp n, 8, 9, 10, 11, 12, 13, 14, 15 132 ld t0, 8*\n(sp) 133 sd t0, 8*(\n - 8) - ARG_STACK(sp) 134.endr 135 136 /* Setup the stack canary */ 137 ld t0, MAX_ARGS*8(sp) 138 addi sp, sp, -ARG_STACK 139 slli t0, t0, 3 140 add t0, t0, sp 141 ld t0, (t0) 142 not t0, t0 143 sd t0, ARG_STACK - 8(sp) 144 145 /* Clobber the stack space right below SP */ 146 lla t0, register_init 147 ld t1, (t0) 148.rept 16 149 addi sp, sp, -16 150 sd t1, (sp) 151 sd t1, 8(sp) 152.endr 153 addi sp, sp, 16*16 154 155 /* Clobber the callee-saved and temporary registers */ 156.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 157.if (\n > 0 && \n < 7) 158 ld t\n, 16*\n(t0) 159.endif 160 ld s\n, 8 + 8*\n(t0) 161#ifdef __riscv_float_abi_double 162 fld ft\n, 16 + 16*\n(t0) 163 fld fs\n, 24 + 8*\n(t0) 164#endif 165.endr 166 167 /* Call the checked function */ 168 la.tls.ie t0, saved_regs 169 add t0, tp, t0 170 ld t0, (t0) 171 jalr t0 172 173 /* Check the value of callee-saved registers */ 174 lla t0, register_init 175.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 176 ld t1, 8 + 8*\n(t0) 177 li a1, \n 178 bne t1, s\n, 2f 179#ifdef __riscv_float_abi_double 180 ld t1, 24 + 8*\n(t0) 181 fmv.x.d t2, fs\n 182 bne t1, t2, 3f 183#endif 184.endr 185 186 /* Check unallocatable register values */ 187 la.tls.ie t0, saved_regs 188 add t0, tp, t0 189 ld t1, 16(t0) 190 addi t1, t1, -ARG_STACK 191 bne t1, sp, 4f 192 ld t1, 24(t0) 193 bne t1, gp, 4f 194 ld t1, 32(t0) 195 bne t1, tp, 4f 196 197 /* Check the stack canary */ 198 ld t0, ARG_STACK + MAX_ARGS*8(sp) 199 slli t0, t0, 3 200 add t0, t0, sp 201 ld t0, (t0) 202 not t0, t0 203 ld t1, ARG_STACK - 8(sp) 204 bne t0, t1, 5f 205 2061: 207 /* Restore RA, SP and callee-saved registers from thread local storage */ 208 la.tls.ie t0, saved_regs 209 add t0, tp, t0 210 ld ra, 8(t0) 211 ld sp, 16(t0) 212.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 213 ld s\n, 40 + 16*\n(t0) 214#ifdef __riscv_float_abi_double 215 fld fs\n, 48 + 16*\n(t0) 216#endif 217.endr 218 ret 219 2202: 221 lla a0, error_message_sreg 222#ifdef PREFIX 223 call _checkasm_fail_func 224#else 225 call checkasm_fail_func 226#endif 227 j 1b 228 229#ifdef __riscv_float_abi_double 2303: 231 lla a0, error_message_fsreg 232#ifdef PREFIX 233 call _checkasm_fail_func 234#else 235 call checkasm_fail_func 236#endif 237 j 1b 238#endif 239 2404: 241 lla a0, error_message_rsvd 242#ifdef PREFIX 243 call _checkasm_fail_func 244#else 245 call checkasm_fail_func 246#endif 247 j 1b 248 2495: 250 lla a0, error_message_stack 251#ifdef PREFIX 252 call _checkasm_fail_func 253#else 254 call checkasm_fail_func 255#endif 256 j 1b 257endfunc 258