Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/usermode Completely redo R/M emulation and fault ha...
details: https://anonhg.NetBSD.org/src/rev/b10d0dee546a
branches: trunk
changeset: 769091:b10d0dee546a
user: reinoud <reinoud%NetBSD.org@localhost>
date: Wed Aug 31 12:42:41 2011 +0000
description:
Completely redo R/M emulation and fault handling taking UVM as authorative
answer and not relying on UVM's pmap directions since UVM has its own schemes
for COW etc.
diffstat:
sys/arch/usermode/conf/GENERIC | 11 ++-
sys/arch/usermode/usermode/pmap.c | 122 +++++++++++++++++++++++++++++--------
sys/arch/usermode/usermode/trap.c | 85 ++++++++++++-------------
3 files changed, 142 insertions(+), 76 deletions(-)
diffs (truncated from 364 to 300 lines):
diff -r 878d3367e34c -r b10d0dee546a sys/arch/usermode/conf/GENERIC
--- a/sys/arch/usermode/conf/GENERIC Wed Aug 31 12:25:05 2011 +0000
+++ b/sys/arch/usermode/conf/GENERIC Wed Aug 31 12:42:41 2011 +0000
@@ -1,9 +1,9 @@
-# $NetBSD: GENERIC,v 1.14 2011/08/27 18:13:09 jmcneill Exp $
+# $NetBSD: GENERIC,v 1.15 2011/08/31 12:42:41 reinoud Exp $
include "arch/usermode/conf/std.usermode"
options INCLUDE_CONFIG_FILE
-#ident "GENERIC-$Revision: 1.14 $"
+#ident "GENERIC-$Revision: 1.15 $"
maxusers 32
makeoptions DEBUG="-O1 -g3"
@@ -20,9 +20,12 @@
options SYSVSHM
options DEBUG
+options DIAGNOSTIC
+options LOCKDEBUG
options DEBUG_EXEC
-options DIAGNOSTIC
-options LOCKDEBUG
+#options CPU_DEBUG
+#options UVMHIST
+#options UVMHIST_PRINT
options COMPAT_BSDPTY
options COMPAT_50
diff -r 878d3367e34c -r b10d0dee546a sys/arch/usermode/usermode/pmap.c
--- a/sys/arch/usermode/usermode/pmap.c Wed Aug 31 12:25:05 2011 +0000
+++ b/sys/arch/usermode/usermode/pmap.c Wed Aug 31 12:42:41 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.48 2011/08/30 12:02:38 reinoud Exp $ */
+/* $NetBSD: pmap.c,v 1.49 2011/08/31 12:42:41 reinoud Exp $ */
/*-
* Copyright (c) 2011 Reinoud Zandijk <reinoud%NetBSD.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.48 2011/08/30 12:02:38 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.49 2011/08/31 12:42:41 reinoud Exp $");
#include "opt_memsize.h"
#include "opt_kmempages.h"
@@ -89,9 +89,8 @@
static void pmap_page_deactivate(struct pv_entry *pv);
static void pv_update(struct pv_entry *pv);
static void pmap_update_page(uintptr_t ppn);
+bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
-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);
@@ -440,39 +439,102 @@
return pv;
}
-void
-pmap_get_current_protection(pmap_t pmap, vaddr_t va,
- vm_prot_t *cur_prot, vm_prot_t *prot)
+/*
+ * Check if the given page fault was our reference / modified emulation fault;
+ * if so return true otherwise return false and let uvm handle it
+ */
+bool
+pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype)
{
- struct pv_entry *pv;
+ struct pv_entry *pv, *ppv;
+ uintptr_t lpn, ppn;
+ int prot, cur_prot, diff;
+
+ /* get current protection settings */
+
+ aprint_debug("pmap_fault pmap %p, va %p\n", pmap, (void *) va);
+
+ /* get logical page from vaddr */
+ lpn = atop(va - VM_MIN_ADDRESS); /* V->L */
+ pv = pmap->pm_entries[lpn];
+
+ /* not known! then it must be UVM's work */
+ if (pv == NULL) {
+aprint_debug("no mapping yet\n");
+ *atype = VM_PROT_READ; /* assume it was a read */
+ return false;
+ }
+
+ /* determine physical address and lookup 'root' pv_entry */
+ ppn = pv->pv_ppn;
+ ppv = &pv_table[ppn];
- uintptr_t lpn;
+ /* if unmanaged we just make sure it is there! */
+ if (ppv->pv_vflags & PV_UNMANAGED) {
+ printf("%s: oops warning unmanaged page %"PRIiPTR" faulted\n",
+ __func__, ppn);
+ /* atype not set */
+ 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;
+ 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;
+
+ diff = prot & (prot ^ cur_prot);
- 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");
+aprint_debug("prot = %d, cur_prot = %d, diff = %d\n", 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) {
+ ppv->pv_vflags |= PV_REFERENCED;
+ pmap_update_page(ppn);
+ return true;
+ }
+ return false;
+ }
+
+#if 0
+ /* this might be questionable */
+ if (diff & VM_PROT_EXECUTE) {
+ *atype = VM_PROT_EXECUTE; /* assume it was executing */
+ if (prot & VM_PROT_EXECUTE) {
+ if ((ppv->pv_pflags & PV_REFERENCED) == 0) {
+ ppv->pv_vflags |= PV_REFERENCED;
+ pmap_update_page(ppn);
+ return true;
+ }
+ }
+ return false;
+ }
#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;
+ *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");
+ if ((ppv->pv_pflags & PV_MODIFIED) == 0) {
+aprint_debug("was marked unmodified\n");
+ ppv->pv_vflags |= PV_MODIFIED;
+ pmap_update_page(ppn);
+ return true;
+ }
+ }
+ return false;
}
- *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;
+ /* not due to our r/m handling, let uvm handle it ! */
+ return false;
}
+
static void
pmap_page_activate(struct pv_entry *pv)
{
@@ -515,6 +577,10 @@
pflags = pv_table[pv->pv_ppn].pv_pflags;
vflags = pv_table[pv->pv_ppn].pv_vflags;
+ KASSERT(PROT_READ == VM_PROT_READ);
+ KASSERT(PROT_WRITE == VM_PROT_WRITE);
+ KASSERT(PROT_EXEC == VM_PROT_EXECUTE);
+
/* create referenced/modified emulation */
if ((pv->pv_prot & VM_PROT_WRITE) &&
(pflags & PV_REFERENCED) && (pflags & PV_MODIFIED))
diff -r 878d3367e34c -r b10d0dee546a sys/arch/usermode/usermode/trap.c
--- a/sys/arch/usermode/usermode/trap.c Wed Aug 31 12:25:05 2011 +0000
+++ b/sys/arch/usermode/usermode/trap.c Wed Aug 31 12:42:41 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.13 2011/08/29 14:59:09 reinoud Exp $ */
+/* $NetBSD: trap.c,v 1.14 2011/08/31 12:42:41 reinoud Exp $ */
/*-
* Copyright (c) 2011 Reinoud Zandijk <reinoud%netbsd.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.13 2011/08/29 14:59:09 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.14 2011/08/31 12:42:41 reinoud Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -52,10 +52,11 @@
/* forwards and externals */
void setup_signal_handlers(void);
static void mem_access_handler(int sig, siginfo_t *info, void *ctx);
+extern int errno;
-extern void pmap_get_current_protection(pmap_t pmap, vaddr_t va,
- vm_prot_t *cur_prot, vm_prot_t *prot);
-extern int errno;
+bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
+
+static int debug_fh;
void
startlwp(void *arg)
@@ -74,6 +75,8 @@
panic("couldn't register SIGSEGV handler : %d", errno);
if (thunk_sigaction(SIGBUS, &sa, NULL) == -1)
panic("couldn't register SIGBUS handler : %d", errno);
+
+ debug_fh = thunk_open("/usr/sources/debug", O_RDWR | O_TRUNC | O_CREAT, 0666);
}
static struct trapframe kernel_tf;
@@ -81,33 +84,37 @@
static void
mem_access_handler(int sig, siginfo_t *info, void *ctx)
{
+ static volatile int recurse = 0;
struct proc *p;
struct lwp *l;
struct pcb *pcb;
struct vmspace *vm;
struct vm_map *vm_map;
struct trapframe *tf;
- vm_prot_t cur_prot, prot, atype;
+ vm_prot_t atype;
vaddr_t va;
- vaddr_t onfault;
+ void *onfault;
int kmem, rv;
- static volatile int recurse = 0;
recurse++;
- aprint_debug("trap lwp=%p pid=%d lid=%d\n",
- curlwp,
- curlwp->l_proc->p_pid,
- curlwp->l_lid);
if (recurse > 1)
printf("enter trap recursion level %d\n", recurse);
if ((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS)) {
l = curlwp;
p = l->l_proc;
pcb = lwp_getpcb(l);
- onfault = (vaddr_t) pcb->pcb_onfault;
+ onfault = pcb->pcb_onfault;
vm = p->p_vmspace;
-#if 1
+#if 0
+ va = (vaddr_t) info->si_addr;
+ printf("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("SIGSEGV or SIGBUS!\n");
printf("\tsi_signo = %d\n", info->si_signo);
printf("\tsi_errno = %d\n", info->si_errno);
@@ -134,50 +141,39 @@
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!");
+
kmem = 1;
vm_map = kernel_map;
if ((va >= VM_MIN_ADDRESS) && (va < VM_MAXUSER_ADDRESS)) {
kmem = 0;
vm_map = &vm->vm_map;
}
Home |
Main Index |
Thread Index |
Old Index