Module Name: src Committed By: reinoud Date: Thu Sep 8 19:39:00 UTC 2011
Modified Files: src/sys/arch/usermode/include: machdep.h src/sys/arch/usermode/usermode: machdep.c syscall.c trap.c Log Message: Implement a working(!) syscall! well, it can call a number of syscalls without dying ;) To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/usermode/include/machdep.h cvs rdiff -u -r1.26 -r1.27 src/sys/arch/usermode/usermode/machdep.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/usermode/usermode/syscall.c cvs rdiff -u -r1.36 -r1.37 src/sys/arch/usermode/usermode/trap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/usermode/include/machdep.h diff -u src/sys/arch/usermode/include/machdep.h:1.1 src/sys/arch/usermode/include/machdep.h:1.2 --- src/sys/arch/usermode/include/machdep.h:1.1 Thu Sep 8 15:11:42 2011 +++ src/sys/arch/usermode/include/machdep.h Thu Sep 8 19:38:59 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.h,v 1.1 2011/09/08 15:11:42 reinoud Exp $ */ +/* $NetBSD: machdep.h,v 1.2 2011/09/08 19:38:59 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -26,6 +26,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -int md_check_syscall_opcode(void *ptr); +int md_syscall_check_opcode(void *ptr); +void md_syscall_get_syscallnumber(ucontext_t *ucp, uint32_t *code); +int md_syscall_getargs(lwp_t *l, ucontext_t *ucp, int nargs, int argsize, + register_t *args); +void md_syscall_set_returnargs(lwp_t *l, ucontext_t *ucp, register_t *rval); +void md_syscall_inc_pc(ucontext_t *ucp); + void syscall(void); Index: src/sys/arch/usermode/usermode/machdep.c diff -u src/sys/arch/usermode/usermode/machdep.c:1.26 src/sys/arch/usermode/usermode/machdep.c:1.27 --- src/sys/arch/usermode/usermode/machdep.c:1.26 Thu Sep 8 15:10:59 2011 +++ src/sys/arch/usermode/usermode/machdep.c Thu Sep 8 19:39:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.26 2011/09/08 15:10:59 reinoud Exp $ */ +/* $NetBSD: machdep.c,v 1.27 2011/09/08 19:39:00 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -32,7 +32,7 @@ #include "opt_urkelvisor.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.26 2011/09/08 15:10:59 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.27 2011/09/08 19:39:00 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -214,13 +214,78 @@ #endif } +void +md_syscall_get_syscallnumber(ucontext_t *ucp, uint32_t *code) +{ + uint *reg = (int *) &ucp->uc_mcontext; + + *code = reg[11]; /* EAX */ +} + +int +md_syscall_getargs(lwp_t *l, ucontext_t *ucp, int nargs, int argsize, + register_t *args) +{ + uint *reg = (int *) &ucp->uc_mcontext; + register_t *sp = (register_t *) reg[17];/* ESP */ + int ret; + uint i; + + i = 0; +#if 0 + reg = (int *) &ucp->uc_mcontext; + /* register dump before call */ + const char *name[] = {"GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP", + "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP", "CS", "EFL", + "UESP", "SS"}; + + for (i =0; i < 19; i++) + printf("reg[%02d] (%6s) = %"PRIx32"\n", i, name[i], reg[i]); + printf("\n"); +#endif + + ret = copyin(sp + 1, args, argsize); + +#if 0 + for (i = 0; i < nargs+4; i++) + printf("stack[%02d] = %"PRIx32"\n", i, (uint) sp[i]); +#endif +#if 0 + for (i = 0; i < nargs; i++) + printf("arg[%02d] = %"PRIx32"\n", i, (uint) args[i]); + printf("\n"); +#endif + + return ret; +} + +void +md_syscall_set_returnargs(lwp_t *l, ucontext_t *ucp, register_t *rval) +{ + uint *reg = (int *) &ucp->uc_mcontext; + + /* set return parameters */ + reg[11] = rval[0]; /* EAX */ + reg[ 9] = rval[1]; /* EDX */ + +#if 0 + uint i; + reg = (int *) &ucp->uc_mcontext; + /* register dump before call */ + const char *name[] = {"GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP", + "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP", "CS", "EFL", + "UESP", "SS"}; + + for (i =0; i < 19; i++) + printf("reg[%02d] (%6s) = %"PRIx32"\n", i, name[i], reg[i]); +#endif + +} int -md_check_syscall_opcode(void *ptr) +md_syscall_check_opcode(void *ptr) { -// uint8_t *p8; uint16_t *p16; -// uint32_t *p32; /* undefined instruction */ p16 = (uint16_t *) ptr; @@ -233,6 +298,24 @@ return 0; } +void +md_syscall_inc_pc(ucontext_t *ucp) +{ + uint *reg = (int *) &ucp->uc_mcontext; + uint16_t *p16; + + /* advance program counter */ + p16 = (uint16_t *) reg[14]; + if (*p16 == 0xff0f) + reg[14] += 2; /* EIP */ + if (*p16 == 0xff0b) + reg[14] += 2; /* EIP */ + + /* TODO int $80 and sysenter */ + + printf("jump back to %p\n", (void *) reg[14]); +} + #else # error setregs() not yet ported to this architecture Index: src/sys/arch/usermode/usermode/syscall.c diff -u src/sys/arch/usermode/usermode/syscall.c:1.7 src/sys/arch/usermode/usermode/syscall.c:1.8 --- src/sys/arch/usermode/usermode/syscall.c:1.7 Thu Sep 8 14:49:42 2011 +++ src/sys/arch/usermode/usermode/syscall.c Thu Sep 8 19:39:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.c,v 1.7 2011/09/08 14:49:42 reinoud Exp $ */ +/* $NetBSD: syscall.c,v 1.8 2011/09/08 19:39:00 reinoud Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.7 2011/09/08 14:49:42 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.8 2011/09/08 19:39:00 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -43,8 +43,8 @@ #include <sys/userret.h> #include <machine/pcb.h> #include <machine/thunk.h> +#include <machine/machdep.h> -extern void syscall(void); void userret(struct lwp *l); @@ -73,39 +73,59 @@ syscall(void) { lwp_t *l = curlwp; + const struct proc * const p = l->l_proc; + const struct sysent *callp; struct pcb *pcb = lwp_getpcb(l); ucontext_t *ucp = &pcb->pcb_userland_ucp; - uint *reg, i; + register_t copyargs[2+SYS_MAXSYSARGS]; + register_t *args; + register_t rval[2]; + uint32_t code; + uint nargs, argsize; + int error; - l = curlwp; - - printf("syscall called for lwp %p!\n", l); - reg = (int *) &ucp->uc_mcontext; -#if 1 - /* register dump before call */ - const char *name[] = {"GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP", - "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP", "CS", "EFL", - "UESP", "SS"}; - - for (i =0; i < 19; i++) - printf("reg[%02d] (%6s) = %"PRIx32"\n", i, name[i], reg[i]); -#endif +// printf("syscall called for lwp %p!\n", l); /* system call accounting */ curcpu()->ci_data.cpu_nsyscall++; + LWP_CACHE_CREDS(l, l->l_proc); /* XXX do we want do do emulation? */ - LWP_CACHE_CREDS(l, l->l_proc); - /* TODO issue!! */ + md_syscall_get_syscallnumber(ucp, &code); + code &= (SYS_NSYSENT -1); + + callp = p->p_emul->e_sysent + code; + nargs = callp->sy_narg; + argsize = callp->sy_argsize; + + printf("syscall no. %d, ", code); + printf("nargs %d, argsize %d => ", nargs, argsize); + + args = copyargs; + rval[0] = rval[1] = 0; + error = md_syscall_getargs(l, ucp, nargs, argsize, args); + if (!error) + error = (*callp->sy_call)(l, args, rval); + + printf("error = %d, rval[0] = %"PRIx32", retval[1] = %"PRIx32"\n", + error, (uint) rval[0], (uint) rval[1]); + switch (error) { + default: + rval[0] = error; +// rval[1] = 0; + /* fall trough */ + case 0: + md_syscall_set_returnargs(l, ucp, rval); + /* fall trough */ + case EJUSTRETURN: + md_syscall_inc_pc(ucp); + break; + case ERESTART: + /* nothing to do */ + break; + } - printf("syscall no. %d\n", reg[11]); -/* skip instruction */ -reg[14] += 2; - -/* retval */ -reg[11] = 0; - printf("end of syscall : return to userland\n"); +// printf("end of syscall : return to userland\n"); userret(l); -printf("jump back to %p\n", (void *) reg[14]); } Index: src/sys/arch/usermode/usermode/trap.c diff -u src/sys/arch/usermode/usermode/trap.c:1.36 src/sys/arch/usermode/usermode/trap.c:1.37 --- src/sys/arch/usermode/usermode/trap.c:1.36 Thu Sep 8 15:13:27 2011 +++ src/sys/arch/usermode/usermode/trap.c Thu Sep 8 19:39:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.36 2011/09/08 15:13:27 reinoud Exp $ */ +/* $NetBSD: trap.c,v 1.37 2011/09/08 19:39:00 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.36 2011/09/08 15:13:27 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.37 2011/09/08 19:39:00 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -218,7 +218,7 @@ recurse--; return; } - panic("should deliver a trap to the process"); + panic("%s: should deliver a trap to the process", __func__); /* XXX HOWTO see arm/arm/syscall.c illegal instruction signal */ } @@ -239,12 +239,14 @@ struct pcb *pcb; vaddr_t va; + va = 0; + if (info->si_signo == SIGILL) { l = curlwp; p = l->l_proc; pcb = lwp_getpcb(l); -#if 1 +#if 0 va = (vaddr_t) info->si_addr; printf("illegal instruction trap lwp = %p pid = %d lid = %d, va = %p\n", curlwp, @@ -252,7 +254,7 @@ curlwp->l_lid, (void *) va); #endif -#if 1 +#if 0 printf("SIGILL!\n"); printf("\tsi_signo = %d\n", info->si_signo); printf("\tsi_errno = %d\n", info->si_errno); @@ -286,7 +288,7 @@ memcpy(&pcb->pcb_userland_ucp, uct, sizeof(ucontext_t)); /* if its a syscall, switch to the syscall entry */ - if (md_check_syscall_opcode(info->si_addr)) { + if (md_syscall_check_opcode(info->si_addr)) { thunk_setcontext(&pcb->pcb_syscall_ucp); /* NOT REACHED */ }