aboutsummaryrefslogtreecommitdiff
path: root/sys/sun4v/sun4v/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/sun4v/sun4v/trap.c')
-rw-r--r--sys/sun4v/sun4v/trap.c157
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, &params);
-#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);
}
+