summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2013-07-19 19:06:15 +0000
committerjhb <jhb@FreeBSD.org>2013-07-19 19:06:15 +0000
commitd67e7a1cc9054fbcf546edfe5ebc03bb5e29d4ca (patch)
tree7777baf0c52b0b66567d2147e4ab8ed497fc8e3c
parent7dbfd863d4e1dcba1978d736ffc507f0e23eaf26 (diff)
downloadFreeBSD-src-d67e7a1cc9054fbcf546edfe5ebc03bb5e29d4ca.zip
FreeBSD-src-d67e7a1cc9054fbcf546edfe5ebc03bb5e29d4ca.tar.gz
Be more aggressive in using superpages in all mappings of objects:
- Add a new address space allocation method (VMFS_OPTIMAL_SPACE) for vm_map_find() that will try to alter the alignment of a mapping to match any existing superpage mappings of the object being mapped. If no suitable address range is found with the necessary alignment, vm_map_find() will fall back to using the simple first-fit strategy (VMFS_ANY_SPACE). - Change mmap() without MAP_FIXED, shmat(), and the GEM mapping ioctl to use VMFS_OPTIMAL_SPACE instead of VMFS_ANY_SPACE. Reviewed by: alc (earlier version) MFC after: 2 weeks
-rw-r--r--sys/dev/drm2/i915/i915_gem.c2
-rw-r--r--sys/kern/sysv_shm.c2
-rw-r--r--sys/vm/vm_map.c20
-rw-r--r--sys/vm/vm_map.h5
-rw-r--r--sys/vm/vm_mmap.c3
5 files changed, 22 insertions, 10 deletions
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index c505cdb..398fb0d 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -1289,7 +1289,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
vm_object_reference(obj->vm_obj);
DRM_UNLOCK(dev);
rv = vm_map_find(map, obj->vm_obj, args->offset, &addr, args->size,
- VMFS_ANY_SPACE, VM_PROT_READ | VM_PROT_WRITE,
+ VMFS_OPTIMAL_SPACE, VM_PROT_READ | VM_PROT_WRITE,
VM_PROT_READ | VM_PROT_WRITE, MAP_SHARED);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(obj->vm_obj);
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index a1c6b34..90f5d77 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -414,7 +414,7 @@ kern_shmat(td, shmid, shmaddr, shmflg)
vm_object_reference(shmseg->object);
rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object,
0, &attach_va, size, (flags & MAP_FIXED) ? VMFS_NO_SPACE :
- VMFS_ANY_SPACE, prot, prot, MAP_INHERIT_SHARE);
+ VMFS_OPTIMAL_SPACE, prot, prot, MAP_INHERIT_SHARE);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(shmseg->object);
error = ENOMEM;
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 778c054..9cf8827 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1444,19 +1444,29 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
vm_size_t length, int find_space, vm_prot_t prot,
vm_prot_t max, int cow)
{
- vm_offset_t start;
+ vm_offset_t start, initial_addr;
int result;
- start = *addr;
+ if (find_space == VMFS_OPTIMAL_SPACE && (object == NULL ||
+ (object->flags & OBJ_COLORED) == 0))
+ find_space = VMFS_ANY_SPACE;
+ initial_addr = *addr;
+again:
+ start = initial_addr;
vm_map_lock(map);
do {
if (find_space != VMFS_NO_SPACE) {
if (vm_map_findspace(map, start, length, addr)) {
vm_map_unlock(map);
+ if (find_space == VMFS_OPTIMAL_SPACE) {
+ find_space = VMFS_ANY_SPACE;
+ goto again;
+ }
return (KERN_NO_SPACE);
}
switch (find_space) {
case VMFS_ALIGNED_SPACE:
+ case VMFS_OPTIMAL_SPACE:
pmap_align_superpage(object, offset, addr,
length);
break;
@@ -1473,11 +1483,11 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
}
result = vm_map_insert(map, object, offset, start, start +
length, prot, max, cow);
- } while (result == KERN_NO_SPACE && (find_space == VMFS_ALIGNED_SPACE
+ } while (result == KERN_NO_SPACE && (find_space == VMFS_ALIGNED_SPACE ||
#ifdef VMFS_TLB_ALIGNED_SPACE
- || find_space == VMFS_TLB_ALIGNED_SPACE
+ find_space == VMFS_TLB_ALIGNED_SPACE ||
#endif
- ));
+ find_space == VMFS_OPTIMAL_SPACE));
vm_map_unlock(map);
return (result);
}
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index a73691d..824a9a0 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -343,9 +343,10 @@ long vmspace_resident_count(struct vmspace *vmspace);
*/
#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 */
+#define VMFS_OPTIMAL_SPACE 2 /* find a range with optimal alignment*/
+#define VMFS_ALIGNED_SPACE 3 /* find a superpage-aligned range */
#if defined(__mips__)
-#define VMFS_TLB_ALIGNED_SPACE 3 /* find a TLB entry aligned range */
+#define VMFS_TLB_ALIGNED_SPACE 4 /* find a TLB entry aligned range */
#endif
/*
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index c7e22c3..a5e6792 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -1603,7 +1603,8 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
else if (fitit)
rv = vm_map_find(map, object, foff, addr, size,
object != NULL && object->type == OBJT_DEVICE ?
- VMFS_ALIGNED_SPACE : VMFS_ANY_SPACE, prot, maxprot, docow);
+ VMFS_ALIGNED_SPACE : VMFS_OPTIMAL_SPACE, prot, maxprot,
+ docow);
else
rv = vm_map_fixed(map, object, foff, *addr, size,
prot, maxprot, docow);
OpenPOWER on IntegriCloud