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) {

Reply via email to