1 1.7 ad /* $NetBSD: freebsd_syscall.c,v 1.7 2023/10/05 19:41:06 ad Exp $ */ 2 1.1 maxv 3 1.1 maxv /*- 4 1.1 maxv * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 1.1 maxv * All rights reserved. 6 1.1 maxv * 7 1.1 maxv * This code is derived from software contributed to The NetBSD Foundation 8 1.1 maxv * by Charles M. Hannum. 9 1.1 maxv * 10 1.1 maxv * Redistribution and use in source and binary forms, with or without 11 1.1 maxv * modification, are permitted provided that the following conditions 12 1.1 maxv * are met: 13 1.1 maxv * 1. Redistributions of source code must retain the above copyright 14 1.1 maxv * notice, this list of conditions and the following disclaimer. 15 1.1 maxv * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 maxv * notice, this list of conditions and the following disclaimer in the 17 1.1 maxv * documentation and/or other materials provided with the distribution. 18 1.1 maxv * 19 1.1 maxv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 maxv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 maxv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 maxv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 maxv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 maxv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 maxv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 maxv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 maxv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 maxv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 maxv * POSSIBILITY OF SUCH DAMAGE. 30 1.1 maxv */ 31 1.1 maxv 32 1.1 maxv #include <sys/cdefs.h> 33 1.7 ad __KERNEL_RCSID(0, "$NetBSD: freebsd_syscall.c,v 1.7 2023/10/05 19:41:06 ad Exp $"); 34 1.1 maxv 35 1.1 maxv #include <sys/param.h> 36 1.1 maxv #include <sys/systm.h> 37 1.1 maxv #include <sys/proc.h> 38 1.1 maxv #include <sys/signal.h> 39 1.1 maxv #include <sys/syscall.h> 40 1.1 maxv #include <sys/syscallvar.h> 41 1.1 maxv 42 1.1 maxv #include <uvm/uvm_extern.h> 43 1.1 maxv 44 1.1 maxv #include <machine/cpu.h> 45 1.1 maxv #include <machine/psl.h> 46 1.1 maxv #include <machine/userret.h> 47 1.1 maxv 48 1.1 maxv #include <compat/sys/signal.h> 49 1.1 maxv 50 1.2 maxv #include <compat/freebsd/freebsd_machdep.h> 51 1.1 maxv #include <compat/freebsd/freebsd_syscall.h> 52 1.1 maxv 53 1.1 maxv void freebsd_syscall(struct trapframe *); 54 1.1 maxv 55 1.1 maxv void 56 1.1 maxv freebsd_syscall_intern(struct proc *p) 57 1.1 maxv { 58 1.1 maxv 59 1.1 maxv p->p_md.md_syscall = freebsd_syscall; 60 1.1 maxv } 61 1.1 maxv 62 1.1 maxv /* 63 1.1 maxv * syscall(frame): 64 1.1 maxv * System call request from POSIX system call gate interface to kernel. 65 1.1 maxv * Like trap(), argument is call by reference. 66 1.1 maxv */ 67 1.1 maxv void 68 1.1 maxv freebsd_syscall(struct trapframe *frame) 69 1.1 maxv { 70 1.1 maxv char *params; 71 1.1 maxv const struct sysent *callp; 72 1.1 maxv struct lwp *l; 73 1.1 maxv struct proc *p; 74 1.1 maxv int error; 75 1.1 maxv size_t argsize; 76 1.1 maxv register_t code, args[8], rval[2]; 77 1.1 maxv 78 1.1 maxv l = curlwp; 79 1.1 maxv p = l->l_proc; 80 1.1 maxv 81 1.1 maxv code = frame->tf_eax; 82 1.1 maxv callp = p->p_emul->e_sysent; 83 1.1 maxv params = (char *)frame->tf_esp + sizeof(int); 84 1.1 maxv 85 1.1 maxv switch (code) { 86 1.1 maxv case SYS_syscall: 87 1.1 maxv /* 88 1.1 maxv * Code is first argument, followed by actual args. 89 1.1 maxv */ 90 1.6 kre error = ufetch_long((void *)params, (u_long *)&code); 91 1.3 thorpej if (error) 92 1.3 thorpej goto bad; 93 1.1 maxv params += sizeof(int); 94 1.1 maxv break; 95 1.1 maxv case SYS___syscall: 96 1.1 maxv /* 97 1.1 maxv * Like syscall, but code is a quad, so as to maintain 98 1.1 maxv * quad alignment for the rest of the arguments. 99 1.1 maxv */ 100 1.6 kre error = ufetch_long((void *)(params + 101 1.3 thorpej _QUAD_LOWWORD * sizeof(int)), 102 1.6 kre (u_long *)&code); 103 1.3 thorpej if (error) 104 1.3 thorpej goto bad; 105 1.1 maxv params += sizeof(quad_t); 106 1.1 maxv break; 107 1.1 maxv default: 108 1.1 maxv break; 109 1.1 maxv } 110 1.1 maxv 111 1.1 maxv code &= (SYS_NSYSENT - 1); 112 1.1 maxv callp += code; 113 1.1 maxv argsize = callp->sy_argsize; 114 1.1 maxv if (argsize) { 115 1.1 maxv error = copyin(params, (void *)args, argsize); 116 1.1 maxv if (error) 117 1.1 maxv goto bad; 118 1.1 maxv } 119 1.1 maxv 120 1.1 maxv if (!__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_entry)) 121 1.1 maxv || (error = trace_enter(code, callp, args)) == 0) { 122 1.1 maxv rval[0] = 0; 123 1.1 maxv rval[1] = frame->tf_edx; /* need to keep edx for shared FreeBSD bins */ 124 1.1 maxv error = sy_call(callp, l, args, rval); 125 1.1 maxv } 126 1.1 maxv 127 1.1 maxv switch (error) { 128 1.1 maxv case 0: 129 1.1 maxv frame->tf_eax = rval[0]; 130 1.1 maxv frame->tf_edx = rval[1]; 131 1.1 maxv frame->tf_eflags &= ~PSL_C; /* carry bit */ 132 1.1 maxv break; 133 1.1 maxv case ERESTART: 134 1.1 maxv /* 135 1.1 maxv * The offset to adjust the PC by depends on whether we entered 136 1.1 maxv * the kernel through the trap or call gate. We pushed the 137 1.1 maxv * size of the instruction into tf_err on entry. 138 1.1 maxv */ 139 1.1 maxv frame->tf_eip -= frame->tf_err; 140 1.1 maxv break; 141 1.1 maxv case EJUSTRETURN: 142 1.1 maxv /* nothing to do */ 143 1.1 maxv break; 144 1.1 maxv default: 145 1.1 maxv bad: 146 1.1 maxv frame->tf_eax = error; 147 1.1 maxv frame->tf_eflags |= PSL_C; /* carry bit */ 148 1.1 maxv break; 149 1.1 maxv } 150 1.1 maxv 151 1.1 maxv if (__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_return))) 152 1.1 maxv trace_exit(code, callp, args, rval, error); 153 1.1 maxv 154 1.1 maxv userret(l); 155 1.1 maxv } 156