1 /* $NetBSD: syscall.c,v 1.69 2023/10/05 19:41:03 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1994-1998 Mark Brinicombe. 34 * Copyright (c) 1994 Brini. 35 * All rights reserved. 36 * 37 * This code is derived from software written for Brini by Mark Brinicombe 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by Mark Brinicombe 50 * for the NetBSD Project. 51 * 4. The name of the company nor the name of the author may be used to 52 * endorse or promote products derived from this software without specific 53 * prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 56 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 57 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 58 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 59 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 60 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 * 67 * syscall entry handling 68 * 69 * Created : 09/11/94 70 */ 71 72 #include <sys/param.h> 73 74 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.69 2023/10/05 19:41:03 ad Exp $"); 75 76 #include <sys/cpu.h> 77 #include <sys/device.h> 78 #include <sys/errno.h> 79 #include <sys/kernel.h> 80 #include <sys/reboot.h> 81 #include <sys/signalvar.h> 82 #include <sys/syscall.h> 83 #include <sys/syscallvar.h> 84 #include <sys/systm.h> 85 #include <sys/ktrace.h> 86 87 #include <uvm/uvm_extern.h> 88 89 #include <machine/frame.h> 90 #include <arm/swi.h> 91 #include <arm/locore.h> 92 93 void 94 swi_handler(trapframe_t *tf) 95 { 96 lwp_t * const l = curlwp; 97 uint32_t insn; 98 99 /* 100 * Enable interrupts if they were enabled before the exception. 101 * Since all syscalls *should* come from user mode it will always 102 * be safe to enable them, but check anyway. 103 */ 104 KASSERT(VALID_PSR(tf->tf_spsr)); 105 restore_interrupts(tf->tf_spsr & IF32_bits); 106 107 #ifndef THUMB_CODE 108 /* 109 * Make sure the program counter is correctly aligned so we 110 * don't take an alignment fault trying to read the opcode. 111 */ 112 if (__predict_false(((tf->tf_pc - INSN_SIZE) & 3) != 0)) { 113 ksiginfo_t ksi; 114 /* Give the user an illegal instruction signal. */ 115 KSI_INIT_TRAP(&ksi); 116 ksi.ksi_signo = SIGILL; 117 ksi.ksi_code = ILL_ILLOPC; 118 ksi.ksi_addr = (uint32_t *)(intptr_t) (tf->tf_pc-INSN_SIZE); 119 #if 0 120 /* maybe one day we'll do emulations */ 121 (*l->l_proc->p_emul->e_trapsignal)(l, &ksi); 122 #else 123 trapsignal(l, &ksi); 124 #endif 125 userret(l); 126 return; 127 } 128 #endif 129 130 #ifdef THUMB_CODE 131 if (tf->tf_spsr & PSR_T_bit) { 132 insn = 0xef000000 | SWI_OS_NETBSD | tf->tf_r0; 133 tf->tf_r0 = tf->tf_ip; 134 } 135 else 136 #endif 137 { 138 insn = read_insn(tf->tf_pc - INSN_SIZE, true); 139 } 140 141 KASSERTMSG(tf == lwp_trapframe(l), "tf %p vs %p", tf, lwp_trapframe(l)); 142 143 #ifdef CPU_ARM7 144 /* 145 * This code is only needed if we are including support for the ARM7 146 * core. Other CPUs do not need it but it does not hurt. 147 */ 148 149 /* 150 * ARM700/ARM710 match sticks and sellotape job ... 151 * 152 * I know this affects GPS/VLSI ARM700/ARM710 + various ARM7500. 153 * 154 * On occasion data aborts are mishandled and end up calling 155 * the swi vector. 156 * 157 * If the instruction that caused the exception is not a SWI 158 * then we hit the bug. 159 */ 160 if ((insn & 0x0f000000) != 0x0f000000) { 161 tf->tf_pc -= INSN_SIZE; 162 curcpu()->ci_arm700bugcount.ev_count++; 163 userret(l); 164 return; 165 } 166 #endif /* CPU_ARM7 */ 167 168 curcpu()->ci_data.cpu_nsyscall++; 169 170 (*l->l_proc->p_md.md_syscall)(tf, l, insn); 171 } 172 173 void syscall(struct trapframe *, lwp_t *, uint32_t); 174 175 void 176 syscall_intern(struct proc *p) 177 { 178 p->p_md.md_syscall = syscall; 179 } 180 181 void 182 syscall(struct trapframe *tf, lwp_t *l, uint32_t insn) 183 { 184 struct proc * const p = l->l_proc; 185 const struct sysent *callp; 186 int error; 187 u_int nargs, off = 0; 188 register_t *args; 189 uint64_t copyargs64[sizeof(register_t) * 190 (2+SYS_MAXSYSARGS+1)/sizeof(uint64_t)]; 191 register_t *copyargs = (register_t *)copyargs64; 192 register_t rval[2]; 193 ksiginfo_t ksi; 194 const uint32_t os_mask = insn & SWI_OS_MASK; 195 uint32_t code = insn & 0x000fffff; 196 197 /* test new official and old unofficial NetBSD ranges */ 198 if (__predict_false(os_mask != SWI_OS_NETBSD) 199 && __predict_false(os_mask != 0)) { 200 201 const uint32_t swi = __SHIFTOUT(insn, __BITS(23,0)); 202 if (swi == SWI_IMB || swi == SWI_IMBrange) { 203 userret(l); 204 return; 205 } 206 207 /* Undefined so illegal instruction */ 208 KSI_INIT_TRAP(&ksi); 209 ksi.ksi_signo = SIGILL; 210 ksi.ksi_code = ILL_ILLTRP; 211 #ifdef THUMB_CODE 212 if (tf->tf_spsr & PSR_T_bit) 213 ksi.ksi_addr = (void *)(tf->tf_pc - THUMB_INSN_SIZE); 214 else 215 #endif 216 ksi.ksi_addr = (void *)(tf->tf_pc - INSN_SIZE); 217 ksi.ksi_trap = insn; 218 trapsignal(l, &ksi); 219 userret(l); 220 return; 221 } 222 223 code &= (SYS_NSYSENT - 1); 224 225 if (__predict_false(code == SYS_syscall)) { 226 off = 1; 227 code = tf->tf_r0; 228 code &= (SYS_NSYSENT - 1); 229 if (__predict_false(code == SYS_syscall)) { 230 error = EINVAL; 231 goto bad; 232 } 233 } 234 235 callp = p->p_emul->e_sysent + code; 236 nargs = callp->sy_narg; 237 238 if ((nargs+off) > 4) { 239 args = copyargs; 240 memcpy(args, &tf->tf_r0+off, (4-off) * sizeof(register_t)); 241 error = copyin((void *)tf->tf_usr_sp, args + 4 - off, 242 (nargs - 4 + off) * sizeof(register_t)); 243 if (error) 244 goto bad; 245 } else { 246 args = &tf->tf_r0 + off; 247 } 248 249 error = sy_invoke(callp, l, args, rval, code); 250 251 switch (error) { 252 case 0: 253 tf->tf_r0 = rval[0]; 254 tf->tf_r1 = rval[1]; 255 256 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */ 257 break; 258 259 case ERESTART: 260 /* 261 * Reconstruct the pc to point at the swi. 262 */ 263 #ifdef THUMB_CODE 264 if (tf->tf_spsr & PSR_T_bit) 265 tf->tf_pc -= THUMB_INSN_SIZE; 266 else 267 #endif 268 tf->tf_pc -= INSN_SIZE; 269 break; 270 271 case EJUSTRETURN: 272 /* nothing to do */ 273 break; 274 275 default: 276 bad: 277 tf->tf_r0 = error; 278 tf->tf_spsr |= PSR_C_bit; /* carry bit */ 279 break; 280 } 281 282 userret(l); 283 } 284 285 void 286 md_child_return(struct lwp *l) 287 { 288 struct trapframe * const tf = lwp_trapframe(l); 289 290 tf->tf_r0 = 0; 291 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */ 292 293 userret(l); 294 } 295 296 /* 297 * Process the tail end of a posix_spawn() for the child. 298 */ 299 void 300 cpu_spawn_return(struct lwp *l) 301 { 302 303 userret(l); 304 } 305