Module Name: src Committed By: reinoud Date: Sun Nov 27 21:38:17 UTC 2011
Modified Files: src/sys/arch/usermode/dev: cpu.c src/sys/arch/usermode/include: machdep.h param.h pcb.h src/sys/arch/usermode/usermode: machdep.c syscall.c trap.c urkelvisor.c Log Message: Big patch that changes the signal stack usage of urkel significantly. Formerly, all signals came on the signal stack and the two important ones were then forwared to either the system call or the pagefault handler. This worked fine but the signal stack remains that, a stack. When we go multi-process this stack gets corrupted and out-of-order with all kind of nastyness since a userland process switch can occure when a system call is called or when a process gets a page fault. The new scheme only uses the signal stack as a jumpboard. It swaps states and then returns from the signal, clearing the stack but instead of returning to the code it now jumpt to the handler and that handler then returns to the code when its finished. To generate a diff of this commit: cvs rdiff -u -r1.46 -r1.47 src/sys/arch/usermode/dev/cpu.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/usermode/include/machdep.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/usermode/include/param.h cvs rdiff -u -r1.12 -r1.13 src/sys/arch/usermode/include/pcb.h cvs rdiff -u -r1.32 -r1.33 src/sys/arch/usermode/usermode/machdep.c cvs rdiff -u -r1.10 -r1.11 src/sys/arch/usermode/usermode/syscall.c cvs rdiff -u -r1.41 -r1.42 src/sys/arch/usermode/usermode/trap.c cvs rdiff -u -r1.8 -r1.9 src/sys/arch/usermode/usermode/urkelvisor.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/dev/cpu.c diff -u src/sys/arch/usermode/dev/cpu.c:1.46 src/sys/arch/usermode/dev/cpu.c:1.47 --- src/sys/arch/usermode/dev/cpu.c:1.46 Wed Sep 14 18:30:13 2011 +++ src/sys/arch/usermode/dev/cpu.c Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.46 2011/09/14 18:30:13 reinoud Exp $ */ +/* $NetBSD: cpu.c,v 1.47 2011/11/27 21:38:17 reinoud Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -30,7 +30,7 @@ #include "opt_hz.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.46 2011/09/14 18:30:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.47 2011/11/27 21:38:17 reinoud Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -163,7 +163,7 @@ cpu_switchto(lwp_t *oldlwp, lwp_t *newlw struct cpu_info *ci = curcpu(); #ifdef CPU_DEBUG - printf("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n", + dprintf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n", oldlwp ? oldlwp->l_name : "none", oldlwp ? oldlwp->l_proc->p_pid : -1, oldlwp ? oldlwp->l_lid : -1, @@ -171,14 +171,14 @@ cpu_switchto(lwp_t *oldlwp, lwp_t *newlw newlwp ? newlwp->l_proc->p_pid : -1, newlwp ? newlwp->l_lid : -1); if (oldpcb) { - printf(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, " + dprintf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, " "uc_stack.ss_size=%d\n", oldpcb->pcb_ucp.uc_link, oldpcb->pcb_ucp.uc_stack.ss_sp, (int)oldpcb->pcb_ucp.uc_stack.ss_size); } if (newpcb) { - printf(" newpcb uc_link=%p, uc_stack.ss_sp=%p, " + dprintf_debug(" newpcb uc_link=%p, uc_stack.ss_sp=%p, " "uc_stack.ss_size=%d\n", newpcb->pcb_ucp.uc_link, newpcb->pcb_ucp.uc_stack.ss_sp, @@ -202,7 +202,7 @@ cpu_switchto(lwp_t *oldlwp, lwp_t *newlw } #ifdef CPU_DEBUG - printf("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); + dprintf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); #endif return ci->ci_stash; } @@ -211,7 +211,7 @@ void cpu_dumpconf(void) { #ifdef CPU_DEBUG - printf("cpu_dumpconf\n"); + dprintf_debug("cpu_dumpconf\n"); #endif } @@ -223,16 +223,18 @@ cpu_signotify(struct lwp *l) void cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) { + panic("cpu_getmcontext"); #ifdef CPU_DEBUG - printf("cpu_getmcontext\n"); + dprintf_debug("cpu_getmcontext\n"); #endif } int cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) { + panic("cpu_setmcontext"); #ifdef CPU_DEBUG - printf("cpu_setmcontext\n"); + dprintf_debug("cpu_setmcontext\n"); #endif return 0; } @@ -254,7 +256,7 @@ void cpu_lwp_free(struct lwp *l, int proc) { #ifdef CPU_DEBUG - printf("cpu_lwp_free\n"); + dprintf_debug("cpu_lwp_free (dummy)\n"); #endif } @@ -264,7 +266,7 @@ cpu_lwp_free2(struct lwp *l) struct pcb *pcb = lwp_getpcb(l); #ifdef CPU_DEBUG - printf("cpu_lwp_free2\n"); + dprintf_debug("cpu_lwp_free2\n"); #endif if (pcb == NULL) @@ -287,7 +289,7 @@ static void cpu_lwp_trampoline(ucontext_t *ucp, void (*func)(void *), void *arg) { #ifdef CPU_DEBUG - printf("cpu_lwp_trampoline called with func %p, arg %p\n", (void *) func, arg); + dprintf_debug("cpu_lwp_trampoline called with func %p, arg %p\n", (void *) func, arg); #endif /* init lwp */ lwp_startup(curcpu()->ci_stash, curlwp); @@ -303,10 +305,10 @@ cpu_lwp_fork(struct lwp *l1, struct lwp { struct pcb *pcb1 = lwp_getpcb(l1); struct pcb *pcb2 = lwp_getpcb(l2); - void *stack_ucp, *stack_syscall_ucp; + void *stack_ucp, *stack_syscall_ucp, *stack_pagefault_ucp; #ifdef CPU_DEBUG - printf("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n", + dprintf_debug("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n", l1 ? l1->l_name : "none", l1, l2 ? l2->l_name : "none", l2, stack, (int)stacksize); @@ -318,9 +320,10 @@ cpu_lwp_fork(struct lwp *l1, struct lwp /* copy the PCB and its switchframes from parent */ memcpy(pcb2, pcb1, sizeof(struct pcb)); - stacksize = 4*PAGE_SIZE; - stack_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); - stack_syscall_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); + stacksize = 16*PAGE_SIZE; + stack_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); + stack_syscall_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); + stack_pagefault_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); pcb2->pcb_needfree = true; if (thunk_getcontext(&pcb2->pcb_ucp)) @@ -329,8 +332,8 @@ cpu_lwp_fork(struct lwp *l1, struct lwp /* set up the ucontext for the userland switch */ pcb2->pcb_ucp.uc_stack.ss_sp = stack_ucp; pcb2->pcb_ucp.uc_stack.ss_size = stacksize; - pcb2->pcb_ucp.uc_link = &pcb2->pcb_userland_ucp; pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU; + pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp; thunk_makecontext(&pcb2->pcb_ucp, (void (*)(void)) cpu_lwp_trampoline, 3, &pcb2->pcb_ucp, func, arg); @@ -338,10 +341,18 @@ cpu_lwp_fork(struct lwp *l1, struct lwp /* set up the ucontext for the syscall */ pcb2->pcb_syscall_ucp.uc_stack.ss_sp = stack_syscall_ucp; pcb2->pcb_syscall_ucp.uc_stack.ss_size = stacksize; - pcb2->pcb_syscall_ucp.uc_flags = _UC_CPU; - pcb2->pcb_syscall_ucp.uc_link = &pcb2->pcb_userland_ucp; + pcb2->pcb_syscall_ucp.uc_flags = _UC_STACK | _UC_CPU; + pcb2->pcb_syscall_ucp.uc_link = &pcb2->pcb_userret_ucp; thunk_makecontext(&pcb2->pcb_syscall_ucp, (void (*)(void)) syscall, 0, NULL, NULL, NULL); + + /* set up the ucontext for the pagefault */ + pcb2->pcb_pagefault_ucp.uc_stack.ss_sp = stack_pagefault_ucp; + pcb2->pcb_pagefault_ucp.uc_stack.ss_size = stacksize; + pcb2->pcb_pagefault_ucp.uc_flags = _UC_STACK | _UC_CPU; + pcb2->pcb_pagefault_ucp.uc_link = &pcb2->pcb_trapret_ucp; + thunk_makecontext(&pcb2->pcb_pagefault_ucp, (void (*)(void)) pagefault, + 0, NULL, NULL, NULL); } void @@ -358,6 +369,9 @@ cpu_initclocks(void) void cpu_startup(void) { + size_t stacksize; + void *stack_pagefault_ucp; + msgbuf = thunk_malloc(PAGE_SIZE); if (msgbuf == NULL) panic("couldn't allocate msgbuf"); @@ -370,9 +384,22 @@ cpu_startup(void) panic("getcontext failed"); uvm_lwp_setuarea(&lwp0, (vaddr_t)&lwp0pcb); - /* init trapframe (going nowhere!), maybe a panic func? */ - memcpy(&lwp0pcb.pcb_userland_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); - memcpy(&lwp0pcb.pcb_syscall_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); + /* init trapframes (going nowhere!), maybe a panic func? */ + memcpy(&lwp0pcb.pcb_syscall_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); + memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); + memcpy(&lwp0pcb.pcb_pagefault_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); + memcpy(&lwp0pcb.pcb_trapret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); + + /* set up the ucontext for the pagefault */ + stacksize = 16*PAGE_SIZE; + stack_pagefault_ucp = malloc(stacksize, M_TEMP, M_NOWAIT); + + lwp0pcb.pcb_pagefault_ucp.uc_stack.ss_sp = stack_pagefault_ucp; + lwp0pcb.pcb_pagefault_ucp.uc_stack.ss_size = stacksize; + lwp0pcb.pcb_pagefault_ucp.uc_flags = _UC_STACK | _UC_CPU; + lwp0pcb.pcb_pagefault_ucp.uc_link = &lwp0pcb.pcb_userret_ucp; + thunk_makecontext(&lwp0pcb.pcb_pagefault_ucp, (void (*)(void)) pagefault, + 0, NULL, NULL, NULL); } void Index: src/sys/arch/usermode/include/machdep.h diff -u src/sys/arch/usermode/include/machdep.h:1.3 src/sys/arch/usermode/include/machdep.h:1.4 --- src/sys/arch/usermode/include/machdep.h:1.3 Fri Sep 9 12:44:27 2011 +++ src/sys/arch/usermode/include/machdep.h Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.h,v 1.3 2011/09/09 12:44:27 reinoud Exp $ */ +/* $NetBSD: machdep.h,v 1.4 2011/11/27 21:38:17 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -27,12 +27,16 @@ */ int md_syscall_check_opcode(void *ptr); +void md_syscall_get_opcode(ucontext_t *ucp, uint32_t *opcode); 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, int error, register_t *rval); -void md_syscall_inc_pc(ucontext_t *ucp); +void md_syscall_inc_pc(ucontext_t *ucp, uint32_t opcode); +void md_syscall_dec_pc(ucontext_t *ucp, uint32_t opcode); +/* handlers */ void syscall(void); +void pagefault(void); Index: src/sys/arch/usermode/include/param.h diff -u src/sys/arch/usermode/include/param.h:1.4 src/sys/arch/usermode/include/param.h:1.5 --- src/sys/arch/usermode/include/param.h:1.4 Thu Sep 8 10:49:57 2011 +++ src/sys/arch/usermode/include/param.h Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.4 2011/09/08 10:49:57 jmcneill Exp $ */ +/* $NetBSD: param.h,v 1.5 2011/11/27 21:38:17 reinoud Exp $ */ /* * Automatically generated by genheaders.sh on Thu Sep 8 06:50:18 EDT 2011 @@ -14,7 +14,9 @@ #else #error port me #endif +#undef UPAGES +#define UPAGES 6 #undef USPACE -#define USPACE (PAGE_SIZE*4) +#define USPACE (PAGE_SIZE*UPAGES) #endif Index: src/sys/arch/usermode/include/pcb.h diff -u src/sys/arch/usermode/include/pcb.h:1.12 src/sys/arch/usermode/include/pcb.h:1.13 --- src/sys/arch/usermode/include/pcb.h:1.12 Thu Sep 8 19:37:01 2011 +++ src/sys/arch/usermode/include/pcb.h Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pcb.h,v 1.12 2011/09/08 19:37:01 reinoud Exp $ */ +/* $NetBSD: pcb.h,v 1.13 2011/11/27 21:38:17 reinoud Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -41,13 +41,16 @@ struct pcb { ucontext_t pcb_ucp; /* lwp switchframe */ - ucontext_t pcb_userland_ucp; /* userland switchframe */ - ucontext_t pcb_syscall_ucp; /* to switch to for syscall */ + ucontext_t pcb_syscall_ucp; /* syscall context */ + ucontext_t pcb_userret_ucp; /* reutn to userland context */ + ucontext_t pcb_pagefault_ucp; /* pagefault context */ + ucontext_t pcb_trapret_ucp; bool pcb_needfree; void * pcb_onfault; /* on fault handler */ int pcb_errno; /* save/restore place */ + vaddr_t pcb_fault_addr; /* save place for fault addr */ }; #endif /* !_ARCH_USERMODE_INCLUDE_PCB_H */ Index: src/sys/arch/usermode/usermode/machdep.c diff -u src/sys/arch/usermode/usermode/machdep.c:1.32 src/sys/arch/usermode/usermode/machdep.c:1.33 --- src/sys/arch/usermode/usermode/machdep.c:1.32 Fri Sep 16 16:26:19 2011 +++ src/sys/arch/usermode/usermode/machdep.c Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.32 2011/09/16 16:26:19 reinoud Exp $ */ +/* $NetBSD: machdep.c,v 1.33 2011/11/27 21:38:17 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.32 2011/09/16 16:26:19 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.33 2011/11/27 21:38:17 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -176,7 +176,7 @@ void setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) { struct pcb *pcb = lwp_getpcb(l); - ucontext_t *ucp = &pcb->pcb_userland_ucp; + ucontext_t *ucp = &pcb->pcb_userret_ucp; uint *reg, i; #ifdef DEBUG_EXEC @@ -187,10 +187,10 @@ setregs(struct lwp *l, struct exec_packa pcb->pcb_ucp.uc_stack.ss_sp); printf("\tpcb->pcb_ucp.uc_stack.ss_size = %d\n", (int) pcb->pcb_ucp.uc_stack.ss_size); - printf("\tpcb->pcb_userland_ucp.uc_stack.ss_sp = %p\n", - pcb->pcb_userland_ucp.uc_stack.ss_sp); - printf("\tpcb->pcb_userland_ucp.uc_stack.ss_size = %d\n", - (int) pcb->pcb_userland_ucp.uc_stack.ss_size); + printf("\tpcb->pcb_userret_ucp.uc_stack.ss_sp = %p\n", + pcb->pcb_userret_ucp.uc_stack.ss_sp); + printf("\tpcb->pcb_userret_ucp.uc_stack.ss_size = %d\n", + (int) pcb->pcb_userret_ucp.uc_stack.ss_size); #endif reg = (int *) &ucp->uc_mcontext; @@ -213,10 +213,10 @@ setregs(struct lwp *l, struct exec_packa pcb->pcb_ucp.uc_stack.ss_sp); printf("\tpcb->pcb_ucp.uc_stack.ss_size = %d\n", (int) pcb->pcb_ucp.uc_stack.ss_size); - printf("\tpcb->pcb_userland_ucp.uc_stack.ss_sp = %p\n", - pcb->pcb_userland_ucp.uc_stack.ss_sp); - printf("\tpcb->pcb_userland_ucp.uc_stack.ss_size = %d\n", - (int) pcb->pcb_userland_ucp.uc_stack.ss_size); + printf("\tpcb->pcb_userret_ucp.uc_stack.ss_sp = %p\n", + pcb->pcb_userret_ucp.uc_stack.ss_sp); + printf("\tpcb->pcb_userret_ucp.uc_stack.ss_size = %d\n", + (int) pcb->pcb_userret_ucp.uc_stack.ss_size); printf("\tpack->ep_entry = %p\n", (void *) pack->ep_entry); #endif @@ -226,7 +226,6 @@ void md_syscall_get_syscallnumber(ucontext_t *ucp, uint32_t *code) { uint *reg = (int *) &ucp->uc_mcontext; - *code = reg[11]; /* EAX */ } @@ -241,16 +240,6 @@ md_syscall_getargs(lwp_t *l, ucontext_t //dump_regs(reg); 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 (int i = 0; i < nargs; i++) - printf("arg[%02d] = %"PRIx32", ", i, (uint) args[i]); - printf("\n"); -#endif - return ret; } @@ -287,26 +276,52 @@ md_syscall_check_opcode(void *ptr) return 1; /* TODO int $80 and sysenter */ - return 0; } void -md_syscall_inc_pc(ucontext_t *ucp) +md_syscall_get_opcode(ucontext_t *ucp, uint32_t *opcode) { uint *reg = (int *) &ucp->uc_mcontext; - uint16_t *p16; +// uint8_t *p8 = (uint8_t *) (reg[14]); + uint16_t *p16 = (uint16_t*) (reg[14]); + + *opcode = 0; - /* advance program counter */ - p16 = (uint16_t *) reg[14]; if (*p16 == 0xff0f) - reg[14] += 2; /* EIP */ + *opcode = *p16; if (*p16 == 0xff0b) + *opcode = *p16; + + /* TODO int $80 and sysenter */ +} + +void +md_syscall_inc_pc(ucontext_t *ucp, uint32_t opcode) +{ + uint *reg = (int *) &ucp->uc_mcontext; + + /* advance program counter */ + if (opcode == 0xff0f) + reg[14] += 2; /* EIP */ + if (opcode == 0xff0b) reg[14] += 2; /* EIP */ /* TODO int $80 and sysenter */ +} - // printf("jump back to %p\n", (void *) reg[14]); +void +md_syscall_dec_pc(ucontext_t *ucp, uint32_t opcode) +{ + uint *reg = (int *) &ucp->uc_mcontext; + + /* advance program counter */ + if (opcode == 0xff0f) + reg[14] -= 2; /* EIP */ + if (opcode == 0xff0b) + reg[14] -= 2; /* EIP */ + + /* TODO int $80 and sysenter */ } Index: src/sys/arch/usermode/usermode/syscall.c diff -u src/sys/arch/usermode/usermode/syscall.c:1.10 src/sys/arch/usermode/usermode/syscall.c:1.11 --- src/sys/arch/usermode/usermode/syscall.c:1.10 Thu Sep 15 12:26:51 2011 +++ src/sys/arch/usermode/usermode/syscall.c Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.c,v 1.10 2011/09/15 12:26:51 reinoud Exp $ */ +/* $NetBSD: syscall.c,v 1.11 2011/11/27 21:38:17 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.10 2011/09/15 12:26:51 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.11 2011/11/27 21:38:17 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -69,6 +69,8 @@ child_return(void *arg) ktrsysret(SYS_fork, 0, 0); } +extern const char *const syscallnames[]; + void syscall(void) { @@ -76,11 +78,11 @@ syscall(void) 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; + ucontext_t *ucp = &pcb->pcb_userret_ucp; register_t copyargs[2+SYS_MAXSYSARGS]; register_t *args; register_t rval[2]; - uint32_t code; + uint32_t code, opcode; uint nargs, argsize; int error; @@ -89,6 +91,7 @@ syscall(void) LWP_CACHE_CREDS(l, l->l_proc); /* XXX do we want do do emulation? */ + md_syscall_get_opcode(ucp, &opcode); md_syscall_get_syscallnumber(ucp, &code); code &= (SYS_NSYSENT -1); @@ -100,51 +103,41 @@ syscall(void) rval[0] = rval[1] = 0; error = md_syscall_getargs(l, ucp, nargs, argsize, args); + if (code != 4) { + printf("code %3d, nargs %d, argsize %3d\t%s(", + code, nargs, argsize, syscallnames[code]); + for (int i = 0; i < nargs; i++) + printf("%"PRIx32", ", (uint) args[i]); + if (nargs) + printf("\b\b"); + printf(") "); + } #if 0 aprint_debug("syscall no. %d, ", code); aprint_debug("nargs %d, argsize %d => ", nargs, argsize); dprintf_debug("syscall no. %d, ", code); dprintf_debug("nargs %d, argsize %d => ", nargs, argsize); #endif +#if 0 if ((code == 4)) { dprintf_debug("[us] %s", (char *) args[1]); printf("[us] %s", (char *) args[1]); } - - if (code == 5) - aprint_debug("open('%s', %d,...) => ", (char *) (args[0]), - (int) (args[1])); -#if 0 - - if (code == 3) - aprint_debug("read(%d, %p, %d) => ", (int) args[0], - (void *) args[1], (int) args[2]); -#if 0 - if (code == 4) - aprint_debug("write(%d, %p ('%s'), %d) => ", - (int) args[0], (void *) args[1], - (char *) args[1], (int) args[2]); - if (code == 5) - aprint_debug("open('%s', %d,...) => ", (char *) (args[0]), - (int) (args[1])); #endif if (code == 440) - aprint_debug("stat(%d, %p) => ", (uint32_t) args[0], + printf("stat(%d, %p) ", (uint32_t) args[0], (void *) args[1]); -#endif + + md_syscall_inc_pc(ucp, opcode); if (!error) error = (*callp->sy_call)(l, args, rval); - if (code == 5) - aprint_debug("%s\n", error ? "error":"OK"); -#if 0 - if (code ==3) - aprint_debug("{'%s'} => ", (char *) args[1]); - aprint_debug("error = %d, rval[0] = 0x%"PRIx32", retval[1] = 0x%"PRIx32"\n", - error, (uint) (rval[0]), (uint) (rval[1])); -#endif + if (code != 4) + printf("=> %s: %d, (%"PRIx32", %"PRIx32")\n", + error?"ERROR":"OK", error, (uint) (rval[0]), (uint) (rval[1])); +//out: switch (error) { default: /* fall trough */ @@ -152,14 +145,14 @@ syscall(void) md_syscall_set_returnargs(l, ucp, error, rval); /* fall trough */ case EJUSTRETURN: - md_syscall_inc_pc(ucp); break; case ERESTART: + md_syscall_dec_pc(ucp, opcode); /* nothing to do */ break; } - -// aprint_debug("end of syscall : return to userland\n"); + //dprintf_debug("end of syscall : return to userland\n"); +//if (code != 4) printf("userret() code %d\n", code); userret(l); } Index: src/sys/arch/usermode/usermode/trap.c diff -u src/sys/arch/usermode/usermode/trap.c:1.41 src/sys/arch/usermode/usermode/trap.c:1.42 --- src/sys/arch/usermode/usermode/trap.c:1.41 Fri Sep 16 16:29:11 2011 +++ src/sys/arch/usermode/usermode/trap.c Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.41 2011/09/16 16:29:11 reinoud Exp $ */ +/* $NetBSD: trap.c,v 1.42 2011/11/27 21:38:17 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.41 2011/09/16 16:29:11 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.42 2011/11/27 21:38:17 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -89,7 +89,7 @@ setup_signal_handlers(void) if (thunk_sigaction(SIGBUS, &sa, NULL) == -1) panic("couldn't register SIGBUS handler : %d", thunk_geterrno()); - sa.sa_flags = SA_RESTART | SA_SIGINFO; + sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sa.sa_sigaction = illegal_instruction_handler; thunk_sigemptyset(&sa.sa_mask); // thunk_sigaddset(&sa.sa_mask, SIGALRM); @@ -103,197 +103,227 @@ setup_signal_handlers(void) static void mem_access_handler(int sig, siginfo_t *info, void *ctx) { - static volatile int recurse = 0; - static vaddr_t old_va, old_old_va = 0; - - struct proc *p; + ucontext_t *uct = ctx; struct lwp *l; struct pcb *pcb; - struct vmspace *vm; - struct vm_map *vm_map; - vm_prot_t atype; vaddr_t va; - void *onfault; - int kmem, lwp_errno, rv; - recurse++; - if (recurse > 1) - dprintf_debug("%s: enter trap recursion level %d\n", __func__, recurse); - if ((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS)) { - l = curlwp; - p = l->l_proc; - pcb = lwp_getpcb(l); - onfault = pcb->pcb_onfault; - vm = p->p_vmspace; + assert((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS)); + + if (info->si_code == SI_NOINFO) + panic("received signal %d with no info", + info->si_signo); - lwp_errno = pcb->pcb_errno = thunk_geterrno(); +//printf("sigsegv\n"); #if 0 - va = (vaddr_t) info->si_addr; - dprintf_debug("mem trap lwp = %p pid = %d lid = %d, va = %p\n", - curlwp, - curlwp->l_proc->p_pid, - curlwp->l_lid, - (void *) va); + va = (vaddr_t) info->si_addr; + dprintf_debug("mem trap lwp = %p pid = %d lid = %d, va = %p\n", + curlwp, + curlwp->l_proc->p_pid, + curlwp->l_lid, + (void *) va); #endif #if 0 - dprintf_debug("SIGSEGV or SIGBUS!\n"); - dprintf_debug("\tsi_signo = %d\n", info->si_signo); - dprintf_debug("\tsi_errno = %d\n", info->si_errno); - dprintf_debug("\tsi_code = %d\n", info->si_code); - if (info->si_code == SEGV_MAPERR) - dprintf_debug("\t\tSEGV_MAPERR\n"); - if (info->si_code == SEGV_ACCERR) - dprintf_debug("\t\tSEGV_ACCERR\n"); - if (info->si_code == BUS_ADRALN) - dprintf_debug("\t\tBUS_ADRALN\n"); - if (info->si_code == BUS_ADRERR) - dprintf_debug("\t\tBUS_ADRERR\n"); - if (info->si_code == BUS_OBJERR) - dprintf_debug("\t\tBUS_OBJERR\n"); - dprintf_debug("\tsi_addr = %p\n", info->si_addr); - dprintf_debug("\tsi_trap = %d\n", info->si_trap); + dprintf_debug("SIGSEGV or SIGBUS!\n"); + dprintf_debug("\tsi_signo = %d\n", info->si_signo); + dprintf_debug("\tsi_errno = %d\n", info->si_errno); + dprintf_debug("\tsi_code = %d\n", info->si_code); + if (info->si_code == SEGV_MAPERR) + dprintf_debug("\t\tSEGV_MAPERR\n"); + if (info->si_code == SEGV_ACCERR) + dprintf_debug("\t\tSEGV_ACCERR\n"); + if (info->si_code == BUS_ADRALN) + dprintf_debug("\t\tBUS_ADRALN\n"); + if (info->si_code == BUS_ADRERR) + dprintf_debug("\t\tBUS_ADRERR\n"); + if (info->si_code == BUS_OBJERR) + dprintf_debug("\t\tBUS_OBJERR\n"); + dprintf_debug("\tsi_addr = %p\n", info->si_addr); + dprintf_debug("\tsi_trap = %d\n", info->si_trap); #endif - if (info->si_code == SI_NOINFO) - panic("received signal %d with no info", - info->si_signo); - - va = (vaddr_t) info->si_addr; - va = trunc_page(va); - - /* sanity */ - if ((va < VM_MIN_ADDRESS) || (va >= VM_MAX_ADDRESS)) - panic("peeing outside the box! (va=%p)", (void *)va); - - /* extra debug for now -> should issue signal */ - if (va == 0) - panic("NULL deref\n"); - - kmem = 1; - vm_map = kernel_map; - if ((va >= VM_MIN_ADDRESS) && (va < VM_MAXUSER_ADDRESS)) { - kmem = 0; - vm_map = &vm->vm_map; - } + l = curlwp; + pcb = lwp_getpcb(l); - /* can pmap handle it? on its own? (r/m) */ - rv = 0; - if (!pmap_fault(vm_map->pmap, va, &atype)) { - dprintf_debug("pmap fault couldn't handle it! : " - "derived atype %d\n", atype); - - /* extra debug for now */ - if (pcb == 0) - panic("NULL pcb!\n"); - - pcb->pcb_onfault = NULL; - rv = uvm_fault(vm_map, va, atype); - pcb->pcb_onfault = onfault; - } + va = (vaddr_t) info->si_addr; + va = trunc_page(va); -#if 0 - if (old_old_va) - thunk_pwrite(debug_fh, (void *) old_old_va, PAGE_SIZE, old_old_va); - if (old_va) - thunk_pwrite(debug_fh, (void *) old_va, PAGE_SIZE, old_va); - thunk_pwrite(debug_fh, (void *) va, PAGE_SIZE, va); +#ifdef DIAGNOSTIC + /* sanity */ + if ((va < VM_MIN_ADDRESS) || (va >= VM_MAX_ADDRESS)) + panic("peeing outside the box! (va=%p)", (void *)va); + + /* extra debug for now -> should issue signal */ + if (va == 0) + panic("NULL deref\n"); #endif - old_old_va = old_va; - old_va = va; - if (rv) { - dprintf_debug("uvm_fault returned error %d\n", rv); +//printf("memaccess error : va = %p\n", (void *) va); + /* copy this state to return to */ + memcpy(&pcb->pcb_trapret_ucp, uct, sizeof(ucontext_t)); + + /* remember our parameters */ +// assert((void *) pcb->pcb_fault_addr == NULL); + pcb->pcb_fault_addr = va; - /* something got wrong */ - if (kmem) { - /* copyin / copyout */ - if (!onfault) - panic("kernel fault"); - panic("%s: can't call onfault yet\n", __func__); - /* jump to given onfault */ - // tf = &kernel_tf; - // memset(tf, 0, sizeof(struct trapframe)); - // tf->tf_pc = onfault; - // tf->tf_io[0] = (rv == EACCES) ? EFAULT : rv; - recurse--; - return; - } - panic("%s: should deliver a trap to the process for va %p", __func__, (void *) va); - /* XXX HOWTO see arm/arm/syscall.c illegal instruction signal */ - } - - thunk_seterrno(lwp_errno); - pcb->pcb_errno = lwp_errno; - } - if (recurse > 1) - dprintf_debug("%s: leaving trap recursion level %d\n", __func__, recurse); - recurse--; + /* switch to the pagefault entry on return from signal */ + memcpy(uct, &pcb->pcb_pagefault_ucp, sizeof(ucontext_t)); } + static void illegal_instruction_handler(int sig, siginfo_t *info, void *ctx) { ucontext_t *uct = ctx; + struct lwp *l; + struct pcb *pcb; + + assert(info->si_signo == SIGILL); +#if 0 + sigset_t ss; + thunk_sigemptyset(&ss); + thunk_sigaddset(&ss, SIGALRM); + thunk_sigaddset(&ss, SIGILL); + thunk_sigprocmask(SIG_UNBLOCK, &ss, NULL); +#endif + +#if 0 + printf("\nillegal instruction trap lwp = %p pid = %d lid = %d, va = %p\n", + curlwp, + curlwp->l_proc->p_pid, + curlwp->l_lid, + (void *) info->si_addr); +#endif +#if 0 + printf("SIGILL!\n"); + printf("\tsi_signo = %d\n", info->si_signo); + printf("\tsi_errno = %d\n", info->si_errno); + printf("\tsi_code = %d\n", info->si_code); + if (info->si_code == ILL_ILLOPC) + printf("\t\tIllegal opcode"); + if (info->si_code == ILL_ILLOPN) + printf("\t\tIllegal operand"); + if (info->si_code == ILL_ILLADR) + printf("\t\tIllegal addressing mode"); + if (info->si_code == ILL_ILLTRP) + printf("\t\tIllegal trap"); + if (info->si_code == ILL_PRVOPC) + printf("\t\tPrivileged opcode"); + if (info->si_code == ILL_PRVREG) + printf("\t\tPrivileged register"); + if (info->si_code == ILL_COPROC) + printf("\t\tCoprocessor error"); + if (info->si_code == ILL_BADSTK) + printf("\t\tInternal stack error"); + printf("\tsi_addr = %p\n", info->si_addr); + printf("\tsi_trap = %d\n", info->si_trap); + + printf("%p : ", info->si_addr); + for (int i = 0; i < 10; i++) + printf("%02x ", *((uint8_t *) info->si_addr + i)); + printf("\n"); +#endif + + l = curlwp; + pcb = lwp_getpcb(l); + + /* copy this state to return to */ + memcpy(&pcb->pcb_userret_ucp, uct, sizeof(ucontext_t)); + + /* if its a syscall ... */ + if (md_syscall_check_opcode(info->si_addr)) { + /* switch to the syscall entry on return from signal */ + memcpy(uct, &pcb->pcb_syscall_ucp, sizeof(ucontext_t)); + return; + } + + panic("should deliver a trap to the process : illegal instruction " + "encountered\n"); +} + + +/* + * Entry point from the segv handler; check if its a pmap reference fault or + * let uvm handle it. + */ +void +pagefault(void) +{ struct proc *p; struct lwp *l; struct pcb *pcb; + struct vmspace *vm; + struct vm_map *vm_map; + vm_prot_t atype; vaddr_t va; + void *onfault; + int kmem, lwp_errno, rv; +static vaddr_t old_va, old_old_va = 0; - va = 0; + l = curlwp; + pcb = lwp_getpcb(l); + p = l->l_proc; + vm = p->p_vmspace; + va = pcb->pcb_fault_addr; + + lwp_errno = thunk_geterrno(); + + kmem = 1; + vm_map = kernel_map; + if ((va >= VM_MIN_ADDRESS) && (va < VM_MAXUSER_ADDRESS)) { + kmem = 0; + vm_map = &vm->vm_map; + } - if (info->si_signo == SIGILL) { - l = curlwp; - p = l->l_proc; - pcb = lwp_getpcb(l); +dprintf_debug("pagefault : va = %p\n", (void *) va); + /* can pmap handle it? on its own? (r/m) */ + onfault = pcb->pcb_onfault; + rv = 0; + if (!pmap_fault(vm_map->pmap, va, &atype)) { + dprintf_debug("pmap fault couldn't handle it! : " + "derived atype %d\n", atype); + + /* extra debug for now */ + if (pcb == 0) + panic("NULL pcb!\n"); + + pcb->pcb_onfault = NULL; + rv = uvm_fault(vm_map, va, atype); + pcb->pcb_onfault = onfault; + } #if 0 - va = (vaddr_t) info->si_addr; - printf("\nillegal instruction trap lwp = %p pid = %d lid = %d, va = %p\n", - curlwp, - curlwp->l_proc->p_pid, - curlwp->l_lid, - (void *) va); -#endif -#if 0 - printf("SIGILL!\n"); - printf("\tsi_signo = %d\n", info->si_signo); - printf("\tsi_errno = %d\n", info->si_errno); - printf("\tsi_code = %d\n", info->si_code); - if (info->si_code == ILL_ILLOPC) - printf("\t\tIllegal opcode"); - if (info->si_code == ILL_ILLOPN) - printf("\t\tIllegal operand"); - if (info->si_code == ILL_ILLADR) - printf("\t\tIllegal addressing mode"); - if (info->si_code == ILL_ILLTRP) - printf("\t\tIllegal trap"); - if (info->si_code == ILL_PRVOPC) - printf("\t\tPrivileged opcode"); - if (info->si_code == ILL_PRVREG) - printf("\t\tPrivileged register"); - if (info->si_code == ILL_COPROC) - printf("\t\tCoprocessor error"); - if (info->si_code == ILL_BADSTK) - printf("\t\tInternal stack error"); - printf("\tsi_addr = %p\n", info->si_addr); - printf("\tsi_trap = %d\n", info->si_trap); - - printf("%p : ", info->si_addr); - for (int i = 0; i < 10; i++) - printf("%02x ", *((uint8_t *) info->si_addr + i)); - printf("\n"); +if (old_old_va) + thunk_pwrite(debug_fh, (void *) old_old_va, PAGE_SIZE, old_old_va); +if (old_va) + thunk_pwrite(debug_fh, (void *) old_va, PAGE_SIZE, old_va); +thunk_pwrite(debug_fh, (void *) va, PAGE_SIZE, va); #endif +old_old_va = old_va; +old_va = va; - /* copy this state to return to */ - memcpy(&pcb->pcb_userland_ucp, uct, sizeof(ucontext_t)); + if (rv) { + dprintf_debug("uvm_fault returned error %d\n", rv); - /* if its a syscall, switch to the syscall entry */ - if (md_syscall_check_opcode(info->si_addr)) { - thunk_setcontext(&pcb->pcb_syscall_ucp); - /* NOT REACHED */ + /* something got wrong */ + if (kmem) { + /* copyin / copyout */ + if (!onfault) + panic("kernel fault"); + panic("%s: can't call onfault yet\n", __func__); + /* jump to given onfault */ + // tf = &kernel_tf; + // memset(tf, 0, sizeof(struct trapframe)); + // tf->tf_pc = onfault; + // tf->tf_io[0] = (rv == EACCES) ? EFAULT : rv; + return; } - - panic("should deliver a trap to the process : illegal instruction " - "encountered\n"); + panic("%s: should deliver a trap to the process for va %p", __func__, (void *) va); + /* XXX HOWTO see arm/arm/syscall.c illegal instruction signal */ } + + thunk_seterrno(lwp_errno); + pcb->pcb_errno = lwp_errno; } + + Index: src/sys/arch/usermode/usermode/urkelvisor.c diff -u src/sys/arch/usermode/usermode/urkelvisor.c:1.8 src/sys/arch/usermode/usermode/urkelvisor.c:1.9 --- src/sys/arch/usermode/usermode/urkelvisor.c:1.8 Tue Sep 6 09:55:04 2011 +++ src/sys/arch/usermode/usermode/urkelvisor.c Sun Nov 27 21:38:17 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: urkelvisor.c,v 1.8 2011/09/06 09:55:04 jmcneill Exp $ */ +/* $NetBSD: urkelvisor.c,v 1.9 2011/11/27 21:38:17 reinoud Exp $ */ /*- * Copyright (c) 2011 Jared D. McNeill <jmcne...@invisible.ca> @@ -32,7 +32,7 @@ #include <sys/cdefs.h> #ifdef __NetBSD__ -__RCSID("$NetBSD: urkelvisor.c,v 1.8 2011/09/06 09:55:04 jmcneill Exp $"); +__RCSID("$NetBSD: urkelvisor.c,v 1.9 2011/11/27 21:38:17 reinoud Exp $"); #endif #include <sys/types.h> @@ -121,8 +121,8 @@ handle_syscall(struct reg_struct *puregs pc = (vaddr_t)R_PC(puregs); inkernel = !(pc >= kmem_user_start && pc < kmem_user_end); - //fprintf(stderr, "%s: pid=%d pc=%p inkernel=%d\n", - // __func__, urkel_pid, (void *)R_PC(puregs), inkernel); +// fprintf(stderr, "%s: pid=%d pc=%p inkernel=%d\n", +// __func__, urkel_pid, (void *)R_PC(puregs), inkernel); if (!inkernel) { fprintf(stderr, "caught syscall %d\n", (int)R_SYSCALL(puregs));