From 9ef421f4a93c2d0394e1dacd865f1d11414c098b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 11 Jan 2007 10:15:21 +0000 Subject: [PATCH] Fix a bug vm_fault_page(). PG_MAPPED was not getting set, causing the system to fail to remove pmap entries related to a VM page when reusing the VM page. General cleaning of vm_fault*() routines. These routines now expect all appropriate VM_PROT_* flags to be specified instead of just one. Also clean up the VM_FAULT_* flags. Remove VM_FAULT_HOLD - it is no longer used. vm_fault_page() handles the functionality in a far cleaner fashion then vm_fault(). --- sys/platform/vkernel/i386/trap.c | 5 +++-- sys/platform/vkernel/platform/copyio.c | 8 +++++--- sys/vfs/procfs/procfs_mem.c | 6 ++++-- sys/vm/vm_fault.c | 26 +++++++++++++------------- sys/vm/vm_map.h | 13 ++++++------- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/sys/platform/vkernel/i386/trap.c b/sys/platform/vkernel/i386/trap.c index de77d646d2..2f345490f0 100644 --- a/sys/platform/vkernel/i386/trap.c +++ b/sys/platform/vkernel/i386/trap.c @@ -36,7 +36,7 @@ * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.8 2007/01/10 00:34:05 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.9 2007/01/11 11:15:17 dillon Exp $ */ /* @@ -863,7 +863,7 @@ trap_pfault(struct trapframe *frame, int usermode, vm_offset_t eva) } if (frame->tf_xflags & PGEX_W) - ftype = VM_PROT_WRITE; + ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; @@ -1427,6 +1427,7 @@ go_user(struct trapframe frame) &frame, &curthread->td_savevext); if (r < 0) panic("vmspace_ctl had problems with the context"); + if (frame.tf_trapno) { #if 0 kprintf("User trapno %d eip %08x err %08x xflags %d\n", diff --git a/sys/platform/vkernel/platform/copyio.c b/sys/platform/vkernel/platform/copyio.c index 7fb5514189..03768dcfbe 100644 --- a/sys/platform/vkernel/platform/copyio.c +++ b/sys/platform/vkernel/platform/copyio.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/platform/vkernel/platform/copyio.c,v 1.6 2007/01/08 20:45:38 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/platform/copyio.c,v 1.7 2007/01/11 11:15:18 dillon Exp $ */ #include @@ -131,7 +131,8 @@ copyin(const void *udaddr, void *kaddr, size_t len) error = 0; while (len) { m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr), - VM_PROT_READ, VM_FAULT_NORMAL, &error); + VM_PROT_READ, + VM_FAULT_NORMAL, &error); if (error) break; n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK); @@ -166,7 +167,8 @@ copyout(const void *kaddr, void *udaddr, size_t len) error = 0; while (len) { m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr), - VM_PROT_WRITE, VM_FAULT_NORMAL, &error); + VM_PROT_READ|VM_PROT_WRITE, + VM_FAULT_NORMAL, &error); if (error) break; n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK); diff --git a/sys/vfs/procfs/procfs_mem.c b/sys/vfs/procfs/procfs_mem.c index 8ac95edc0f..0d182944f2 100644 --- a/sys/vfs/procfs/procfs_mem.c +++ b/sys/vfs/procfs/procfs_mem.c @@ -38,7 +38,7 @@ * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94 * * $FreeBSD: src/sys/miscfs/procfs/procfs_mem.c,v 1.46.2.3 2002/01/22 17:22:59 nectar Exp $ - * $DragonFly: src/sys/vfs/procfs/procfs_mem.c,v 1.13 2007/01/06 23:35:46 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_mem.c,v 1.14 2007/01/11 11:15:21 dillon Exp $ */ /* @@ -94,7 +94,9 @@ procfs_rwmem(struct proc *curp, struct proc *p, struct uio *uio) map = &vm->vm_map; writing = uio->uio_rw == UIO_WRITE; - reqprot = writing ? (VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE) : VM_PROT_READ; + reqprot = VM_PROT_READ; + if (writing) + reqprot |= VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE; kva = kmem_alloc_pageable(&kernel_map, PAGE_SIZE); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index c5a55e13e8..27bf9984d0 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -67,7 +67,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_fault.c,v 1.108.2.8 2002/02/26 05:49:27 silby Exp $ - * $DragonFly: src/sys/vm/vm_fault.c,v 1.38 2007/01/09 00:41:31 dillon Exp $ + * $DragonFly: src/sys/vm/vm_fault.c,v 1.39 2007/01/11 11:15:21 dillon Exp $ */ /* @@ -378,8 +378,6 @@ RetryFault: vm_page_flag_clear(fs.m, PG_ZERO); vm_page_flag_set(fs.m, PG_MAPPED|PG_REFERENCED); - if (fs.fault_flags & VM_FAULT_HOLD) - vm_page_hold(fs.m); /* * If the page is not wired down, then put it where the pageout daemon @@ -434,9 +432,6 @@ vm_fault_page_quick(vm_offset_t va, vm_prot_t fault_type, int *errorp) * * The returned page will be properly dirtied if VM_PROT_WRITE was specified, * and marked PG_REFERENCED as well. - * - * Since the pmap is not updated, this routine may not be used to wire - * the page. */ vm_page_t vm_fault_page(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, @@ -573,7 +568,6 @@ RetryFault: */ vm_page_hold(fs.m); vm_page_flag_clear(fs.m, PG_ZERO); - vm_page_flag_set(fs.m, PG_REFERENCED); if (fault_type & VM_PROT_WRITE) vm_page_dirty(fs.m); @@ -583,6 +577,7 @@ RetryFault: * now just do it unconditionally. XXX */ pmap_enter(fs.map->pmap, vaddr, fs.m, fs.prot, fs.wired); + vm_page_flag_set(fs.m, PG_REFERENCED|PG_MAPPED); /* * Unbusy the page by activating it. It remains held and will not @@ -655,7 +650,8 @@ vm_fault_vpagetable(struct faultstate *fs, vm_pindex_t *pindex, * * There is currently no real need to optimize this. */ - result = vm_fault_object(fs, vpte >> PAGE_SHIFT, VM_PROT_WRITE); + result = vm_fault_object(fs, vpte >> PAGE_SHIFT, + VM_PROT_READ|VM_PROT_WRITE); if (result != KERN_SUCCESS) return (result); @@ -679,7 +675,7 @@ vm_fault_vpagetable(struct faultstate *fs, vm_pindex_t *pindex, */ if ((fault_type & VM_PROT_WRITE) && (vpte & VPTE_V) && (vpte & VPTE_W)) { - if ((vpte & (VPTE_M|VPTE_A)) == 0) { + if ((vpte & (VPTE_M|VPTE_A)) != (VPTE_M|VPTE_A)) { atomic_set_int(ptep, VPTE_M|VPTE_A); vm_page_dirty(fs->m); } @@ -738,17 +734,21 @@ vm_fault_object(struct faultstate *fs, * page mapping writable: * * (1) The mapping is read-only or the VM object is read-only, - * fs->prot above will simply not have VM_PROT_WRITE SET. + * fs->prot above will simply not have VM_PROT_WRITE set. * * (2) If the mapping is a virtual page table we need to be able * to detect writes so we can set VPTE_M. * * (3) If the VM page is read-only or copy-on-write, upgrading would * just result in an unnecessary COW fault. + * + * VM_PROT_VPAGED is set if faulting via a virtual page table and + * causes adjustments to the 'M'odify bit to also turn off write + * access to force a re-fault. */ - if (fault_type == VM_PROT_READ && - fs->entry->maptype == VM_MAPTYPE_VPAGETABLE) { - fs->prot &= ~VM_PROT_WRITE; + if (fs->entry->maptype == VM_MAPTYPE_VPAGETABLE) { + if ((fault_type & VM_PROT_WRITE) == 0) + fs->prot &= ~VM_PROT_WRITE; } for (;;) { diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 6ab9504b02..9507a3f33c 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_map.h,v 1.54.2.5 2003/01/13 22:51:17 dillon Exp $ - * $DragonFly: src/sys/vm/vm_map.h,v 1.28 2006/12/28 22:24:02 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.h,v 1.29 2007/01/11 11:15:21 dillon Exp $ */ /* @@ -413,12 +413,11 @@ vmspace_resident_count(struct vmspace *vmspace) /* * vm_fault option flags */ -#define VM_FAULT_NORMAL 0 /* Nothing special */ -#define VM_FAULT_CHANGE_WIRING 1 /* Change the wiring as appropriate */ -#define VM_FAULT_USER_WIRE 2 /* Likewise, but for user purposes */ -#define VM_FAULT_WIRE_MASK (VM_FAULT_CHANGE_WIRING|VM_FAULT_USER_WIRE) -#define VM_FAULT_HOLD 4 /* Hold the page */ -#define VM_FAULT_DIRTY 8 /* Dirty the page */ +#define VM_FAULT_NORMAL 0x00 /* Nothing special */ +#define VM_FAULT_CHANGE_WIRING 0x01 /* Change the wiring as appropriate */ +#define VM_FAULT_USER_WIRE 0x02 /* Likewise, but for user purposes */ +#define VM_FAULT_DIRTY 0x08 /* Dirty the page */ +#define VM_FAULT_WIRE_MASK (VM_FAULT_CHANGE_WIRING|VM_FAULT_USER_WIRE) #ifdef _KERNEL boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); -- 2.11.4.GIT