#include <mach/mach_types.h>
#include <mach/exception_types.h>
#include <mach/error.h>
#include <kern/counters.h>
#include <kern/syscall_sw.h>
#include <kern/task.h>
#include <kern/thread.h>
#include <ppc/thread.h>
#include <kern/thread_act.h>
#include <ppc/thread_act.h>
#include <ppc/asm.h>
#include <ppc/proc_reg.h>
#include <ppc/trap.h>
#include <ppc/exception.h>
#include <kern/assert.h>
#include <sys/syscall.h>
#include <sys/ktrace.h>
#include <sys/kdebug.h>
struct proc;
#define ERESTART -1
#define EJUSTRETURN -2
struct unix_syscallargs {
int flavor;
int r3;
int arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9;
};
struct sysent {
unsigned short sy_narg;
char sy_parallel;
char sy_funnel;
unsigned long (*sy_call)(void *, void *, int *);
};
#define KERNEL_FUNNEL 1
#define NETWORK_FUNNEL 2
extern funnel_t * kernel_flock;
extern funnel_t * network_flock;
extern struct sysent sysent[];
void *get_bsdtask_info(
task_t);
int set_bsduthreadargs (
thread_act_t, struct pcb *,
struct unix_syscallargs *);
void * get_bsduthreadarg(
thread_act_t);
void
unix_syscall(
struct pcb * pcb,
int, int, int, int, int, int, int );
void
unix_syscall(
struct pcb * pcb,
int arg1,
int arg2,
int arg3,
int arg4,
int arg5,
int arg6,
int arg7
)
{
struct ppc_saved_state *regs;
thread_act_t thread;
struct sysent *callp;
int nargs, error;
unsigned short code;
struct proc *p;
void *vt;
int * vtint;
int *rval;
int funnel_type;
struct proc *current_proc();
struct unix_syscallargs sarg;
extern int nsysent;
regs = &pcb->ss;
code = regs->r0;
thread = current_act();
p = current_proc();
rval = (int *)get_bsduthreadrval(thread);
callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
sarg. flavor = (callp == sysent)? 1: 0;
if (sarg.flavor) {
code = regs->r3;
callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
} else
sarg. r3 = regs->r3;
if (code != 180) {
if (sarg.flavor)
KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
arg1, arg2, arg3, arg4, 0);
else
KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START,
sarg.r3, arg1, arg2, arg3, 0);
}
sarg.arg1 = arg1;
sarg.arg2 = arg2;
sarg.arg3 = arg3;
sarg.arg4 = arg4;
sarg.arg5 = arg5;
sarg.arg6 = arg6;
sarg.arg7 = arg7;
if(callp->sy_funnel == NETWORK_FUNNEL) {
(void) thread_funnel_set(network_flock, TRUE);
} else {
(void) thread_funnel_set(kernel_flock, TRUE);
}
set_bsduthreadargs(thread,pcb,&sarg);
if (callp->sy_narg > 8)
panic("unix_syscall: max arg count exceeded");
rval[0] = 0;
rval[1] = 0;
error = 0;
regs->srr0 += 4;
vt = get_bsduthreadarg(thread);
counter_always(c_syscalls_unix++);
current_task()->syscalls_unix++;
ktrsyscall(p, code, callp->sy_narg, vt);
error = (*(callp->sy_call))(p, (void *)vt, rval);
regs = find_user_regs(thread);
if (regs == (struct ppc_saved_state *)0)
panic("No user savearea while returning from system call");
if (error == ERESTART) {
regs->srr0 -= 8;
} else if (error != EJUSTRETURN) {
if (error) {
regs->r3 = error;
regs->srr0 -= 4;
} else {
regs->r3 = rval[0];
regs->r4 = rval[1];
}
}
ktrsysret(p, code, error, rval[0]);
(void) thread_funnel_set(current_thread()->funnel_lock, FALSE);
if (code != 180) {
KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
error, rval[0], rval[1], 0, 0);
}
thread_exception_return();
}
unix_syscall_return(error)
{
struct ppc_saved_state *regs;
thread_act_t thread;
struct sysent *callp;
int nargs;
unsigned short code;
int *rval;
struct proc *p;
void *vt;
int * vtint;
struct pcb *pcb;
struct proc *current_proc();
struct unix_syscallargs sarg;
extern int nsysent;
thread = current_act();
p = current_proc();
rval = (int *)get_bsduthreadrval(thread);
pcb = thread->mact.pcb;
regs = &pcb->ss;
if (thread_funnel_get() == THR_FUNNEL_NULL)
panic("Unix syscall return without funnel held");
code = regs->r0;
if (error == ERESTART) {
regs->srr0 -= 8;
} else if (error != EJUSTRETURN) {
if (error) {
regs->r3 = error;
regs->srr0 -= 4;
} else {
regs->r3 = rval[0];
regs->r4 = rval[1];
}
}
ktrsysret(p, code, error, rval[0]);
(void) thread_funnel_set(current_thread()->funnel_lock, FALSE);
if (code != 180) {
KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END,
error, rval[0], rval[1], 0, 0);
}
thread_exception_return();
}