1 /* $OpenBSD: syscall.c,v 1.9 2021/12/09 00:26:11 guenther Exp $ */ 2 /* 3 * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/proc.h> 20 #include <sys/signalvar.h> 21 #include <sys/user.h> 22 #include <sys/vnode.h> 23 #include <sys/signal.h> 24 #include <sys/syscall.h> 25 #include <sys/syscall_mi.h> 26 #include <sys/systm.h> 27 #include <sys/proc.h> 28 29 #include <uvm/uvm_extern.h> 30 31 #include <machine/vfp.h> 32 33 #define MAXARGS 8 34 35 void 36 svc_handler(trapframe_t *frame) 37 { 38 struct proc *p = curproc; 39 const struct sysent *callp; 40 int code, error; 41 u_int nap = 8, nargs; 42 register_t *ap, *args, copyargs[MAXARGS], rval[2]; 43 44 uvmexp.syscalls++; 45 46 /* Before enabling interrupts, save FPU state */ 47 vfp_save(); 48 49 /* Re-enable interrupts if they were enabled previously */ 50 if (__predict_true((frame->tf_spsr & I_bit) == 0)) 51 intr_enable(); 52 53 /* Skip over speculation-blocking barrier. */ 54 frame->tf_elr += 8; 55 56 code = frame->tf_x[8]; 57 58 ap = &frame->tf_x[0]; 59 60 switch (code) { 61 case SYS_syscall: 62 code = *ap++; 63 nap--; 64 break; 65 case SYS___syscall: 66 code = *ap++; 67 nap--; 68 break; 69 } 70 71 callp = sysent; 72 if (code < 0 || code >= SYS_MAXSYSCALL) 73 callp += SYS_syscall; 74 else 75 callp += code; 76 77 nargs = callp->sy_argsize / sizeof(register_t); 78 if (nargs <= nap) { 79 args = ap; 80 } else { 81 KASSERT(nargs <= MAXARGS); 82 memcpy(copyargs, ap, nap * sizeof(register_t)); 83 if ((error = copyin((void *)frame->tf_sp, copyargs + nap, 84 (nargs - nap) * sizeof(register_t)))) 85 goto bad; 86 args = copyargs; 87 } 88 89 rval[0] = 0; 90 rval[1] = frame->tf_x[1]; 91 92 error = mi_syscall(p, code, callp, args, rval); 93 94 switch (error) { 95 case 0: 96 frame->tf_x[0] = rval[0]; 97 frame->tf_x[1] = rval[1]; 98 99 frame->tf_spsr &= ~PSR_C; /* carry bit */ 100 break; 101 102 case ERESTART: 103 /* 104 * Reconstruct the pc to point at the svc. 105 */ 106 frame->tf_elr -= 12; 107 break; 108 109 case EJUSTRETURN: 110 /* nothing to do */ 111 break; 112 113 default: 114 bad: 115 frame->tf_x[0] = error; 116 frame->tf_spsr |= PSR_C; /* carry bit */ 117 break; 118 } 119 120 mi_syscall_return(p, code, error, rval); 121 } 122 123 void 124 child_return(void *arg) 125 { 126 struct proc *p = arg; 127 struct trapframe *frame = p->p_addr->u_pcb.pcb_tf; 128 129 frame->tf_x[0] = 0; 130 frame->tf_x[1] = 1; 131 frame->tf_spsr &= ~PSR_C; /* carry bit */ 132 133 KERNEL_UNLOCK(); 134 135 mi_child_return(p); 136 } 137