diff --git a/share/man/man9/vm_map_find.9 b/share/man/man9/vm_map_find.9 index e1e8f4030d40..4aa5fb82193d 100644 --- a/share/man/man9/vm_map_find.9 +++ b/share/man/man9/vm_map_find.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd May 10, 2008 .Dt VM_MAP_FIND 9 .Os .Sh NAME @@ -38,7 +38,7 @@ .Ft int .Fo vm_map_find .Fa "vm_map_t map" "vm_object_t object" "vm_ooffset_t offset" -.Fa "vm_offset_t *addr" "vm_size_t length" "boolean_t find_space" +.Fa "vm_offset_t *addr" "vm_size_t length" "int find_space" .Fa "vm_prot_t prot" "vm_prot_t max" "int cow" .Fc .Sh DESCRIPTION @@ -70,11 +70,25 @@ by the caller before calling this function to account for the new entry. .Pp If .Fa find_space -is -.Dv TRUE , +is either +.Dv VMFS_ALIGNED_SPACE +or +.Dv VMFS_ANY_SPACE , the function will call .Xr vm_map_findspace 9 to discover a free region. +Moreover, if +.Fa find_space +is +.Dv VMFS_ALIGNED_SPACE , +the address of the free region will be optimized for the use of superpages. +Otherwise, if +.Fa find_space +is +.Dv VMFS_NO_SPACE , +.Xr vm_map_insert 9 +is called with the given address, +.Fa addr . .Sh IMPLEMENTATION NOTES This function acquires a lock on .Fa map @@ -90,9 +104,14 @@ The .Fn vm_map_find function returns .Dv KERN_SUCCESS -if space for the mapping could be found and -the mapping was successfully created. -If space could not be found in the map, +if the mapping was successfully created. +If space could not be found or +.Fa find_space +was +.Dv VMFS_NO_SPACE +and the given address, +.Fa addr , +was already mapped, .Dv KERN_NO_SPACE will be returned. If the discovered range turned out to be bogus, diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 5a98ce5ceaa6..8873b9836348 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1200,7 +1200,7 @@ vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset, int vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, vm_offset_t *addr, /* IN/OUT */ - vm_size_t length, boolean_t find_space, vm_prot_t prot, + vm_size_t length, int find_space, vm_prot_t prot, vm_prot_t max, int cow) { vm_offset_t start; @@ -1208,15 +1208,20 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, start = *addr; vm_map_lock(map); - if (find_space) { - if (vm_map_findspace(map, start, length, addr)) { - vm_map_unlock(map); - return (KERN_NO_SPACE); + do { + if (find_space != VMFS_NO_SPACE) { + if (vm_map_findspace(map, start, length, addr)) { + vm_map_unlock(map); + return (KERN_NO_SPACE); + } + if (find_space == VMFS_ALIGNED_SPACE) + pmap_align_superpage(object, offset, addr, + length); + start = *addr; } - start = *addr; - } - result = vm_map_insert(map, object, offset, - start, start + length, prot, max, cow); + result = vm_map_insert(map, object, offset, start, start + + length, prot, max, cow); + } while (result == KERN_NO_SPACE && find_space == VMFS_ALIGNED_SPACE); vm_map_unlock(map); return (result); } diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 37d90842fadf..bc2ae43b0c9d 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -324,6 +324,13 @@ long vmspace_wired_count(struct vmspace *vmspace); #define VM_FAULT_WIRE_MASK (VM_FAULT_CHANGE_WIRING|VM_FAULT_USER_WIRE) #define VM_FAULT_DIRTY 8 /* Dirty the page */ +/* + * The following "find_space" options are supported by vm_map_find() + */ +#define VMFS_NO_SPACE 0 /* don't find; use the given range */ +#define VMFS_ANY_SPACE 1 /* find a range with any alignment */ +#define VMFS_ALIGNED_SPACE 2 /* find a superpage-aligned range */ + /* * vm_map_wire and vm_map_unwire option flags */ @@ -337,7 +344,8 @@ long vmspace_wired_count(struct vmspace *vmspace); boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t); int vm_map_delete (vm_map_t, vm_offset_t, vm_offset_t); -int vm_map_find (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, boolean_t, vm_prot_t, vm_prot_t, int); +int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, + int, vm_prot_t, vm_prot_t, int); int vm_map_fixed(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_size_t, vm_prot_t, vm_prot_t, int); int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_offset_t *);