#include <sys/param.h>
#include <sys/cpu.h>
#include <sys/ktrace.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/systm.h>
#include <sys/syscallvar.h>
#include <uvm/uvm_extern.h>
#include <powerpc/frame.h>
#include <powerpc/pcb.h>
#include <powerpc/userret.h>
#define FIRSTARG 3
#define NARGREG 8
#define MOREARGS(sp) ((void *)((uintptr_t)(sp) + 8))
#ifndef EMULNAME
#include <sys/syscall.h>
#define EMULNAME(x) (x)
#define EMULNAMEU(x) (x)
__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.58 2023/10/05 19:41:05 ad Exp $");
void
md_child_return(struct lwp *l)
{
struct trapframe * const tf = l->l_md.md_utf;
tf->tf_fixreg[FIRSTARG] = 0;
tf->tf_fixreg[FIRSTARG + 1] = 1;
tf->tf_cr &= ~0x10000000;
tf->tf_srr1 &= ~(PSL_FP|PSL_VEC);
}
#endif
#include <powerpc/spr.h>
static void EMULNAME(syscall)(struct trapframe *);
void
EMULNAME(syscall)(struct trapframe *tf)
{
struct lwp * const l = curlwp;
struct proc * const p = l->l_proc;
const struct sysent *callp;
size_t argsize;
register_t code;
register_t *params, rval[2];
register_t args[10];
int error;
int n;
curcpu()->ci_ev_scalls.ev_count++;
code = tf->tf_fixreg[0];
params = tf->tf_fixreg + FIRSTARG;
n = NARGREG;
{
switch (code) {
case EMULNAMEU(SYS_syscall):
code = *params++;
n -= 1;
break;
#if !defined(COMPAT_LINUX)
case EMULNAMEU(SYS___syscall):
params++;
code = *params++;
n -= 2;
break;
#endif
default:
break;
}
code &= EMULNAMEU(SYS_NSYSENT) - 1;
callp = p->p_emul->e_sysent + code;
}
argsize = callp->sy_argsize;
if (argsize > n * sizeof(register_t)) {
memcpy(args, params, n * sizeof(register_t));
error = copyin(MOREARGS(tf->tf_fixreg[1]),
args + n,
argsize - n * sizeof(register_t));
if (error)
goto bad;
params = args;
}
error = sy_invoke(callp, l, params, rval, code);
if (__predict_true(error == 0)) {
tf->tf_fixreg[FIRSTARG] = rval[0];
tf->tf_fixreg[FIRSTARG + 1] = rval[1];
tf->tf_cr &= ~0x10000000;
} else {
switch (error) {
case ERESTART:
tf->tf_srr0 -= 4;
break;
case EJUSTRETURN:
break;
default:
bad:
if (p->p_emul->e_errno)
error = p->p_emul->e_errno[error];
tf->tf_fixreg[FIRSTARG] = error;
tf->tf_cr |= 0x10000000;
break;
}
}
userret(l, tf);
}
void EMULNAME(syscall_intern)(struct proc *);
void
EMULNAME(syscall_intern)(struct proc *p)
{
p->p_md.md_syscall = EMULNAME(syscall);
}