* Searches for the specified amount of free space in the given map with the * specified alignment. Performs an address-ordered, first-fit search from * the given address "*addr", with an optional upper bound "max_addr". If the * parameter "alignment" is zero, then the alignment is computed from the * given (object, offset) pair so as to enable the greatest possible use of * superpage mappin
| 2044 | * of free space at the given address. |
| 2045 | */ |
| 2046 | static int |
| 2047 | vm_map_alignspace(vm_map_t map, vm_object_t object, vm_ooffset_t offset, |
| 2048 | vm_offset_t *addr, vm_size_t length, vm_offset_t max_addr, |
| 2049 | vm_offset_t alignment) |
| 2050 | { |
| 2051 | vm_offset_t aligned_addr, free_addr; |
| 2052 | |
| 2053 | VM_MAP_ASSERT_LOCKED(map); |
| 2054 | free_addr = *addr; |
| 2055 | KASSERT(free_addr == vm_map_findspace(map, free_addr, length), |
| 2056 | ("caller failed to provide space %#jx at address %p", |
| 2057 | (uintmax_t)length, (void *)free_addr)); |
| 2058 | for (;;) { |
| 2059 | /* |
| 2060 | * At the start of every iteration, the free space at address |
| 2061 | * "*addr" is at least "length" bytes. |
| 2062 | */ |
| 2063 | if (alignment == 0) |
| 2064 | pmap_align_superpage(object, offset, addr, length); |
| 2065 | else if ((*addr & (alignment - 1)) != 0) { |
| 2066 | *addr &= ~(alignment - 1); |
| 2067 | *addr += alignment; |
| 2068 | } |
| 2069 | aligned_addr = *addr; |
| 2070 | if (aligned_addr == free_addr) { |
| 2071 | /* |
| 2072 | * Alignment did not change "*addr", so "*addr" must |
| 2073 | * still provide sufficient free space. |
| 2074 | */ |
| 2075 | return (KERN_SUCCESS); |
| 2076 | } |
| 2077 | |
| 2078 | /* |
| 2079 | * Test for address wrap on "*addr". A wrapped "*addr" could |
| 2080 | * be a valid address, in which case vm_map_findspace() cannot |
| 2081 | * be relied upon to fail. |
| 2082 | */ |
| 2083 | if (aligned_addr < free_addr) |
| 2084 | return (KERN_NO_SPACE); |
| 2085 | *addr = vm_map_findspace(map, aligned_addr, length); |
| 2086 | if (*addr + length > vm_map_max(map) || |
| 2087 | (max_addr != 0 && *addr + length > max_addr)) |
| 2088 | return (KERN_NO_SPACE); |
| 2089 | free_addr = *addr; |
| 2090 | if (free_addr == aligned_addr) { |
| 2091 | /* |
| 2092 | * If a successful call to vm_map_findspace() did not |
| 2093 | * change "*addr", then "*addr" must still be aligned |
| 2094 | * and provide sufficient free space. |
| 2095 | */ |
| 2096 | return (KERN_SUCCESS); |
| 2097 | } |
| 2098 | } |
| 2099 | } |
| 2100 | |
| 2101 | int |
| 2102 | vm_map_find_aligned(vm_map_t map, vm_offset_t *addr, vm_size_t length, |
no test coverage detected