Module Name:    src
Committed By:   reinoud
Date:           Fri Sep  9 12:28:05 UTC 2011

Modified Files:
        src/sys/arch/usermode/usermode: pmap.c

Log Message:
Implement TBL functionality by remembering if its mapped in or not before
guessing and adjusting access types.

While here, when we hit a read-access fault and reference the page, also mark
it for executable when its permissions permit it. Distinguising between the
two is neigh impossible as we need to guess/derive the access the process
tried to have to the memory: we dont know if its a read/write/exec try.

Also clean up some debug messages.


To generate a diff of this commit:
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/usermode/usermode/pmap.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.57 src/sys/arch/usermode/usermode/pmap.c:1.58
--- src/sys/arch/usermode/usermode/pmap.c:1.57	Tue Sep  6 09:37:41 2011
+++ src/sys/arch/usermode/usermode/pmap.c	Fri Sep  9 12:28:05 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.57 2011/09/06 09:37:41 reinoud Exp $ */
+/* $NetBSD: pmap.c,v 1.58 2011/09/09 12:28:05 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.57 2011/09/06 09:37:41 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.58 2011/09/09 12:28:05 reinoud Exp $");
 
 #include "opt_memsize.h"
 #include "opt_kmempages.h"
@@ -52,11 +52,13 @@
 	uint8_t		pv_vflags;	/* per mapping flags */
 #define PV_WIRED	0x01		/* wired mapping */
 #define PV_UNMANAGED	0x02		/* entered by pmap_kenter_ */
+#define PV_MAPPEDIN	0x04		/* is actually mapped */
 	uint8_t		pv_pflags;	/* per phys page flags */
 #define PV_REFERENCED	0x01
 #define PV_MODIFIED	0x02
 };
 
+
 /* this is a guesstimate of 16KB/process on amd64, or around 680+ mappings */
 #define PM_MIN_NENTRIES ((int) (16*1024 / sizeof(pv_entry)))
 struct pmap {
@@ -484,7 +486,7 @@
 
 	/* not known! then it must be UVM's work */
 	if (pv == NULL) {
-aprint_debug("no mapping yet\n");
+		aprint_debug("%s: no mapping yet\n", __func__);
 		*atype = VM_PROT_READ;		/* assume it was a read */
 		return false;
 	}
@@ -502,6 +504,16 @@
 		return true;
 	}
 
+	/* if its not mapped in, we have a TBL fault */
+	if ((pv->pv_vflags & PV_MAPPEDIN) == 0) {
+		if (pv->pv_mmap_ppl != THUNK_PROT_NONE) {
+			printf("%s: tlb fault page lpn %"PRIiPTR"\n", __func__,
+				pv->pv_lpn);
+			pmap_page_activate(pv);
+			return true;
+		}
+	}
+
 	/* determine pmap access type (mmap doesnt need to be 1:1 on VM_PROT_) */
 	prot = pv->pv_prot;
 	cur_prot = VM_PROT_NONE;
@@ -514,7 +526,8 @@
 
 	diff = prot & (prot ^ cur_prot);
 
-aprint_debug("prot = %d, cur_prot = %d, diff = %d\n", prot, cur_prot, diff);
+	aprint_debug("%s: prot = %d, cur_prot = %d, diff = %d\n",
+		__func__, prot, cur_prot, diff);
 	*atype = VM_PROT_READ;  /* assume its a read error */
 	if (diff & VM_PROT_READ) {
 		if ((ppv->pv_pflags & PV_REFERENCED) == 0) {
@@ -543,9 +556,9 @@
 	*atype = VM_PROT_WRITE; /* assume its a write error */
 	if (diff & VM_PROT_WRITE) {
 		if (prot & VM_PROT_WRITE) {
-aprint_debug("should be allowed to write\n");
+			/* should be allowed to write */
 			if ((ppv->pv_pflags & PV_MODIFIED) == 0) {
-aprint_debug("was marked unmodified\n");
+				/* was marked unmodified */
 				ppv->pv_pflags |= PV_MODIFIED;
 				pmap_update_page(ppn);
 				return true;
@@ -574,6 +587,10 @@
 	if (addr != (void *) va)
 		panic("pmap_page_activate: mmap failed (expected %p got %p): %d",
 		    (void *)va, addr, thunk_geterrno());
+
+	pv->pv_vflags &= ~PV_MAPPEDIN;
+	if (pv->pv_mmap_ppl != THUNK_PROT_NONE)
+		pv->pv_vflags |= PV_MAPPEDIN;
 }
 
 static void
@@ -590,6 +607,7 @@
 		(void *) va, (void *) pa, pv->pv_mmap_ppl, (void *) addr);
 	if (addr != (void *) va)
 		panic("pmap_page_deactivate: mmap failed");
+	pv->pv_vflags &= ~PV_MAPPEDIN;
 }
 
 static void
@@ -608,13 +626,16 @@
 
 	/* create referenced/modified emulation */
 	if ((pv->pv_prot & VM_PROT_WRITE) &&
-	    (pflags & PV_REFERENCED) && (pflags & PV_MODIFIED))
+	    (pflags & PV_REFERENCED) && (pflags & PV_MODIFIED)) {
 		mmap_ppl = THUNK_PROT_READ | THUNK_PROT_WRITE;
-	else if ((pv->pv_prot & (VM_PROT_READ | VM_PROT_EXECUTE)) &&
-		 (pflags & PV_REFERENCED))
+	} else if ((pv->pv_prot & (VM_PROT_READ | VM_PROT_EXECUTE)) &&
+		 (pflags & PV_REFERENCED)) {
 		mmap_ppl = THUNK_PROT_READ;
-	else
+		if (pv->pv_prot & VM_PROT_EXECUTE)
+			mmap_ppl |= THUNK_PROT_EXEC;
+	} else {
 		mmap_ppl = THUNK_PROT_NONE;
+	}
 
 	/* unmanaged pages are special; they dont track r/m */
 	if (vflags & PV_UNMANAGED)

Reply via email to