#if defined(_KERNEL) && defined(_KERNEL_OPT)
#include "opt_dtrace.h"
#endif
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscall.c,v 1.34 2023/10/05 19:41:03 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/syscallvar.h>
#include <sys/syscallargs.h>
#include <sys/syscall_stats.h>
#include <machine/cpu.h>
#include <machine/psl.h>
#include <machine/userret.h>
void netbsd32_syscall_intern(struct proc *);
static void netbsd32_syscall(struct trapframe *);
void
netbsd32_syscall_intern(struct proc *p)
{
p->p_md.md_syscall = netbsd32_syscall;
}
void
netbsd32_syscall(struct trapframe *frame)
{
char *params;
const struct sysent *callp;
struct proc *p;
struct lwp *l;
int error;
int i;
register32_t code, args[2 + SYS_MAXSYSARGS];
register_t rval[2];
register_t args64[SYS_MAXSYSARGS];
l = curlwp;
p = l->l_proc;
code = frame->tf_rax & (SYS_NSYSENT - 1);
callp = p->p_emul->e_sysent + code;
SYSCALL_COUNT(syscall_counts, code);
SYSCALL_TIME_SYS_ENTRY(l, syscall_times, code);
params = (char *)frame->tf_rsp + sizeof(int);
if (callp->sy_argsize) {
error = copyin(params, args, callp->sy_argsize);
if (__predict_false(error != 0))
goto bad;
}
if (__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_entry))
&& !__predict_false(callp->sy_flags & SYCALL_INDIRECT)) {
int narg = callp->sy_argsize >> 2;
for (i = 0; i < narg; i++)
args64[i] = args[i];
error = trace_enter(code, callp, args64);
if (__predict_false(error != 0))
goto out;
}
rval[0] = 0;
rval[1] = 0;
error = sy_call(callp, l, args, rval);
out:
if (__predict_false(p->p_trace_enabled || KDTRACE_ENTRY(callp->sy_return))
&& !__predict_false(callp->sy_flags & SYCALL_INDIRECT)) {
int narg = callp->sy_argsize >> 2;
for (i = 0; i < narg; i++)
args64[i] = args[i];
trace_exit(code, callp, args64, rval, error);
}
if (__predict_true(error == 0)) {
frame->tf_rax = rval[0];
frame->tf_rdx = rval[1];
frame->tf_rflags &= ~PSL_C;
} else {
switch (error) {
case ERESTART:
frame->tf_rip -= frame->tf_err;
break;
case EJUSTRETURN:
break;
default:
bad:
frame->tf_rax = error;
frame->tf_rflags |= PSL_C;
break;
}
}
SYSCALL_TIME_SYS_EXIT(l);
userret(l);
}