diff options
Diffstat (limited to 'sys/sparc64/sparc64/trap.c')
-rw-r--r-- | sys/sparc64/sparc64/trap.c | 123 |
1 files changed, 14 insertions, 109 deletions
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index c0772a188697..8ce6970d65d3 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -94,18 +94,9 @@ __FBSDID("$FreeBSD$"); #include <machine/tsb.h> #include <machine/watch.h> -struct syscall_args { - u_long code; - struct sysent *callp; - register_t args[8]; - register_t *argp; - int narg; -}; - void trap(struct trapframe *tf); void syscall(struct trapframe *tf); -static int fetch_syscall_args(struct thread *td, struct syscall_args *sa); static int trap_cecc(void); static int trap_pfault(struct thread *td, struct trapframe *tf); @@ -123,8 +114,6 @@ extern char fas_fault[]; extern char fas_nofault_begin[]; extern char fas_nofault_end[]; -extern char *syscallnames[]; - const char *const trap_msg[] = { "reserved", "instruction access exception", @@ -579,11 +568,12 @@ trap_pfault(struct thread *td, struct trapframe *tf) /* Maximum number of arguments that can be passed via the out registers. */ #define REG_MAXARGS 6 -static int -fetch_syscall_args(struct thread *td, struct syscall_args *sa) +int +cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) { struct trapframe *tf; struct proc *p; + register_t *argp; int reg; int regcnt; int error; @@ -595,19 +585,13 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa) sa->code = tf->tf_global[1]; - if (p->p_sysent->sv_prepsyscall) { -#if 0 - (*p->p_sysent->sv_prepsyscall)(tf, sa->args, &sa->code, - ¶ms); -#endif - } else if (sa->code == SYS_syscall || sa->code == SYS___syscall) { + if (sa->code == SYS_syscall || sa->code == SYS___syscall) { sa->code = tf->tf_out[reg++]; regcnt--; } if (p->p_sysent->sv_mask) sa->code &= p->p_sysent->sv_mask; - if (sa->code >= p->p_sysent->sv_size) sa->callp = &p->p_sysent->sv_table[0]; else @@ -617,21 +601,17 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa) KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]), ("Too many syscall arguments!")); error = 0; - sa->argp = sa->args; + argp = sa->args; bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt); if (sa->narg > regcnt) error = copyin((void *)(tf->tf_out[6] + SPOFF + offsetof(struct frame, fr_pad[6])), &sa->args[regcnt], (sa->narg - regcnt) * sizeof(sa->args[0])); + if (error == 0) { + td->td_retval[0] = 0; + td->td_retval[1] = 0; + } - /* - * This may result in two records if debugger modified - * registers or memory during sleep at stop/ptrace point. - */ -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSCALL)) - ktrsyscall(sa->code, sa->narg, sa->argp); -#endif return (error); } @@ -644,29 +624,16 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa) void syscall(struct trapframe *tf) { - struct syscall_args sa; struct thread *td; - struct proc *p; + struct syscall_args sa; int error; td = curthread; + td->td_frame = tf; + KASSERT(td != NULL, ("trap: curthread NULL")); KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); - PCPU_INC(cnt.v_syscall); - p = td->td_proc; - td->td_syscalls++; - - td->td_pticks = 0; - td->td_frame = tf; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); - if ((p->p_flag & P_TRACED) != 0) { - PROC_LOCK(p); - td->td_dbgflags &= ~TDB_USERWR; - PROC_UNLOCK(p); - } - /* * For syscalls, we don't want to retry the faulting instruction * (usually), instead we need to advance one instruction. @@ -674,68 +641,6 @@ syscall(struct trapframe *tf) td->td_pcb->pcb_tpc = tf->tf_tpc; TF_DONE(tf); - error = fetch_syscall_args(td, &sa); - CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td, - syscallnames[sa.code], sa.argp[0], sa.argp[1], sa.argp[2]); - - if (error == 0) { - td->td_retval[0] = 0; - td->td_retval[1] = 0; - - STOPEVENT(p, S_SCE, sa.narg); - PTRACESTOP_SC(p, td, S_PT_SCE); - if ((td->td_dbgflags & TDB_USERWR) != 0) { - /* - * Reread syscall number and arguments if - * debugger modified registers or memory. - */ - error = fetch_syscall_args(td, &sa); - if (error != 0) - goto retval; - td->td_retval[1] = 0; - } - - AUDIT_SYSCALL_ENTER(sa.code, td); - error = (*sa.callp->sy_call)(td, sa.argp); - AUDIT_SYSCALL_EXIT(error, td); - - CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx", - p, error, syscallnames[sa.code], td->td_retval[0], - td->td_retval[1]); - } - retval: - cpu_set_syscall_retval(td, error); - - /* - * Check for misbehavior. - */ - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???"); - KASSERT(td->td_critnest == 0, - ("System call %s returning in a critical section", - (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???")); - KASSERT(td->td_locks == 0, - ("System call %s returning with %d locks held", - (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???", td->td_locks)); - - /* - * Handle reschedule and other end-of-syscall issues. - */ - userret(td, tf); - -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(sa.code, error, td->td_retval[0]); -#endif - /* - * This works because errno is findable through the - * register set. If we ever support an emulation where this - * is not the case, this code will need to be revisited. - */ - STOPEVENT(p, S_SCX, sa.code); - - PTRACESTOP_SC(p, td, S_PT_SCX); + error = syscallenter(td, &sa); + syscallret(td, error, &sa); } |