Date: Wed, 22 Nov 2006 13:34:10 GMT From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 110383 for review Message-ID: <200611221334.kAMDYAPu061419@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=110383 Change 110383 by gonzo@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 +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611221334.kAMDYAPu061419>