diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1978,23 +1978,30 @@ static int cluster_anon = 1; SYSCTL_INT(_vm, OID_AUTO, cluster_anon, CTLFLAG_RW, &cluster_anon, 0, - "Cluster anonymous mappings: 0 = no, 1 = yes if no hint, 2 = always"); + "Cluster anonymous mappings: " + "0 = no, 1 = yes if no hint, 2 = always, 3 = keep anon_loc const"); static bool -clustering_anon_allowed(vm_offset_t addr) +clustering_anon_allowed(vm_offset_t addr, vm_offset_t anon_loc) { switch (cluster_anon) { case 0: return (false); case 1: - return (addr == 0); + return (addr == 0 || addr <= anon_loc); case 2: default: return (true); } } +static bool +clustering_anon_loc_const(void) +{ + return (cluster_anon == 3); +} + static long aslr_restarts; SYSCTL_LONG(_vm, OID_AUTO, aslr_restarts, CTLFLAG_RD, &aslr_restarts, 0, @@ -2093,6 +2100,7 @@ vm_size_t length, vm_offset_t max_addr, int find_space, vm_prot_t prot, vm_prot_t max, int cow) { + vm_map_entry_t entry; vm_offset_t alignment, curr_min_addr, min_addr; int gap, pidx, rv, try; bool cluster, en_aslr, update_anon; @@ -2111,7 +2119,7 @@ } else alignment = 0; en_aslr = (map->flags & MAP_ASLR) != 0; - update_anon = cluster = clustering_anon_allowed(*addr) && + update_anon = cluster = clustering_anon_allowed(*addr, map->anon_loc) && (map->flags & MAP_IS_SUB_MAP) == 0 && max_addr == 0 && find_space != VMFS_NO_SPACE && object == NULL && (cow & (MAP_INHERIT_SHARE | MAP_STACK_GROWS_UP | @@ -2127,6 +2135,8 @@ curr_min_addr = map->anon_loc; if (curr_min_addr == 0) cluster = false; + else if (!vm_map_lookup_entry(map, curr_min_addr, &entry)) + curr_min_addr = entry->end; } if (find_space != VMFS_NO_SPACE) { KASSERT(find_space == VMFS_ANY_SPACE || @@ -2226,7 +2236,7 @@ rv = vm_map_insert(map, object, offset, *addr, *addr + length, prot, max, cow); } - if (rv == KERN_SUCCESS && update_anon) + if (rv == KERN_SUCCESS && update_anon && !clustering_anon_loc_const()) map->anon_loc = *addr + length; done: vm_map_unlock(map); @@ -3966,7 +3976,7 @@ entry->object.vm_object != NULL) pmap_map_delete(map->pmap, entry->start, entry->end); - if (entry->end == map->anon_loc) + if (entry->end == map->anon_loc && !clustering_anon_loc_const()) map->anon_loc = entry->start; /*