Mips syscall entry point
Kostik Belousov
kostikbel at gmail.com
Tue Oct 4 21:52:24 UTC 2011
On Wed, Oct 05, 2011 at 12:11:44AM +0300, Kostik Belousov wrote:
> Hi,
> below is the patch, test-compiled for XLP64 only, which converts the
> only remaining architecture MIPS to the new syscall entry sequence.
> The advantage of the conversion is sharing most of the code with all
> other architectures and avoiding duplication. Also, the implementation
> automatically feels the missed features for the MIPS, see the BUGS
s/feels/fills/, sorry
> section in the ptrace(2).
For the same reason, capsicum shall not work on MIPS.
>
> I am asking for you help to debug and test the patch. Please keep me
> on Cc:, I am not on the list.
>
> Thank you.
>
> diff --git a/sys/mips/include/proc.h b/sys/mips/include/proc.h
> index 11a1f8e..4c0b0b6 100644
> --- a/sys/mips/include/proc.h
> +++ b/sys/mips/include/proc.h
> @@ -67,11 +67,22 @@ struct mdproc {
> /* empty */
> };
>
> +#ifdef _KERNEL
> struct thread;
>
> void mips_cpu_switch(struct thread *, struct thread *, struct mtx *);
> void mips_cpu_throw(struct thread *, struct thread *);
>
> +struct syscall_args {
> + u_int code;
> + struct sysent *callp;
> + register_t args[8];
> + int narg;
> + struct trapframe *trapframe;
> +};
> +#define HAVE_SYSCALL_ARGS_DEF 1
> +#endif
> +
> #ifdef __mips_n64
> #define KINFO_PROC_SIZE 1088
> #else
> diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
> index c800e71..9755c70 100644
> --- a/sys/mips/mips/trap.c
> +++ b/sys/mips/mips/trap.c
> @@ -261,6 +261,133 @@ static int emulate_unaligned_access(struct trapframe *frame, int mode);
>
> extern void fswintrberr(void); /* XXX */
>
> +int
> +cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
> +{
> + struct trapframe *locr0 = td->td_frame;
> + struct sysentvec *se;
> + int error, nsaved;
> +
> + bzero(sa->args, sizeof(sa->args));
> +
> + /* compute next PC after syscall instruction */
> + td->td_pcb->pcb_tpc = sa->trapframe->pc; /* Remember if restart */
> + if (DELAYBRANCH(sa->trapframe->cause)) /* Check BD bit */
> + locr0->pc = MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0);
> + else
> + locr0->pc += sizeof(int);
> + sa->code = locr0->v0;
> +
> + switch (sa->code) {
> +#if defined(__mips_n32) || defined(__mips_n64)
> + case SYS___syscall:
> + /*
> + * Quads fit in a single register in
> + * new ABIs.
> + *
> + * XXX o64?
> + */
> +#endif
> + case SYS_syscall:
> + /*
> + * Code is first argument, followed by
> + * actual args.
> + */
> + sa->code = locr0->a0;
> + sa->args[0] = locr0->a1;
> + sa->args[1] = locr0->a2;
> + sa->args[2] = locr0->a3;
> + nsaved = 3;
> +#if defined(__mips_n32) || defined(__mips_n64)
> + sa->args[3] = locr0->t4;
> + sa->args[4] = locr0->t5;
> + sa->args[5] = locr0->t6;
> + sa->args[6] = locr0->t7;
> + nsaved += 4;
> +#endif
> + break;
> +
> +#if defined(__mips_o32)
> + case SYS___syscall:
> + /*
> + * Like syscall, but code is a quad, so as
> + * to maintain quad alignment for the rest
> + * of the arguments.
> + */
> + if (_QUAD_LOWWORD == 0)
> + sa->code = locr0->a0;
> + else
> + sa->code = locr0->a1;
> + sa->args[0] = locr0->a2;
> + sa->args[1] = locr0->a3;
> + nsaved = 2;
> + break;
> +#endif
> +
> + default:
> + sa->args[0] = locr0->a0;
> + sa->args[1] = locr0->a1;
> + sa->args[2] = locr0->a2;
> + sa->args[3] = locr0->a3;
> + nsaved = 4;
> +#if defined (__mips_n32) || defined(__mips_n64)
> + sa->args[4] = locr0->t4;
> + sa->args[5] = locr0->t5;
> + sa->args[6] = locr0->t6;
> + sa->args[7] = locr0->t7;
> + nsaved += 4;
> +#endif
> + break;
> + }
> +#ifdef TRAP_DEBUG
> + if (trap_debug)
> + printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
> +#endif
> +
> + se = td->td_proc->p_sysent;
> + if (se->sv_mask)
> + sa->code &= se->sv_mask;
> +
> + if (sa->code >= se->sv_size)
> + sa->callp = &se->sv_table[0];
> + else
> + sa->callp = &se->sv_table[sa->code];
> +
> + sa->narg = sa->callp->sy_narg;
> +
> + if (sa->narg > nsaved) {
> +#if defined(__mips_n32) || defined(__mips_n64)
> + /*
> + * XXX
> + * Is this right for new ABIs? I think the 4 there
> + * should be 8, size there are 8 registers to skip,
> + * not 4, but I'm not certain.
> + */
> + printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", sa->code,
> + td->td_proc->p_pid);
> +#endif
> + error = copyin((caddr_t)(intptr_t)(locr0->sp +
> + 4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
> + (u_int)(sa->narg - nsaved) * sizeof(register_t));
> + if (error != 0) {
> + locr0->v0 = error;
> + locr0->a3 = 1;
> + }
> + } else
> + error = 0;
> +
> + if (error == 0) {
> + td->td_retval[0] = 0;
> + td->td_retval[1] = locr0->v1;
> + }
> +
> + return (error);
> +}
> +
> +#undef __FBSDID
> +#define __FBSDID(x)
> +#include "../../kern/subr_syscall.c"
> +
> /*
> * Handle an exception.
> * Called from MipsKernGenException() or MipsUserGenException()
> @@ -527,155 +654,11 @@ dofault:
>
> case T_SYSCALL + T_USER:
> {
> - struct trapframe *locr0 = td->td_frame;
> - struct sysent *callp;
> - unsigned int code;
> - int nargs, nsaved;
> - register_t args[8];
> -
> - bzero(args, sizeof args);
> -
> - /*
> - * note: PCPU_LAZY_INC() can only be used if we can
> - * afford occassional inaccuracy in the count.
> - */
> - PCPU_LAZY_INC(cnt.v_syscall);
> - if (td->td_ucred != p->p_ucred)
> - cred_update_thread(td);
> -#ifdef KSE
> - if (p->p_flag & P_SA)
> - thread_user_enter(td);
> -#endif
> - /* compute next PC after syscall instruction */
> - td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
> - if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
> - locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
> - 0);
> - } else {
> - locr0->pc += sizeof(int);
> - }
> - code = locr0->v0;
> + struct syscall_args sa;
> + int error;
>
> - switch (code) {
> -#if defined(__mips_n32) || defined(__mips_n64)
> - case SYS___syscall:
> - /*
> - * Quads fit in a single register in
> - * new ABIs.
> - *
> - * XXX o64?
> - */
> -#endif
> - case SYS_syscall:
> - /*
> - * Code is first argument, followed by
> - * actual args.
> - */
> - code = locr0->a0;
> - args[0] = locr0->a1;
> - args[1] = locr0->a2;
> - args[2] = locr0->a3;
> - nsaved = 3;
> -#if defined(__mips_n32) || defined(__mips_n64)
> - args[3] = locr0->t4;
> - args[4] = locr0->t5;
> - args[5] = locr0->t6;
> - args[6] = locr0->t7;
> - nsaved += 4;
> -#endif
> - break;
> -
> -#if defined(__mips_o32)
> - case SYS___syscall:
> - /*
> - * Like syscall, but code is a quad, so as
> - * to maintain quad alignment for the rest
> - * of the arguments.
> - */
> - if (_QUAD_LOWWORD == 0) {
> - code = locr0->a0;
> - } else {
> - code = locr0->a1;
> - }
> - args[0] = locr0->a2;
> - args[1] = locr0->a3;
> - nsaved = 2;
> - break;
> -#endif
> -
> - default:
> - args[0] = locr0->a0;
> - args[1] = locr0->a1;
> - args[2] = locr0->a2;
> - args[3] = locr0->a3;
> - nsaved = 4;
> -#if defined (__mips_n32) || defined(__mips_n64)
> - args[4] = locr0->t4;
> - args[5] = locr0->t5;
> - args[6] = locr0->t6;
> - args[7] = locr0->t7;
> - nsaved += 4;
> -#endif
> - }
> -#ifdef TRAP_DEBUG
> - if (trap_debug) {
> - printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
> - }
> -#endif
> -
> - 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;
> -
> - if (nargs > nsaved) {
> -#if defined(__mips_n32) || defined(__mips_n64)
> - /*
> - * XXX
> - * Is this right for new ABIs? I think the 4 there
> - * should be 8, size there are 8 registers to skip,
> - * not 4, but I'm not certain.
> - */
> - printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
> -#endif
> - i = copyin((caddr_t)(intptr_t)(locr0->sp +
> - 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
> - (u_int)(nargs - nsaved) * sizeof(register_t));
> - if (i) {
> - locr0->v0 = i;
> - locr0->a3 = 1;
> -#ifdef KTRACE
> - if (KTRPOINT(td, KTR_SYSCALL))
> - ktrsyscall(code, nargs, args);
> -#endif
> - goto done;
> - }
> - }
> -#ifdef TRAP_DEBUG
> - if (trap_debug) {
> - for (i = 0; i < nargs; i++) {
> - printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
> - }
> - }
> -#endif
> -#ifdef SYSCALL_TRACING
> - printf("%s(", syscallnames[code]);
> - for (i = 0; i < nargs; i++) {
> - printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
> - }
> - printf(")\n");
> -#endif
> -#ifdef KTRACE
> - if (KTRPOINT(td, KTR_SYSCALL))
> - ktrsyscall(code, nargs, args);
> -#endif
> - td->td_retval[0] = 0;
> - td->td_retval[1] = locr0->v1;
> + sa.trapframe = trapframe;
> + error = syscallenter(td, &sa);
>
> #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
> if (trp == trapdebug)
> @@ -683,21 +666,7 @@ dofault:
> else
> trp[-1].code = code;
> #endif
> - STOPEVENT(p, S_SCE, nargs);
> -
> - PTRACESTOP_SC(p, td, S_PT_SCE);
> - i = (*callp->sy_call) (td, args);
> -#if 0
> - /*
> - * Reinitialize proc pointer `p' as it may be
> - * different if this is a child returning from fork
> - * syscall.
> - */
> - td = curthread;
> - locr0 = td->td_frame;
> -#endif
> trapdebug_enter(locr0, -code);
> - cpu_set_syscall_retval(td, i);
>
> /*
> * The sync'ing of I & D caches for SYS_ptrace() is
> @@ -705,38 +674,7 @@ dofault:
> * instead of being done here under a special check
> * for SYS_ptrace().
> */
> - done:
> - /*
> - * Check for misbehavior.
> - */
> - 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));
> - userret(td, trapframe);
> -#ifdef KTRACE
> - if (KTRPOINT(td, KTR_SYSRET))
> - ktrsysret(code, i, 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, code);
> -
> - PTRACESTOP_SC(p, td, S_PT_SCX);
> -
> - mtx_assert(&Giant, MA_NOTOWNED);
> + syscallret(td, error, &sa);
> return (trapframe->pc);
> }
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-mips/attachments/20111004/45bebd6d/attachment.pgp
More information about the freebsd-mips
mailing list