From 53025830b33ce581d13c85a67f243833d886d654 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 13 Sep 2006 22:25:00 +0000 Subject: [PATCH] Collapse some bits of repetitive code into their own procedures and allocate a maximally sized default object to back MAP_VPAGETABLE mappings, allowing us to access logical memory beyond the size of the original mmap() call by programming the page table to point at it. This gives us an abstraction and capability similar to a real kernel's ability to map e.g. 2GB of physical memory into its 1GB address space. --- sys/vm/vm_fault.c | 9 ++-- sys/vm/vm_map.c | 119 ++++++++++++++++++++++++++-------------------- sys/vm/vm_map.h | 3 +- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 46b1743817..4456af9863 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.29 2006/09/13 18:12:18 dillon Exp $ + * $DragonFly: src/sys/vm/vm_fault.c,v 1.30 2006/09/13 22:25:00 dillon Exp $ */ /* @@ -1222,11 +1222,8 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, * Create the top-level object for the destination entry. (Doesn't * actually shadow anything - we copy the pages directly.) */ - dst_object = vm_object_allocate(OBJT_DEFAULT, - (vm_size_t) OFF_TO_IDX(dst_entry->end - dst_entry->start)); - - dst_entry->object.vm_object = dst_object; - dst_entry->offset = 0; + vm_map_entry_allocate_object(dst_entry); + dst_object = dst_entry->object.vm_object; prot = dst_entry->max_protection; diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index f8c3c0dede..11c8c444c3 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_map.c,v 1.187.2.19 2003/05/27 00:47:02 alc Exp $ - * $DragonFly: src/sys/vm/vm_map.c,v 1.49 2006/09/13 17:10:42 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.c,v 1.50 2006/09/13 22:25:00 dillon Exp $ */ /* @@ -144,6 +144,7 @@ static struct vm_map_entry map_entry_init[MAX_MAPENT]; static struct vm_map_entry cpu_map_entry_init[MAXCPU][VMEPERCPU]; static struct vm_map map_init[MAX_KMAP]; +static void vm_map_entry_shadow(vm_map_entry_t entry); static vm_map_entry_t vm_map_entry_create(vm_map_t map, int *); static void vm_map_entry_dispose (vm_map_t map, vm_map_entry_t entry, int *); static void _vm_map_clip_end (vm_map_t, vm_map_entry_t, vm_offset_t, int *); @@ -356,6 +357,60 @@ vm_map_init(struct vm_map *map, vm_offset_t min, vm_offset_t max) lockinit(&map->lock, "thrd_sleep", 0, 0); } +/* + * Shadow the vm_map_entry's object. This typically needs to be done when + * a write fault is taken on an entry which had previously been cloned by + * fork(). The shared object (which might be NULL) must become private so + * we add a shadow layer above it. + * + * Object allocation for anonymous mappings is defered as long as possible. + * When creating a shadow, however, the underlying object must be instantiated + * so it can be shared. + * + * If the map segment is governed by a virtual page table then it is + * possible to address offsets beyond the mapped area. Just allocate + * a maximally sized object for this case. + */ +static +void +vm_map_entry_shadow(vm_map_entry_t entry) +{ + if (entry->maptype == VM_MAPTYPE_VPAGETABLE) { + vm_object_shadow(&entry->object.vm_object, &entry->offset, + 0x7FFFFFFF); /* XXX */ + } else { + vm_object_shadow(&entry->object.vm_object, &entry->offset, + atop(entry->end - entry->start)); + } + entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; +} + +/* + * Allocate an object for a vm_map_entry. + * + * Object allocation for anonymous mappings is defered as long as possible. + * This function is called when we can defer no longer, generally when a map + * entry might be split or forked or takes a page fault. + * + * If the map segment is governed by a virtual page table then it is + * possible to address offsets beyond the mapped area. Just allocate + * a maximally sized object for this case. + */ +void +vm_map_entry_allocate_object(vm_map_entry_t entry) +{ + vm_object_t obj; + + if (entry->maptype == VM_MAPTYPE_VPAGETABLE) { + obj = vm_object_allocate(OBJT_DEFAULT, 0x7FFFFFFF); /* XXX */ + } else { + obj = vm_object_allocate(OBJT_DEFAULT, + atop(entry->end - entry->start)); + } + entry->object.vm_object = obj; + entry->offset = 0; +} + /* * vm_map_entry_reserve_cpu_init: * @@ -1072,13 +1127,8 @@ _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start, int *c * map. This is a bit of a hack, but is also about the best place to * put this improvement. */ - if (entry->object.vm_object == NULL && !map->system_map) { - vm_object_t object; - object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->object.vm_object = object; - entry->offset = 0; + vm_map_entry_allocate_object(entry); } new_entry = vm_map_entry_create(map, countp); @@ -1132,11 +1182,7 @@ _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end, int *count */ if (entry->object.vm_object == NULL && !map->system_map) { - vm_object_t object; - object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->object.vm_object = object; - entry->offset = 0; + vm_map_entry_allocate_object(entry); } /* @@ -1840,20 +1886,10 @@ vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t real_end, if (entry->maptype != VM_MAPTYPE_SUBMAP) { int copyflag = entry->eflags & MAP_ENTRY_NEEDS_COPY; if (copyflag && ((entry->protection & VM_PROT_WRITE) != 0)) { - - vm_object_shadow(&entry->object.vm_object, - &entry->offset, - atop(entry->end - entry->start)); - entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; - + vm_map_entry_shadow(entry); } else if (entry->object.vm_object == NULL && !map->system_map) { - - entry->object.vm_object = - vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->offset = (vm_offset_t) 0; - + vm_map_entry_allocate_object(entry); } } entry->wired_count++; @@ -2047,17 +2083,10 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t real_end, int kmflags) int copyflag = entry->eflags & MAP_ENTRY_NEEDS_COPY; if (copyflag && ((entry->protection & VM_PROT_WRITE) != 0)) { - - vm_object_shadow(&entry->object.vm_object, - &entry->offset, - atop(entry->end - entry->start)); - entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; + vm_map_entry_shadow(entry); } else if (entry->object.vm_object == NULL && !map->system_map) { - entry->object.vm_object = - vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->offset = (vm_offset_t) 0; + vm_map_entry_allocate_object(entry); } } @@ -2804,22 +2833,17 @@ vmspace_fork(struct vmspace *vm1) */ object = old_entry->object.vm_object; if (object == NULL) { - object = vm_object_allocate(OBJT_DEFAULT, - atop(old_entry->end - old_entry->start)); - old_entry->object.vm_object = object; - old_entry->offset = (vm_offset_t) 0; + vm_map_entry_allocate_object(old_entry); + object = old_entry->object.vm_object; } /* - * Add the reference before calling vm_object_shadow + * Add the reference before calling vm_map_entry_shadow * to insure that a shadow object is created. */ vm_object_reference(object); if (old_entry->eflags & MAP_ENTRY_NEEDS_COPY) { - vm_object_shadow(&old_entry->object.vm_object, - &old_entry->offset, - atop(old_entry->end - old_entry->start)); - old_entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; + vm_map_entry_shadow(old_entry); /* Transfer the second reference too. */ vm_object_reference( old_entry->object.vm_object); @@ -3340,12 +3364,7 @@ RetryLookup: } use_read_lock = 0; - vm_object_shadow( - &entry->object.vm_object, - &entry->offset, - atop(entry->end - entry->start)); - - entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; + vm_map_entry_shadow(entry); } else { /* * We're attempting to read a copy-on-write page -- @@ -3366,9 +3385,7 @@ RetryLookup: goto RetryLookup; } use_read_lock = 0; - entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->offset = 0; + vm_map_entry_allocate_object(entry); } /* diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 1828e03f12..37c6ffe9fa 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.25 2006/09/13 17:10:42 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.h,v 1.26 2006/09/13 22:25:00 dillon Exp $ */ /* @@ -424,6 +424,7 @@ vmspace_resident_count(struct vmspace *vmspace) boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); struct pmap; struct globaldata; +void vm_map_entry_allocate_object(vm_map_entry_t); void vm_map_entry_reserve_cpu_init(struct globaldata *gd); int vm_map_entry_reserve(int); int vm_map_entry_kreserve(int); -- 2.41.0