diff options
Diffstat (limited to 'sys/sun4v/sun4v/trap.c')
-rw-r--r-- | sys/sun4v/sun4v/trap.c | 157 |
1 files changed, 51 insertions, 106 deletions
diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c index 702fd5ce28fd..d099351e3e62 100644 --- a/sys/sun4v/sun4v/trap.c +++ b/sys/sun4v/sun4v/trap.c @@ -117,8 +117,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", @@ -566,132 +564,79 @@ trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data /* Maximum number of arguments that can be passed via the out registers. */ #define REG_MAXARGS 6 -/* - * Syscall handler. The arguments to the syscall are passed in the o registers - * by the caller, and are saved in the trap frame. The syscall number is passed - * in %g1 (and also saved in the trap frame). - */ -void -syscall(struct trapframe *tf) +int +cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) { - struct sysent *callp; - struct thread *td; - register_t args[8]; - register_t *argp; + struct trapframe *tf; struct proc *p; - u_long code; + register_t *argp; int reg; int regcnt; - int narg; int error; - td = curthread; - KASSERT(td != NULL, ("trap: curthread NULL")); - KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); - p = td->td_proc; - - PCPU_INC(cnt.v_syscall); - - td->td_pticks = 0; - td->td_frame = tf; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); - code = tf->tf_global[1]; - - /* - * For syscalls, we don't want to retry the faulting instruction - * (usually), instead we need to advance one instruction. - */ - td->td_pcb->pcb_tpc = tf->tf_tpc; - TF_DONE(tf); - + tf = td->td_frame; reg = 0; regcnt = REG_MAXARGS; - if (p->p_sysent->sv_prepsyscall) { - /* - * The prep code is MP aware. - */ -#if 0 - (*p->p_sysent->sv_prepsyscall)(tf, args, &code, ¶ms); -#endif - } else if (code == SYS_syscall || code == SYS___syscall) { - code = tf->tf_out[reg++]; - regcnt--; - } - - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; + sa->code = tf->tf_global[1]; - narg = callp->sy_narg; - - if (narg <= regcnt) { - argp = &tf->tf_out[reg]; - error = 0; - } else { - KASSERT(narg <= sizeof(args) / sizeof(args[0]), - ("Too many syscall arguments!")); - argp = args; - bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt); - error = copyin((void *)(tf->tf_out[6] + SPOFF + - offsetof(struct frame, fr_pad[6])), - &args[regcnt], (narg - regcnt) * sizeof(args[0])); + if (sa->code == SYS_syscall || sa->code == SYS___syscall) { + sa->code = tf->tf_out[reg++]; + regcnt--; } - CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td, - syscallnames[code], argp[0], argp[1], argp[2]); - - /* - * Try to run the syscall without the MP lock if the syscall - * is MP safe. - */ -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSCALL)) - ktrsyscall(code, narg, argp); -#endif + 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 + sa->callp = &p->p_sysent->sv_table[sa->code]; + + sa->narg = sa->callp->sy_narg; + KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]), + ("Too many syscall arguments!")); + error = 0; + 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; + } - STOPEVENT(p, S_SCE, narg); /* MP aware */ - - PTRACESTOP_SC(p, td, S_PT_SCE); - - AUDIT_SYSCALL_ENTER(code, td); - error = (*callp->sy_call)(td, argp); - AUDIT_SYSCALL_EXIT(error, td); + return (error); +} - CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx ", p, - error, syscallnames[code], td->td_retval[0], - td->td_retval[1]); - } +/* + * Syscall handler. The arguments to the syscall are passed in the o registers + * by the caller, and are saved in the trap frame. The syscall number is passed + * in %g1 (and also saved in the trap frame). + */ +void +syscall(struct trapframe *tf) +{ + struct thread *td; + struct syscall_args sa; + int error; - cpu_set_syscall_retval(td, error); + td = curthread; + td->td_frame = tf; - /* - * Handle reschedule and other end-of-syscall issues - */ - userret(td, tf); + KASSERT(td != NULL, ("trap: curthread NULL")); + KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(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. + * For syscalls, we don't want to retry the faulting instruction + * (usually), instead we need to advance one instruction. */ - STOPEVENT(p, S_SCX, code); - - PTRACESTOP_SC(p, td, S_PT_SCX); + td->td_pcb->pcb_tpc = tf->tf_tpc; + TF_DONE(tf); - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&Giant, MA_NOTOWNED); + error = syscallenter(td, &sa); + syscallret(td, error, &sa); } + |