summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2013-09-09 18:11:59 +0000
committerjhb <jhb@FreeBSD.org>2013-09-09 18:11:59 +0000
commit04bb6e10cd2cbd0ee0de7fef3f81e88ebd43e6b4 (patch)
tree42d2ff2e91fcca16534848427856c6243db2126a /sys/vm
parent2a48fed0b32ceb1567f3b7e33835bacfdf3e0971 (diff)
downloadFreeBSD-src-04bb6e10cd2cbd0ee0de7fef3f81e88ebd43e6b4.zip
FreeBSD-src-04bb6e10cd2cbd0ee0de7fef3f81e88ebd43e6b4.tar.gz
Add a mmap flag (MAP_32BIT) on 64-bit platforms to request that a mapping use
an address in the first 2GB of the process's address space. This flag should have the same semantics as the same flag on Linux. To facilitate this, add a new parameter to vm_map_find() that specifies an optional maximum virtual address. While here, fix several callers of vm_map_find() to use a VMFS_* constant for the findspace argument instead of TRUE and FALSE. Reviewed by: alc Approved by: re (kib)
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_init.c2
-rw-r--r--sys/vm/vm_kern.c2
-rw-r--r--sys/vm/vm_map.c7
-rw-r--r--sys/vm/vm_map.h2
-rw-r--r--sys/vm/vm_mmap.c31
5 files changed, 32 insertions, 12 deletions
diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c
index 0a381d0..30faa5a 100644
--- a/sys/vm/vm_init.c
+++ b/sys/vm/vm_init.c
@@ -111,7 +111,7 @@ kva_import(void *unused, vmem_size_t size, int flags, vmem_addr_t *addrp)
int result;
addr = vm_map_min(kernel_map);
- result = vm_map_find(kernel_map, NULL, 0, &addr, size,
+ result = vm_map_find(kernel_map, NULL, 0, &addr, size, 0,
VMFS_SUPER_SPACE, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT);
if (result != KERN_SUCCESS)
return (ENOMEM);
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 9790653..dd075c1 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -285,7 +285,7 @@ kmem_suballoc(vm_map_t parent, vm_offset_t *min, vm_offset_t *max,
size = round_page(size);
*min = vm_map_min(parent);
- ret = vm_map_find(parent, NULL, 0, min, size, superpage_align ?
+ ret = vm_map_find(parent, NULL, 0, min, size, 0, superpage_align ?
VMFS_SUPER_SPACE : VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL,
MAP_ACC_NO_CHARGE);
if (ret != KERN_SUCCESS)
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 1be62af..5990630 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1432,8 +1432,8 @@ 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, int find_space, vm_prot_t prot,
- vm_prot_t max, int cow)
+ vm_size_t length, vm_offset_t max_addr, int find_space,
+ vm_prot_t prot, vm_prot_t max, int cow)
{
vm_offset_t alignment, initial_addr, start;
int result;
@@ -1452,7 +1452,8 @@ again:
vm_map_lock(map);
do {
if (find_space != VMFS_NO_SPACE) {
- if (vm_map_findspace(map, start, length, addr)) {
+ if (vm_map_findspace(map, start, length, addr) ||
+ (max_addr != 0 && *addr + length > max_addr)) {
vm_map_unlock(map);
if (find_space == VMFS_OPTIMAL_SPACE) {
find_space = VMFS_ANY_SPACE;
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index 054c506..850bf25 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -366,7 +366,7 @@ 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,
- int, vm_prot_t, vm_prot_t, int);
+ vm_offset_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 *);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 77f64f4..9548485 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -94,10 +94,8 @@ SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, &old_mlock, 0,
"Do not apply RLIMIT_MEMLOCK on mlockall");
TUNABLE_INT("vm.old_mlock", &old_mlock);
-#ifndef _SYS_SYSPROTO_H_
-struct sbrk_args {
- int incr;
-};
+#ifdef MAP_32BIT
+#define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31)
#endif
static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
@@ -107,6 +105,12 @@ static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
static int vm_mmap_shm(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
int *, struct shmfd *, vm_ooffset_t, vm_object_t *);
+#ifndef _SYS_SYSPROTO_H_
+struct sbrk_args {
+ int incr;
+};
+#endif
+
/*
* MPSAFE
*/
@@ -278,6 +282,18 @@ sys_mmap(td, uap)
return (EINVAL);
if (addr + size < addr)
return (EINVAL);
+#ifdef MAP_32BIT
+ if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
+ return (EINVAL);
+ } else if (flags & MAP_32BIT) {
+ /*
+ * For MAP_32BIT, override the hint if it is too high and
+ * do not bother moving the mapping past the heap (since
+ * the heap is usually above 2GB).
+ */
+ if (addr + size > MAP_32BIT_MAX_ADDR)
+ addr = 0;
+#endif
} else {
/*
* XXX for non-fixed mappings where no hint is provided or
@@ -1620,8 +1636,11 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
MAP_ALIGNMENT_SHIFT);
else
findspace = VMFS_OPTIMAL_SPACE;
- rv = vm_map_find(map, object, foff, addr, size, findspace,
- prot, maxprot, docow);
+ rv = vm_map_find(map, object, foff, addr, size,
+#ifdef MAP_32BIT
+ flags & MAP_32BIT ? MAP_32BIT_MAX_ADDR :
+#endif
+ 0, findspace, prot, maxprot, docow);
} else
rv = vm_map_fixed(map, object, foff, *addr, size,
prot, maxprot, docow);
OpenPOWER on IntegriCloud