Date: Wed, 5 Oct 2011 00:52:18 +0300 From: Kostik Belousov <kostikbel@gmail.com> To: mips@freebsd.org Subject: Re: Mips syscall entry point Message-ID: <20111004215218.GY1511@deviant.kiev.zoral.com.ua> In-Reply-To: <20111004211144.GW1511@deviant.kiev.zoral.com.ua> References: <20111004211144.GW1511@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
--GKxt9isuFuuOF2/C
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
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.
>=20
> I am asking for you help to debug and test the patch. Please keep me
> on Cc:, I am not on the list.
>=20
> Thank you.
>=20
> 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 */
> };
> =20
> +#ifdef _KERNEL
> struct thread;
> =20
> void mips_cpu_switch(struct thread *, struct thread *, struct mtx *);
> void mips_cpu_throw(struct thread *, struct thread *);
> =20
> +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 trapfram=
e *frame, int mode);
> =20
> extern void fswintrberr(void); /* XXX */
> =20
> +int
> +cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
> +{
> + struct trapframe *locr0 =3D 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 =3D sa->trapframe->pc; /* Remember if restart */
> + if (DELAYBRANCH(sa->trapframe->cause)) /* Check BD bit */
> + locr0->pc =3D MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0);
> + else
> + locr0->pc +=3D sizeof(int);
> + sa->code =3D 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 =3D locr0->a0;
> + sa->args[0] =3D locr0->a1;
> + sa->args[1] =3D locr0->a2;
> + sa->args[2] =3D locr0->a3;
> + nsaved =3D 3;
> +#if defined(__mips_n32) || defined(__mips_n64)
> + sa->args[3] =3D locr0->t4;
> + sa->args[4] =3D locr0->t5;
> + sa->args[5] =3D locr0->t6;
> + sa->args[6] =3D locr0->t7;
> + nsaved +=3D 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 =3D=3D 0)
> + sa->code =3D locr0->a0;
> + else
> + sa->code =3D locr0->a1;
> + sa->args[0] =3D locr0->a2;
> + sa->args[1] =3D locr0->a3;
> + nsaved =3D 2;
> + break;
> +#endif
> +
> + default:
> + sa->args[0] =3D locr0->a0;
> + sa->args[1] =3D locr0->a1;
> + sa->args[2] =3D locr0->a2;
> + sa->args[3] =3D locr0->a3;
> + nsaved =3D 4;
> +#if defined (__mips_n32) || defined(__mips_n64)
> + sa->args[4] =3D locr0->t4;
> + sa->args[5] =3D locr0->t5;
> + sa->args[6] =3D locr0->t6;
> + sa->args[7] =3D locr0->t7;
> + nsaved +=3D 4;
> +#endif
> + break;
> + }
> +#ifdef TRAP_DEBUG
> + if (trap_debug)
> + printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
> +#endif
> +
> + se =3D td->td_proc->p_sysent;
> + if (se->sv_mask)
> + sa->code &=3D se->sv_mask;
> +
> + if (sa->code >=3D se->sv_size)
> + sa->callp =3D &se->sv_table[0];
> + else
> + sa->callp =3D &se->sv_table[sa->code];
> +
> + sa->narg =3D 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 =3D 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 !=3D 0) {
> + locr0->v0 =3D error;
> + locr0->a3 =3D 1;
> + }
> + } else
> + error =3D 0;
> +
> + if (error =3D=3D 0) {
> + td->td_retval[0] =3D 0;
> + td->td_retval[1] =3D 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:
> =20
> case T_SYSCALL + T_USER:
> {
> - struct trapframe *locr0 =3D 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 !=3D 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 =3D trapframe->pc; /* Remember if restart */
> - if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
> - locr0->pc =3D MipsEmulateBranch(locr0, trapframe->pc, 0,
> - 0);
> - } else {
> - locr0->pc +=3D sizeof(int);
> - }
> - code =3D locr0->v0;
> + struct syscall_args sa;
> + int error;
> =20
> - 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 =3D locr0->a0;
> - args[0] =3D locr0->a1;
> - args[1] =3D locr0->a2;
> - args[2] =3D locr0->a3;
> - nsaved =3D 3;
> -#if defined(__mips_n32) || defined(__mips_n64)
> - args[3] =3D locr0->t4;
> - args[4] =3D locr0->t5;
> - args[5] =3D locr0->t6;
> - args[6] =3D locr0->t7;
> - nsaved +=3D 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 =3D=3D 0) {
> - code =3D locr0->a0;
> - } else {
> - code =3D locr0->a1;
> - }
> - args[0] =3D locr0->a2;
> - args[1] =3D locr0->a3;
> - nsaved =3D 2;
> - break;
> -#endif
> -
> - default:
> - args[0] =3D locr0->a0;
> - args[1] =3D locr0->a1;
> - args[2] =3D locr0->a2;
> - args[3] =3D locr0->a3;
> - nsaved =3D 4;
> -#if defined (__mips_n32) || defined(__mips_n64)
> - args[4] =3D locr0->t4;
> - args[5] =3D locr0->t5;
> - args[6] =3D locr0->t6;
> - args[7] =3D locr0->t7;
> - nsaved +=3D 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 &=3D p->p_sysent->sv_mask;
> -
> - if (code >=3D p->p_sysent->sv_size)
> - callp =3D &p->p_sysent->sv_table[0];
> - else
> - callp =3D &p->p_sysent->sv_table[code];
> -
> - nargs =3D 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 =3D 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 =3D i;
> - locr0->a3 =3D 1;
> -#ifdef KTRACE
> - if (KTRPOINT(td, KTR_SYSCALL))
> - ktrsyscall(code, nargs, args);
> -#endif
> - goto done;
> - }
> - }
> -#ifdef TRAP_DEBUG
> - if (trap_debug) {
> - for (i =3D 0; i < nargs; i++) {
> - printf("args[%d] =3D %#jx\n", i, (intmax_t)args[i]);
> - }
> - }
> -#endif
> -#ifdef SYSCALL_TRACING
> - printf("%s(", syscallnames[code]);
> - for (i =3D 0; i < nargs; i++) {
> - printf("%s%#jx", i =3D=3D 0 ? "" : ", ", (intmax_t)args[i]);
> - }
> - printf(")\n");
> -#endif
> -#ifdef KTRACE
> - if (KTRPOINT(td, KTR_SYSCALL))
> - ktrsyscall(code, nargs, args);
> -#endif
> - td->td_retval[0] =3D 0;
> - td->td_retval[1] =3D locr0->v1;
> + sa.trapframe =3D trapframe;
> + error =3D syscallenter(td, &sa);
> =20
> #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
> if (trp =3D=3D trapdebug)
> @@ -683,21 +666,7 @@ dofault:
> else
> trp[-1].code =3D code;
> #endif
> - STOPEVENT(p, S_SCE, nargs);
> -
> - PTRACESTOP_SC(p, td, S_PT_SCE);
> - i =3D (*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 =3D curthread;
> - locr0 =3D td->td_frame;
> -#endif
> trapdebug_enter(locr0, -code);
> - cpu_set_syscall_retval(td, i);
> =20
> /*
> * 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 >=3D 0 && code < SYS_MAXSYSCALL) ?
> - syscallnames[code] : "???");
> - KASSERT(td->td_critnest =3D=3D 0,
> - ("System call %s returning in a critical section",
> - (code >=3D 0 && code < SYS_MAXSYSCALL) ?
> - syscallnames[code] : "???"));
> - KASSERT(td->td_locks =3D=3D 0,
> - ("System call %s returning with %d locks held",
> - (code >=3D 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);
> }
> =20
--GKxt9isuFuuOF2/C
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (FreeBSD)
iEYEARECAAYFAk6LgBIACgkQC3+MBN1Mb4iM7wCgkpuaW287HeD0JK5UeQwfLzvh
WG0AoIGtxYkCeoLN1suM6VmhEgUtPIMA
=qTZU
-----END PGP SIGNATURE-----
--GKxt9isuFuuOF2/C--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111004215218.GY1511>
