Module Name: src Committed By: reinoud Date: Mon Aug 29 14:59:09 UTC 2011
Modified Files: src/sys/arch/usermode/usermode: pmap.c trap.c Log Message: Implement read and modify detection code To generate a diff of this commit: cvs rdiff -u -r1.38 -r1.39 src/sys/arch/usermode/usermode/pmap.c cvs rdiff -u -r1.12 -r1.13 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/usermode/pmap.c diff -u src/sys/arch/usermode/usermode/pmap.c:1.38 src/sys/arch/usermode/usermode/pmap.c:1.39 --- src/sys/arch/usermode/usermode/pmap.c:1.38 Sat Aug 27 17:59:24 2011 +++ src/sys/arch/usermode/usermode/pmap.c Mon Aug 29 14:59:09 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.38 2011/08/27 17:59:24 reinoud Exp $ */ +/* $NetBSD: pmap.c,v 1.39 2011/08/29 14:59:09 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.38 2011/08/27 17:59:24 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.39 2011/08/29 14:59:09 reinoud Exp $"); #include "opt_memsize.h" #include "opt_kmempages.h" @@ -90,6 +90,8 @@ static void pv_update(struct pv_entry *pv); static void pmap_update_page(uintptr_t ppn); +void pmap_get_current_protection(pmap_t pmap, vaddr_t va, + vm_prot_t *cur_prot, vm_prot_t *prot); static struct pv_entry *pv_get(pmap_t pmap, uintptr_t ppn, uintptr_t lpn); static struct pv_entry *pv_alloc(void); static void pv_free(struct pv_entry *pv); @@ -421,6 +423,39 @@ return pv; } +void +pmap_get_current_protection(pmap_t pmap, vaddr_t va, + vm_prot_t *cur_prot, vm_prot_t *prot) +{ + struct pv_entry *pv; + + uintptr_t lpn; + + aprint_debug("pmap_get_current_protection pmap %p, va %p\n", pmap, (void *) va); +#ifdef DIAGNOSTIC + if ((va < VM_MIN_ADDRESS) || (va >= VM_MAX_ADDRESS)) + panic("pmap_do_enter: invalid va isued\n"); +#endif + + lpn = atop(va - VM_MIN_ADDRESS); /* V->L */ + + /* raise interupt level */ + pv = pmap->pm_entries[lpn]; + if (pv == NULL) { + *cur_prot = *prot = VM_PROT_NONE; + return; + } + + *prot = pv->pv_prot; + *cur_prot = VM_PROT_NONE; + if (pv->pv_mmap_ppl & PROT_READ) + *cur_prot |= VM_PROT_READ; + if (pv->pv_mmap_ppl & PROT_WRITE) + *cur_prot |= VM_PROT_WRITE; + if (pv->pv_mmap_ppl & PROT_EXEC) + *cur_prot |= VM_PROT_EXECUTE; +} + static void pmap_page_activate(struct pv_entry *pv) { @@ -660,6 +695,10 @@ /* TODO protect against roque values */ aprint_debug("pmap_extract: extracting va %p\n", (void *) va); +#ifdef DIAGNOSTIC + if ((va < VM_MIN_ADDRESS) || (va > VM_MAX_ADDRESS)) + panic("pmap_extract: invalid va isued\n"); +#endif pv = pmap->pm_entries[atop(va - VM_MIN_ADDRESS)]; /* V->L */ if (pv == NULL) Index: src/sys/arch/usermode/usermode/trap.c diff -u src/sys/arch/usermode/usermode/trap.c:1.12 src/sys/arch/usermode/usermode/trap.c:1.13 --- src/sys/arch/usermode/usermode/trap.c:1.12 Mon Aug 29 13:15:54 2011 +++ src/sys/arch/usermode/usermode/trap.c Mon Aug 29 14:59:09 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.12 2011/08/29 13:15:54 jmcneill Exp $ */ +/* $NetBSD: trap.c,v 1.13 2011/08/29 14:59:09 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.12 2011/08/29 13:15:54 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.13 2011/08/29 14:59:09 reinoud Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -49,11 +49,12 @@ //#include <machine/userret.h> +/* forwards and externals */ void setup_signal_handlers(void); static void mem_access_handler(int sig, siginfo_t *info, void *ctx); - -static struct sigaction sa; +extern void pmap_get_current_protection(pmap_t pmap, vaddr_t va, + vm_prot_t *cur_prot, vm_prot_t *prot); extern int errno; void @@ -64,6 +65,8 @@ void setup_signal_handlers(void) { + static struct sigaction sa; + sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_SIGINFO; sa.sa_sigaction = mem_access_handler; @@ -84,7 +87,7 @@ struct vmspace *vm; struct vm_map *vm_map; struct trapframe *tf; - vm_prot_t atype; + vm_prot_t cur_prot, prot, atype; vaddr_t va; vaddr_t onfault; int kmem, rv; @@ -104,7 +107,7 @@ onfault = (vaddr_t) pcb->pcb_onfault; vm = p->p_vmspace; -#if 0 +#if 1 printf("SIGSEGV or SIGBUS!\n"); printf("\tsi_signo = %d\n", info->si_signo); printf("\tsi_errno = %d\n", info->si_errno); @@ -141,17 +144,39 @@ panic("peeing outside the box!"); } - /* XXX TODO determine atype?? */ -atype = PROT_READ; -again: - pcb->pcb_onfault = NULL; - rv = uvm_fault(vm_map, (vaddr_t) va, atype); - pcb->pcb_onfault = (void *) onfault; -if (rv) printf("uvm_fault rv = %d\n", rv); -if (rv == EACCES) { - atype |= PROT_WRITE | PROT_EXEC; - goto again; -} + /* determine accesstype */ + pmap_get_current_protection(vm_map->pmap, va, &cur_prot, &prot); + rv = 0; + if ((prot == VM_PROT_NONE) && (cur_prot == VM_PROT_NONE)) { + /* not mapped in yet */ +printf("was not mapped in yet --> faulting read first\n"); + pcb->pcb_onfault = NULL; + rv = uvm_fault(vm_map, (vaddr_t) va, VM_PROT_READ); + pcb->pcb_onfault = (void *) onfault; + + /* update accesstypes */ + pmap_get_current_protection(vm_map->pmap, va, &cur_prot, &prot); + } + + /* if no error, its map-able */ + if (rv == 0) { + atype = VM_PROT_NONE; /* assume read */ + if (prot & PROT_EXEC) + atype |= VM_PROT_EXECUTE; /* could well be execute */ + if ((prot & PROT_WRITE) && (cur_prot & VM_PROT_READ)) + atype = VM_PROT_WRITE; /* if it had write access */ + +printf("%sva %p, prot = %d, cur_prot = %d ==> atype = %d\n", kmem?"kmem, ":"", (void *) va, prot, cur_prot, atype); + if (atype != VM_PROT_NONE) { + pcb->pcb_onfault = NULL; + rv = uvm_fault(vm_map, (vaddr_t) va, atype); + pcb->pcb_onfault = (void *) onfault; + } + } + + if (rv) + aprint_debug("uvm_fault returned error %d\n", rv); + if (rv) { /* something got wrong */ if (kmem) {