Index: lib/libc/sys/mmap.2 =================================================================== --- lib/libc/sys/mmap.2 (revision 255249) +++ lib/libc/sys/mmap.2 (working copy) @@ -98,6 +98,12 @@ .Em or Ns 'ing the following values: .Bl -tag -width MAP_PREFAULT_READ +.It Dv MAP_32BIT +Request a region in the first 2GB of the current process' address space. +If a suitable region cannot be found, +.Fn mmap +will fail. +This flag is only available on 64-bit platforms. .It Dv MAP_ALIGNED Ns Pq Fa n Align the region on a requested boundary. If a suitable region cannot be found, @@ -362,6 +368,13 @@ argument was not page aligned, or part of the desired address space resides out of the valid address space for a user process. .It Bq Er EINVAL +Both +.Dv MAP_FIXED +and +.Dv MAP_32BIT +were specified and part of the desired address space resides outside +of the first 2GB of user address space. +.It Bq Er EINVAL The .Fa len argument Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c (revision 255249) +++ sys/compat/freebsd32/freebsd32_misc.c (working copy) @@ -448,9 +448,8 @@ } } else { vm_offset_t addr = trunc_page(start); - rv = vm_map_find(map, 0, 0, - &addr, PAGE_SIZE, FALSE, prot, - VM_PROT_ALL, 0); + rv = vm_map_find(map, NULL, 0, &addr, PAGE_SIZE, 0, + VMFS_NO_SPACE, prot, VM_PROT_ALL, 0); if (rv != KERN_SUCCESS) return (EINVAL); } @@ -542,9 +541,8 @@ rv = vm_map_remove(map, start, end); if (rv != KERN_SUCCESS) return (EINVAL); - rv = vm_map_find(map, 0, 0, - &start, end - start, FALSE, - prot, VM_PROT_ALL, 0); + rv = vm_map_find(map, NULL, 0, &start, end - start, + 0, VMFS_NO_SPACE, prot, VM_PROT_ALL, 0); if (rv != KERN_SUCCESS) return (EINVAL); r.fd = fd; Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c (revision 255249) +++ sys/compat/linux/linux_misc.c (working copy) @@ -410,8 +410,8 @@ /* get anon user mapping, read+write+execute */ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, - &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, - VM_PROT_ALL, 0); + &vmaddr, a_out->a_text + a_out->a_data, 0, VMFS_NO_SPACE, + VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto cleanup; @@ -455,7 +455,8 @@ /* allocate some 'anon' space */ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, - &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, + VM_PROT_ALL, 0); if (error) goto cleanup; } Index: sys/compat/svr4/imgact_svr4.c =================================================================== --- sys/compat/svr4/imgact_svr4.c (revision 255249) +++ sys/compat/svr4/imgact_svr4.c (working copy) @@ -140,8 +140,8 @@ */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, - a_out->a_text + a_out->a_data + bss_size, FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); + a_out->a_text + a_out->a_data + bss_size, 0, VMFS_NO_SPACE, + VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; @@ -204,7 +204,7 @@ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, - bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; #ifdef DEBUG Index: sys/dev/drm2/i915/i915_gem.c =================================================================== --- sys/dev/drm2/i915/i915_gem.c (revision 255249) +++ sys/dev/drm2/i915/i915_gem.c (working copy) @@ -1291,7 +1291,7 @@ addr = 0; vm_object_reference(obj->vm_obj); DRM_UNLOCK(dev); - rv = vm_map_find(map, obj->vm_obj, args->offset, &addr, args->size, + rv = vm_map_find(map, obj->vm_obj, args->offset, &addr, args->size, 0, VMFS_OPTIMAL_SPACE, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE, MAP_INHERIT_SHARE); if (rv != KERN_SUCCESS) { Index: sys/i386/ibcs2/imgact_coff.c =================================================================== --- sys/i386/ibcs2/imgact_coff.c (revision 255249) +++ sys/i386/ibcs2/imgact_coff.c (working copy) @@ -128,7 +128,7 @@ if (map_len != 0) { error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr, - map_len, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); + map_len, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (vm_mmap_to_errno(error)); } @@ -473,7 +473,7 @@ DPRINTF(("imgact: error = %d\n", error)); vm_map_find(&vmspace->vm_map, NULL, 0, - (vm_offset_t *)&hole, PAGE_SIZE, VMFS_NO_SPACE, + (vm_offset_t *)&hole, PAGE_SIZE, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%p end = 0x%p\n", ctob(vmspace->vm_dsize), vmspace->vm_daddr, Index: sys/i386/linux/imgact_linux.c =================================================================== --- sys/i386/linux/imgact_linux.c (revision 255249) +++ sys/i386/linux/imgact_linux.c (working copy) @@ -139,8 +139,8 @@ */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, - a_out->a_text + a_out->a_data + bss_size, FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); + a_out->a_text + a_out->a_data + bss_size, 0, VMFS_NO_SPACE, + VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; @@ -204,7 +204,7 @@ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, - bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; #ifdef DEBUG Index: sys/ia64/ia32/ia32_signal.c =================================================================== --- sys/ia64/ia32/ia32_signal.c (revision 255249) +++ sys/ia64/ia32/ia32_signal.c (working copy) @@ -169,8 +169,8 @@ * Build the GDT and LDT. */ gdt = sv->sv_usrstack; - vm_map_find(&vmspace->vm_map, 0, 0, &gdt, IA32_PAGE_SIZE << 1, 0, - VM_PROT_ALL, VM_PROT_ALL, 0); + vm_map_find(&vmspace->vm_map, NULL, 0, &gdt, IA32_PAGE_SIZE << 1, 0, + VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); ldt = gdt + IA32_PAGE_SIZE; desc.sd_lolimit = 8*NLDT-1; Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c (revision 255249) +++ sys/kern/imgact_elf.c (working copy) @@ -417,8 +417,9 @@ * The mapping is not page aligned. This means we have * to copy the data. Sigh. */ - rv = vm_map_find(map, NULL, 0, &start, end - start, - FALSE, prot | VM_PROT_WRITE, VM_PROT_ALL, 0); + rv = vm_map_find(map, NULL, 0, &start, end - start, 0, + VMFS_NO_SPACE, prot | VM_PROT_WRITE, VM_PROT_ALL, + 0); if (rv) return (rv); if (object == NULL) Index: sys/kern/imgact_gzip.c =================================================================== --- sys/kern/imgact_gzip.c (revision 255249) +++ sys/kern/imgact_gzip.c (working copy) @@ -269,12 +269,9 @@ */ vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; - error = vm_map_find(&vmspace->vm_map, - NULL, - 0, - &vmaddr, - gz->bss_size, - FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, + gz->bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, + 0); if (error) { gz->where = __LINE__; return (error); Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c (revision 255249) +++ sys/kern/init_main.c (working copy) @@ -709,8 +709,8 @@ * Need just enough stack to hold the faked-up "execve()" arguments. */ addr = p->p_sysent->sv_usrstack - PAGE_SIZE; - if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, - FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) + if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 0, + VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) panic("init: couldn't allocate argument space"); p->p_vmspace->vm_maxsaddr = (caddr_t)addr; p->p_vmspace->vm_ssize = 1; Index: sys/kern/link_elf.c =================================================================== --- sys/kern/link_elf.c (revision 255249) +++ sys/kern/link_elf.c (working copy) @@ -891,7 +891,7 @@ } ef->address = (caddr_t) vm_map_min(kernel_map); error = vm_map_find(kernel_map, ef->object, 0, - (vm_offset_t *) &ef->address, mapsize, 1, + (vm_offset_t *) &ef->address, mapsize, 0, VMFS_OPTIMAL_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error != 0) { vm_object_deallocate(ef->object); Index: sys/kern/link_elf_obj.c =================================================================== --- sys/kern/link_elf_obj.c (revision 255249) +++ sys/kern/link_elf_obj.c (working copy) @@ -689,7 +689,8 @@ mapbase = VM_MIN_KERNEL_ADDRESS; #endif error = vm_map_find(kernel_map, ef->object, 0, &mapbase, - round_page(mapsize), TRUE, VM_PROT_ALL, VM_PROT_ALL, FALSE); + round_page(mapsize), 0, VMFS_OPTIMAL_SPACE, VM_PROT_ALL, + VM_PROT_ALL, 0); if (error) { vm_object_deallocate(ef->object); ef->object = 0; Index: sys/kern/sys_pipe.c =================================================================== --- sys/kern/sys_pipe.c (revision 255249) +++ sys/kern/sys_pipe.c (working copy) @@ -524,7 +524,7 @@ buffer = (caddr_t) vm_map_min(pipe_map); error = vm_map_find(pipe_map, NULL, 0, - (vm_offset_t *) &buffer, size, 1, + (vm_offset_t *) &buffer, size, 0, VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error != KERN_SUCCESS) { if ((cpipe->pipe_buffer.buffer == NULL) && Index: sys/kern/sysv_shm.c =================================================================== --- sys/kern/sysv_shm.c (revision 255249) +++ sys/kern/sysv_shm.c (working copy) @@ -413,7 +413,7 @@ 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 : + 0, &attach_va, size, 0, (flags & MAP_FIXED) ? VMFS_NO_SPACE : VMFS_OPTIMAL_SPACE, prot, prot, MAP_INHERIT_SHARE); if (rv != KERN_SUCCESS) { vm_object_deallocate(shmseg->object); Index: sys/kern/uipc_shm.c =================================================================== --- sys/kern/uipc_shm.c (revision 255249) +++ sys/kern/uipc_shm.c (working copy) @@ -954,7 +954,7 @@ ofs = offset & PAGE_MASK; offset = trunc_page(offset); size = round_page(size + ofs); - rv = vm_map_find(kernel_map, obj, offset, &kva, size, + rv = vm_map_find(kernel_map, obj, offset, &kva, size, 0, VMFS_OPTIMAL_SPACE, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE, 0); if (rv == KERN_SUCCESS) { Index: sys/sparc64/sparc64/pmap.c =================================================================== --- sys/sparc64/sparc64/pmap.c (revision 255249) +++ sys/sparc64/sparc64/pmap.c (working copy) @@ -786,7 +786,7 @@ continue; if (addr < VM_MIN_PROM_ADDRESS || addr > VM_MAX_PROM_ADDRESS) continue; - result = vm_map_find(kernel_map, NULL, 0, &addr, size, + result = vm_map_find(kernel_map, NULL, 0, &addr, size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT); if (result != KERN_SUCCESS || addr != translations[i].om_start) panic("pmap_init: vm_map_find"); Index: sys/sys/mman.h =================================================================== --- sys/sys/mman.h (revision 255249) +++ sys/sys/mman.h (working copy) @@ -91,6 +91,9 @@ */ #define MAP_NOCORE 0x00020000 /* dont include these pages in a coredump */ #define MAP_PREFAULT_READ 0x00040000 /* prefault mapping for reading */ +#ifdef __LP64__ +#define MAP_32BIT 0x00080000 /* map in the low 2GB of address space */ +#endif /* * Request specific alignment (n == log2 of the desired alignment). Index: sys/vm/vm_init.c =================================================================== --- sys/vm/vm_init.c (revision 255249) +++ sys/vm/vm_init.c (working copy) @@ -111,7 +111,7 @@ 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); Index: sys/vm/vm_kern.c =================================================================== --- sys/vm/vm_kern.c (revision 255249) +++ sys/vm/vm_kern.c (working copy) @@ -285,7 +285,7 @@ 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) Index: sys/vm/vm_map.c =================================================================== --- sys/vm/vm_map.c (revision 255249) +++ sys/vm/vm_map.c (working copy) @@ -1432,8 +1432,8 @@ 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 @@ 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; Index: sys/vm/vm_map.h =================================================================== --- sys/vm/vm_map.h (revision 255249) +++ sys/vm/vm_map.h (working copy) @@ -366,7 +366,7 @@ 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 *); Index: sys/vm/vm_mmap.c =================================================================== --- sys/vm/vm_mmap.c (revision 255249) +++ sys/vm/vm_mmap.c (working copy) @@ -94,10 +94,8 @@ "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_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 @@ 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 @@ 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); Index: usr.bin/kdump/mksubr =================================================================== --- usr.bin/kdump/mksubr (revision 255249) +++ usr.bin/kdump/mksubr (working copy) @@ -497,6 +497,10 @@ ++i; \ printf "\tif (!((flags > 0) ^ ((%s) > 0)))\n\t\tif_print_or(flags, %s, or);\n", $i, $i }' cat <<_EOF_ +#ifdef MAP_32BIT + if (!((flags > 0) ^ ((MAP_32BIT) > 0))) + if_print_or(flags, MAP_32BIT, or); +#endif align = flags & MAP_ALIGNMENT_MASK; if (align != 0) { if (align == MAP_ALIGNED_SUPER) Index: usr.bin/truss/syscalls.c =================================================================== --- usr.bin/truss/syscalls.c (revision 255249) +++ usr.bin/truss/syscalls.c (working copy) @@ -296,7 +296,11 @@ X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RENAME) X(MAP_NORESERVE) X(MAP_RESERVED0080) X(MAP_RESERVED0100) X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON) - X(MAP_NOCORE) X(MAP_PREFAULT_READ) XEND + X(MAP_NOCORE) X(MAP_PREFAULT_READ) +#ifdef MAP_32BIT + X(MAP_32BIT) +#endif + XEND }; static struct xlat mprot_flags[] = {