1 /* $NetBSD: linux32_syscall.c,v 1.33 2023/10/05 19:41:03 ad Exp $ */ 2 3 #include <sys/cdefs.h> 4 __KERNEL_RCSID(0, "$NetBSD: linux32_syscall.c,v 1.33 2023/10/05 19:41:03 ad Exp $"); 5 6 #include <sys/param.h> 7 #include <sys/systm.h> 8 #include <sys/proc.h> 9 #include <sys/signal.h> 10 #include <sys/syscall.h> 11 #include <sys/syscallvar.h> 12 13 #include <machine/cpu.h> 14 #include <machine/psl.h> 15 #include <machine/userret.h> 16 17 #include <compat/linux32/linux32_syscall.h> 18 #include <compat/linux32/common/linux32_errno.h> 19 20 void linux32_syscall_intern(struct proc *); 21 void linux32_syscall(struct trapframe *); 22 23 void 24 linux32_syscall_intern(struct proc *p) 25 { 26 27 p->p_md.md_syscall = linux32_syscall; 28 } 29 30 void 31 linux32_syscall(struct trapframe *frame) 32 { 33 const struct sysent *callp; 34 struct proc *p; 35 struct lwp *l; 36 int error; 37 size_t narg; 38 register32_t code, args[6]; 39 register_t rval[2]; 40 int i; 41 register_t args64[6]; 42 43 l = curlwp; 44 p = l->l_proc; 45 46 code = frame->tf_rax; 47 48 callp = p->p_emul->e_sysent; 49 50 code &= (LINUX32_SYS_NSYSENT - 1); 51 callp += code; 52 53 /* 54 * Linux passes the args in ebx, ecx, edx, esi, edi, ebp, in 55 * increasing order. 56 */ 57 args[0] = frame->tf_rbx & 0xffffffff; 58 args[1] = frame->tf_rcx & 0xffffffff; 59 args[2] = frame->tf_rdx & 0xffffffff; 60 args[3] = frame->tf_rsi & 0xffffffff; 61 args[4] = frame->tf_rdi & 0xffffffff; 62 args[5] = frame->tf_rbp & 0xffffffff; 63 64 if (__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_return))) { 65 narg = callp->sy_narg; 66 if (__predict_false(narg > __arraycount(args))) 67 panic("impossible syscall narg, code %d, narg %zu", 68 code, narg); 69 for (i = 0; i < narg; i++) 70 args64[i] = args[i] & 0xffffffff; 71 if ((error = trace_enter(code, callp, args64)) != 0) 72 goto out; 73 } 74 75 rval[0] = 0; 76 rval[1] = 0; 77 78 error = sy_call(callp, l, args, rval); 79 out: 80 switch (error) { 81 case 0: 82 frame->tf_rax = rval[0]; 83 frame->tf_rflags &= ~PSL_C; /* carry bit */ 84 break; 85 case ERESTART: 86 /* 87 * The offset to adjust the PC by depends on whether we entered 88 * the kernel through the trap or call gate. We pushed the 89 * size of the instruction into tf_err on entry. 90 */ 91 frame->tf_rip -= frame->tf_err; 92 break; 93 case EJUSTRETURN: 94 /* nothing to do */ 95 break; 96 default: 97 error = native_to_linux32_errno[error]; 98 frame->tf_rax = error; 99 frame->tf_rflags |= PSL_C; /* carry bit */ 100 break; 101 } 102 103 if (__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_return))) { 104 narg = callp->sy_narg; 105 for (i = 0; i < narg; i++) 106 args64[i] = args[i] & 0xffffffff; 107 trace_exit(code, callp, args64, rval, error); 108 } 109 userret(l); 110 } 111