PERFORCE change 110383 for review
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Wed Nov 22 13:34:11 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=110383
Change 110383 by gonzo at gonzo_hq on 2006/11/22 13:33:31
o Since we provide trapframe using exception_store_registers
for every trap call there is no need to check curthread's
td_frame.
o Add syscal "case" in trap function.
o Replace "XXX send signal" comment with panic call for it's
harder to be ignored unlike comment.
o Add syscall function.
Affected files ...
.. //depot/projects/mips2/src/sys/mips/mips/trap.c#10 edit
Differences ...
==== //depot/projects/mips2/src/sys/mips/mips/trap.c#10 (text+ko) ====
@@ -25,18 +25,31 @@
* $FreeBSD$
*/
+#include <sys/types.h>
#include "opt_ddb.h"
#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/signalvar.h>
+#include <sys/ktr.h>
#include <sys/kdb.h>
+#ifdef KTRACE
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#endif
+#include <sys/ptrace.h>
+#include <sys/pioctl.h>
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <vm/vm_kern.h>
#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
#include <vm/vm_param.h>
#include <vm/vm_extern.h>
@@ -47,10 +60,16 @@
#include <machine/trap.h>
#include <machine/hwfunc.h>
+#include <security/audit/audit.h>
+
#ifdef DDB
#include <machine/db_machdep.h>
#endif
+#ifdef KDB
+#include <sys/kdb.h>
+#endif
+
struct trap_identifier {
u_int ExcCode;
const char *Mnemonic;
@@ -90,30 +109,27 @@
{ 31, "VCED", "Virtual coherency (data)" }
};
#define MAXTRAPID 31
+#define MAXARGS 8
+
+void syscall(struct thread *, struct trapframe *);
+extern const char *syscallnames[];
/* Protected by critical sections, for checking for bad addresses. */
static volatile char *trap_addr;
static volatile int trap_error;
void
-trap(struct trapframe *retf, u_int cause, void *badvaddr)
+trap(struct trapframe * tf, u_int cause, void *badvaddr)
{
vm_offset_t va;
vm_map_t map;
struct thread *td;
- struct trapframe *tf;
struct trap_identifier *tid;
int code, kernelmode;
int ftype, error;
platform_trap_enter();
- if (curthread != NULL)
- tf = curthread->td_frame;
- else
- tf = retf;
- bcopy(retf, tf, sizeof *tf);
-
code = (cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
kernelmode = (tf->tf_regs[TF_SR] & MIPS_SR_KSU_USER) == 0;
@@ -166,7 +182,16 @@
goto done;
if (kernelmode)
break;
- /* XXX send signal */
+
+ /* TODO: send signal */
+ panic("Send signal to userland here... error=%d, va=0x%08x\n",
+ error, va);
+
+ case TrSys:
+ syscall(curthread, tf);
+ goto done;
+ break;
+
case TrAdEL:
case TrDBE:
if (trap_error == -1/* && trap_addr == badvaddr*/) {
@@ -237,7 +262,6 @@
#endif
done:
platform_trap_exit();
- bcopy(tf, retf, sizeof *tf);
}
int
@@ -261,3 +285,153 @@
return (0);
return (error);
}
+
+/*
+ * Following conventions are used for syscall implementation:
+ * - Syscall number is passed in v0
+ * - Arguments in a0,a1,...,stack..
+ * - Error flag is returned in a3 (a3 != 0 ergo there was an error)
+ * - v0 (possibly v1) contains return value
+ */
+void
+syscall(struct thread *td, struct trapframe *frame)
+{
+
+ struct proc *p = td->td_proc;
+ int code, error;
+ u_int nargs, i;
+ register_t *args, copyargs[MAXARGS];
+ struct sysent *callp;
+ int locked = 0;
+ int args_shift = 0;
+
+ PCPU_LAZY_INC(cnt.v_syscall);
+ td->td_pticks = 0;
+ if (td->td_ucred != td->td_proc->p_ucred)
+ cred_update_thread(td);
+
+ code = frame->tf_regs[TF_V0] & 0x000fffff;
+
+ /*
+ * For SYS_syscall first argument is an actual syscall number
+ * and following are arguments
+ */
+ if(code == SYS_syscall)
+ {
+ code = frame->tf_regs[TF_A0];
+ args_shift = 1;
+ }
+
+ /* TODO: implement */
+ if(code == SYS___syscall)
+ panic("SYS___syscall: to implement");
+
+ 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];
+ nargs = callp->sy_narg & SYF_ARGMASK;
+
+ printf("syscall enter thread %p pid %d proc " \
+ "%s code %d(%s) nargs: %d\n", td,
+ td->td_proc->p_pid, td->td_proc->p_comm, code,
+ syscallnames[code], nargs);
+
+ /* Copy arguments from a0..a4 */
+ for(i = 0; i < MIN(nargs, 4 - args_shift); i++)
+ copyargs[i] = frame->tf_regs[TF_A0 + i + args_shift];
+
+ /* Copy arguments from stack (if any) */
+ if(i < nargs)
+ {
+ error = copyin((void *)frame->tf_regs[TF_SP], copyargs + i,
+ (nargs - i) * sizeof(register_t));
+
+ if (error)
+ goto bad;
+ }
+
+ args = copyargs;
+ error = 0;
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(code, nargs, args);
+#endif
+
+ CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_proc->p_comm, code);
+
+ if ((callp->sy_narg & SYF_MPSAFE) == 0)
+ mtx_lock(&Giant);
+ locked = 1;
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = 0;
+ STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK));
+ PTRACESTOP_SC(p, td, S_PT_SCE);
+ AUDIT_SYSCALL_ENTER(code, td);
+ error = (*callp->sy_call)(td, args);
+ AUDIT_SYSCALL_EXIT(error, td);
+ KASSERT(td->td_ar == NULL,
+ ("returning from syscall with td_ar set!"));
+ }
+ switch (error) {
+ case 0:
+ frame->tf_regs[TF_V0] = td->td_retval[0];
+ /*
+ * XXXMIPS: should we consider this case for 32-bit or
+ * only for 64bits?
+ */
+ /* frame->tf_regs[TF_V1] = td->td_retval[1]; */
+ frame->tf_regs[TF_A3] = 0;
+ break;
+
+ case ERESTART:
+ /*
+ * Reconstruct the pc to point at the swi.
+ */
+ panic("TODO: implement ERESTART in syscall");
+ /* frame->tf_pc -= INSN_SIZE; */
+ break;
+
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+
+ default:
+bad:
+ frame->tf_regs[TF_V0] = error;
+ frame->tf_regs[TF_A3] = 1;
+ break;
+ }
+
+ if (locked && (callp->sy_narg & SYF_MPSAFE) == 0)
+ mtx_unlock(&Giant);
+
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
+ td->td_locks));
+
+ /* XXXMIPS: Check for branch delay? */
+ frame->tf_regs[TF_EPC] += 4;
+ userret(td, frame);
+
+ CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_proc->p_comm, code);
+
+ STOPEVENT(p, S_SCX, code);
+ PTRACESTOP_SC(p, td, S_PT_SCX);
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSRET))
+ ktrsysret(code, error, td->td_retval[0]);
+#endif
+}
More information about the p4-projects
mailing list