1/* $OpenBSD: lcore_access.S,v 1.36 2023/12/12 07:37:21 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28#include <sys/errno.h> 29#include <sys/syscall.h> 30 31#include <machine/param.h> 32#include <machine/asm.h> 33#include <machine/cpu.h> 34#include <mips64/mips_cpu.h> 35#include <machine/regnum.h> 36#include <machine/cpustate.h> 37#include <machine/trap.h> 38 39#include "assym.h" 40 41 .set mips3 42 43 .set noreorder # Noreorder is default style! 44 45/* 46 * Primitives 47 */ 48 49/* 50 * This table is indexed by u.u_pcb.pcb_onfault in trap(). 51 * The reason for using this table rather than storing an address in 52 * u.u_pcb.pcb_onfault is simply to make the code faster. 53 * This table must match with definitions in trap.h. 54 */ 55 .globl onfault_table 56 .data 57 .align 3 58onfault_table: 59 PTR_VAL 0 # invalid index number 60 PTR_VAL _copyerr 61 PTR_VAL _kcopyerr 62#if defined(DDB) || defined(DEBUG) 63 PTR_VAL kt_ddberr 64#else 65 PTR_VAL 0 66#endif 67 .text 68 69/* 70 * This code is copied the user's stack for returning from signal handlers 71 * (see sendsig() and sigreturn()). We have to compute the address 72 * of the sigcontext struct for the sigreturn call. 73 */ 74 .globl sigcode 75sigcode: 76 PTR_ADDU a0, sp, 4*REGSZ # address of sigcontext 77 LI v0, SYS_sigreturn # sigreturn(scp) 78 .globl sigcodecall 79sigcodecall: 80 syscall 81 .globl sigcoderet 82sigcoderet: 83 .globl esigcode 84esigcode: 85 /* FALLTHROUGH */ 86 .globl sigfill 87sigfill: 88 teq zero, zero, 0x52 89esigfill: 90 91 .data 92 .globl sigfillsiz 93sigfillsiz: 94 .long esigfill - sigfill 95 96 .text 97 98/* 99 * Copy a null terminated string within the kernel address space. 100 * Maxlength may be null if count not wanted. 101 * copystr(fromaddr, toaddr, maxlength, &lencopied) 102 * caddr_t fromaddr; 103 * caddr_t toaddr; 104 * u_int maxlength; 105 * u_long *lencopied; 106 */ 107LEAF(copystr, 0) 108 beq a2, zero, 9f 109 move t2, a2 # Save the number of bytes 110 move v0, zero 1111: 112 lbu t0, 0(a0) 113 PTR_SUBU a2, a2, 1 114 sb t0, 0(a1) 115 PTR_ADDU a0, a0, 1 116 beq t0, zero, 2f 117 PTR_ADDU a1, a1, 1 118 bne a2, zero, 1b 119 NOP 1209: 121 LI v0, ENAMETOOLONG # String is longer than maxlength 1222: 123 beq a3, zero, 3f 124 PTR_SUBU a2, t2, a2 # Compute length copied 125 REG_S a2, 0(a3) 1263: 127 j ra 128 NOP 129END(copystr) 130 131/* 132 * Optimized memory zero code. 133 * mem_zero_page(addr); 134 */ 135LEAF(mem_zero_page, 0) 136 LI v0, PAGE_SIZE 1371: 138 PTR_SUBU v0, 8 139 sd zero, 0(a0) 140 bne zero, v0, 1b 141 PTR_ADDU a0, 8 142 jr ra 143 NOP 144END(mem_zero_page) 145 146/* 147 * Copy a null terminated string from the user address space into 148 * the kernel address space. 149 * 150 * _copyinstr(fromaddr, toaddr, maxlength, &lencopied) 151 * caddr_t fromaddr; 152 * caddr_t toaddr; 153 * u_int maxlength; 154 * u_int *lencopied; 155 */ 156NON_LEAF(_copyinstr, FRAMESZ(CF_SZ), ra) 157 PTR_SUBU sp, sp, FRAMESZ(CF_SZ) 158 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) 159 PTR_S ra, CF_RA_OFFS(sp) 160 blt a0, zero, _copyerr # make sure address is in user space 161 LI v0, KT_COPYERR 162 GET_CPU_INFO(t1, t0) 163 PTR_L t3, CI_CURPROCPADDR(t1) 164 jal copystr 165 sw v0, PCB_ONFAULT(t3) 166 167 PTR_L ra, CF_RA_OFFS(sp) 168 GET_CPU_INFO(t1, t0) 169 PTR_L t3, CI_CURPROCPADDR(t1) 170 sw zero, PCB_ONFAULT(t3) 171 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 172 j ra 173 NOP 174END(_copyinstr) 175 176/* 177 * Copy a null terminated string from the kernel address space into 178 * the user address space. 179 * 180 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 181 * caddr_t fromaddr; 182 * caddr_t toaddr; 183 * u_int maxlength; 184 * u_int *lencopied; 185 */ 186NON_LEAF(copyoutstr, FRAMESZ(CF_SZ), ra) 187 PTR_SUBU sp, sp, FRAMESZ(CF_SZ) 188 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) 189 PTR_S ra, CF_RA_OFFS(sp) 190 blt a1, zero, _copyerr # make sure address is in user space 191 LI v0, KT_COPYERR 192 GET_CPU_INFO(t1, t0) 193 PTR_L t3, CI_CURPROCPADDR(t1) 194 jal copystr 195 sw v0, PCB_ONFAULT(t3) 196 197 PTR_L ra, CF_RA_OFFS(sp) 198 GET_CPU_INFO(t1, t0) 199 PTR_L t3, CI_CURPROCPADDR(t1) 200 sw zero, PCB_ONFAULT(t3) 201 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 202 j ra 203 NOP 204END(copyoutstr) 205 206/* 207 * Copy specified amount of data from user space into the kernel 208 * _copyin(from, to, len) 209 * caddr_t *from; (user source address) 210 * caddr_t *to; (kernel destination address) 211 * unsigned len; 212 */ 213NON_LEAF(_copyin, FRAMESZ(CF_SZ), ra) 214 PTR_SUBU sp, sp, FRAMESZ(CF_SZ) 215 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) 216 PTR_S ra, CF_RA_OFFS(sp) 217 blt a0, zero, _copyerr # make sure address is in user space 218 li v0, KT_COPYERR 219 GET_CPU_INFO(t1, t0) 220 PTR_L t3, CI_CURPROCPADDR(t1) 221 jal bcopy 222 sw v0, PCB_ONFAULT(t3) 223 224 PTR_L ra, CF_RA_OFFS(sp) 225 GET_CPU_INFO(t1, t0) 226 PTR_L t3, CI_CURPROCPADDR(t1) 227 sw zero, PCB_ONFAULT(t3) 228 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 229 j ra 230 move v0, zero 231END(_copyin) 232 233/* 234 * Copy specified amount of data from kernel to the user space 235 * copyout(from, to, len) 236 * caddr_t *from; (kernel source address) 237 * caddr_t *to; (user destination address) 238 * unsigned len; 239 */ 240NON_LEAF(copyout, FRAMESZ(CF_SZ), ra) 241 PTR_SUBU sp, sp, FRAMESZ(CF_SZ) 242 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) 243 PTR_S ra, CF_RA_OFFS(sp) 244 blt a1, zero, _copyerr # make sure address is in user space 245 li v0, KT_COPYERR 246 GET_CPU_INFO(t1, t0) 247 PTR_L t3, CI_CURPROCPADDR(t1) 248 jal bcopy 249 sw v0, PCB_ONFAULT(t3) 250 251 PTR_L ra, CF_RA_OFFS(sp) 252 GET_CPU_INFO(t1, t0) 253 PTR_L t3, CI_CURPROCPADDR(t1) 254 sw zero, PCB_ONFAULT(t3) 255 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 256 j ra 257 move v0, zero 258END(copyout) 259 260/* 261 * Copy an aligned 32-bit word atomically from user space into the kernel 262 * copyin32(from, to) 263 * uint32_t *from; (user source address) 264 * uint32_t *to; (kernel destination address) 265 */ 266NON_LEAF(copyin32, FRAMESZ(CF_SZ), ra) 267 PTR_SUBU sp, sp, FRAMESZ(CF_SZ) 268 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) 269 PTR_S ra, CF_RA_OFFS(sp) 270 blt a0, zero, _copyerr # make sure address is in user space 271 li v0, KT_COPYERR 272 GET_CPU_INFO(t1, t0) 273 PTR_L t3, CI_CURPROCPADDR(t1) 274 sw v0, PCB_ONFAULT(t3) 275 276 lw v1, 0(a0) 277 sw v1, 0(a1) 278 279 sw zero, PCB_ONFAULT(t3) 280 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 281 j ra 282 move v0, zero 283END(copyin32) 284 285_copyerr: 286 PTR_L ra, CF_RA_OFFS(sp) 287 GET_CPU_INFO(t1, t0) 288 PTR_L t3, CI_CURPROCPADDR(t1) 289 sw zero, PCB_ONFAULT(t3) 290 PTR_ADDU sp, sp, FRAMESZ(CF_SZ) 291 j ra 292 li v0, EFAULT # return error 293 294/* 295 * kcopy is a wrapper around bcopy that catches bad memory references. 296 */ 297NON_LEAF(kcopy, FRAMESZ(CF_SZ + REGSZ), ra) 298 PTR_SUBU sp, sp, FRAMESZ(CF_SZ + REGSZ) 299 .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ + REGSZ)) 300 PTR_S ra, CF_RA_OFFS + REGSZ(sp) 301 GET_CPU_INFO(t1, t0) 302 PTR_L t3, CI_CURPROCPADDR(t1) 303 lw v1, PCB_ONFAULT(t3) 304 li v0, KT_KCOPYERR 305 PTR_S v1, CF_ARGSZ(sp) # save old pcb_onfault 306 jal bcopy 307 sw v0, PCB_ONFAULT(t3) 308 309 PTR_L v0, CF_ARGSZ(sp) 310 GET_CPU_INFO(t1, t0) 311 PTR_L t3, CI_CURPROCPADDR(t1) 312 PTR_L ra, CF_RA_OFFS + REGSZ(sp) 313 sw v0, PCB_ONFAULT(t3) 314 PTR_ADDU sp, sp, FRAMESZ(CF_SZ + REGSZ) 315 j ra 316 move v0, zero 317END(kcopy) 318 319_kcopyerr: 320 PTR_L v0, CF_ARGSZ(sp) 321 GET_CPU_INFO(t1, t0) 322 PTR_L t3, CI_CURPROCPADDR(t1) 323 PTR_L ra, CF_RA_OFFS + REGSZ(sp) 324 sw v0, PCB_ONFAULT(t3) 325 PTR_ADDU sp, sp, FRAMESZ(CF_SZ + REGSZ) 326 j ra 327 li v0, EFAULT # return error 328