Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'memblock-v6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock

Pull memblock updates from Mike Rapoport:

- 'reserve_mem' command line parameter to allow creation of named
memory reservation at boot time.

The driving use-case is to improve the ability of pstore to retain
ramoops data across reboots.

- cleanups and small improvements in memblock and mm_init

- new tests cases in memblock test suite

* tag 'memblock-v6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock:
memblock tests: fix implicit declaration of function 'numa_valid_node'
memblock: Move late alloc warning down to phys alloc
pstore/ramoops: Add ramoops.mem_name= command line option
mm/memblock: Add "reserve_mem" to reserved named memory at boot up
mm/mm_init.c: don't initialize page->lru again
mm/mm_init.c: not always search next deferred_init_pfn from very beginning
mm/mm_init.c: use deferred_init_mem_pfn_range_in_zone() to decide loop condition
mm/mm_init.c: get the highest zone directly
mm/mm_init.c: move nr_initialised reset down a bit
mm/memblock: fix a typo in description of for_each_mem_region()
mm/mm_init.c: use memblock_region_memory_base_pfn() to get startpfn
mm/memblock: use PAGE_ALIGN_DOWN to get pgend in free_memmap
mm/memblock: return true directly on finding overlap region
memblock tests: add memblock_overlaps_region_checks
mm/memblock: fix comment for memblock_isolate_range()
memblock tests: add memblock_reserve_many_may_conflict_check()
memblock tests: add memblock_reserve_all_locations_check()
mm/memblock: remove empty dummy entry

+542 -82
+22
Documentation/admin-guide/kernel-parameters.txt
··· 5674 5674 them. If <base> is less than 0x10000, the region 5675 5675 is assumed to be I/O ports; otherwise it is memory. 5676 5676 5677 + reserve_mem= [RAM] 5678 + Format: nn[KNG]:<align>:<label> 5679 + Reserve physical memory and label it with a name that 5680 + other subsystems can use to access it. This is typically 5681 + used for systems that do not wipe the RAM, and this command 5682 + line will try to reserve the same physical memory on 5683 + soft reboots. Note, it is not guaranteed to be the same 5684 + location. For example, if anything about the system changes 5685 + or if booting a different kernel. It can also fail if KASLR 5686 + places the kernel at the location of where the RAM reservation 5687 + was from a previous boot, the new reservation will be at a 5688 + different location. 5689 + Any subsystem using this feature must add a way to verify 5690 + that the contents of the physical memory is from a previous 5691 + boot, as there may be cases where the memory will not be 5692 + located at the same location. 5693 + 5694 + The format is size:align:label for example, to request 5695 + 12 megabytes of 4096 alignment for ramoops: 5696 + 5697 + reserve_mem=12M:4096:oops ramoops.mem_name=oops 5698 + 5677 5699 reservetop= [X86-32,EARLY] 5678 5700 Format: nn[KMG] 5679 5701 Reserves a hole at the top of the kernel virtual
+13
Documentation/admin-guide/ramoops.rst
··· 23 23 * ``mem_size`` for the size. The memory size will be rounded down to a 24 24 power of two. 25 25 * ``mem_type`` to specify if the memory type (default is pgprot_writecombine). 26 + * ``mem_name`` to specify a memory region defined by ``reserve_mem`` command 27 + line parameter. 26 28 27 29 Typically the default value of ``mem_type=0`` should be used as that sets the pstore 28 30 mapping to pgprot_writecombine. Setting ``mem_type=1`` attempts to use ··· 119 117 printk(KERN_ERR "unable to register platform device\n"); 120 118 return ret; 121 119 } 120 + 121 + D. Using a region of memory reserved via ``reserve_mem`` command line 122 + parameter. The address and size will be defined by the ``reserve_mem`` 123 + parameter. Note, that ``reserve_mem`` may not always allocate memory 124 + in the same location, and cannot be relied upon. Testing will need 125 + to be done, and it may not work on every machine, nor every kernel. 126 + Consider this a "best effort" approach. The ``reserve_mem`` option 127 + takes a size, alignment and name as arguments. The name is used 128 + to map the memory to a label that can be retrieved by ramoops. 129 + 130 + reserver_mem=2M:4096:oops ramoops.mem_name=oops 122 131 123 132 You can specify either RAM memory or peripheral devices' memory. However, when 124 133 specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
+14
fs/pstore/ram.c
··· 50 50 MODULE_PARM_DESC(mem_address, 51 51 "start of reserved RAM used to store oops/panic logs"); 52 52 53 + static char *mem_name; 54 + module_param_named(mem_name, mem_name, charp, 0400); 55 + MODULE_PARM_DESC(mem_name, "name of kernel param that holds addr"); 56 + 53 57 static ulong mem_size; 54 58 module_param(mem_size, ulong, 0400); 55 59 MODULE_PARM_DESC(mem_size, ··· 917 913 static void __init ramoops_register_dummy(void) 918 914 { 919 915 struct ramoops_platform_data pdata; 916 + 917 + if (mem_name) { 918 + phys_addr_t start; 919 + phys_addr_t size; 920 + 921 + if (reserve_mem_find_by_name(mem_name, &start, &size)) { 922 + mem_address = start; 923 + mem_size = size; 924 + } 925 + } 920 926 921 927 /* 922 928 * Prepare a dummy platform data structure to carry the module
+1 -20
include/linux/memblock.h
··· 299 299 void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone, 300 300 unsigned long *out_spfn, 301 301 unsigned long *out_epfn); 302 - /** 303 - * for_each_free_mem_pfn_range_in_zone - iterate through zone specific free 304 - * memblock areas 305 - * @i: u64 used as loop variable 306 - * @zone: zone in which all of the memory blocks reside 307 - * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL 308 - * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL 309 - * 310 - * Walks over free (memory && !reserved) areas of memblock in a specific 311 - * zone. Available once memblock and an empty zone is initialized. The main 312 - * assumption is that the zone start, end, and pgdat have been associated. 313 - * This way we can use the zone to determine NUMA node, and if a given part 314 - * of the memblock is valid for the zone. 315 - */ 316 - #define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end) \ 317 - for (i = 0, \ 318 - __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end); \ 319 - i != U64_MAX; \ 320 - __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end)) 321 302 322 303 /** 323 304 * for_each_free_mem_pfn_range_in_zone_from - iterate through zone specific ··· 546 565 } 547 566 548 567 /** 549 - * for_each_mem_region - itereate over memory regions 568 + * for_each_mem_region - iterate over memory regions 550 569 * @region: loop variable 551 570 */ 552 571 #define for_each_mem_region(region) \
+2
include/linux/mm.h
··· 4261 4261 void vma_pgtable_walk_begin(struct vm_area_struct *vma); 4262 4262 void vma_pgtable_walk_end(struct vm_area_struct *vma); 4263 4263 4264 + int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); 4265 + 4264 4266 #endif /* _LINUX_MM_H */
+135 -16
mm/memblock.c
··· 114 114 115 115 struct memblock memblock __initdata_memblock = { 116 116 .memory.regions = memblock_memory_init_regions, 117 - .memory.cnt = 1, /* empty dummy entry */ 118 117 .memory.max = INIT_MEMBLOCK_MEMORY_REGIONS, 119 118 .memory.name = "memory", 120 119 121 120 .reserved.regions = memblock_reserved_init_regions, 122 - .reserved.cnt = 1, /* empty dummy entry */ 123 121 .reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS, 124 122 .reserved.name = "reserved", 125 123 ··· 128 130 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP 129 131 struct memblock_type physmem = { 130 132 .regions = memblock_physmem_init_regions, 131 - .cnt = 1, /* empty dummy entry */ 132 133 .max = INIT_PHYSMEM_REGIONS, 133 134 .name = "physmem", 134 135 }; ··· 194 197 for (i = 0; i < type->cnt; i++) 195 198 if (memblock_addrs_overlap(base, size, type->regions[i].base, 196 199 type->regions[i].size)) 197 - break; 198 - return i < type->cnt; 200 + return true; 201 + return false; 199 202 } 200 203 201 204 /** ··· 353 356 /* Special case for empty arrays */ 354 357 if (type->cnt == 0) { 355 358 WARN_ON(type->total_size != 0); 356 - type->cnt = 1; 357 359 type->regions[0].base = 0; 358 360 type->regions[0].size = 0; 359 361 type->regions[0].flags = 0; ··· 596 600 597 601 /* special case for empty array */ 598 602 if (type->regions[0].size == 0) { 599 - WARN_ON(type->cnt != 1 || type->total_size); 603 + WARN_ON(type->cnt != 0 || type->total_size); 600 604 type->regions[0].base = base; 601 605 type->regions[0].size = size; 602 606 type->regions[0].flags = flags; 603 607 memblock_set_region_node(&type->regions[0], nid); 604 608 type->total_size = size; 609 + type->cnt = 1; 605 610 return 0; 606 611 } 607 612 ··· 777 780 * Walk @type and ensure that regions don't cross the boundaries defined by 778 781 * [@base, @base + @size). Crossing regions are split at the boundaries, 779 782 * which may create at most two more regions. The index of the first 780 - * region inside the range is returned in *@start_rgn and end in *@end_rgn. 783 + * region inside the range is returned in *@start_rgn and the index of the 784 + * first region after the range is returned in *@end_rgn. 781 785 * 782 786 * Return: 783 787 * 0 on success, -errno on failure. ··· 1439 1441 enum memblock_flags flags = choose_memblock_flags(); 1440 1442 phys_addr_t found; 1441 1443 1444 + /* 1445 + * Detect any accidental use of these APIs after slab is ready, as at 1446 + * this moment memblock may be deinitialized already and its 1447 + * internal data may be destroyed (after execution of memblock_free_all) 1448 + */ 1449 + if (WARN_ON_ONCE(slab_is_available())) { 1450 + void *vaddr = kzalloc_node(size, GFP_NOWAIT, nid); 1451 + 1452 + return vaddr ? virt_to_phys(vaddr) : 0; 1453 + } 1454 + 1442 1455 if (!align) { 1443 1456 /* Can't use WARNs this early in boot on powerpc */ 1444 1457 dump_stack(); ··· 1575 1566 { 1576 1567 phys_addr_t alloc; 1577 1568 1578 - /* 1579 - * Detect any accidental use of these APIs after slab is ready, as at 1580 - * this moment memblock may be deinitialized already and its 1581 - * internal data may be destroyed (after execution of memblock_free_all) 1582 - */ 1583 - if (WARN_ON_ONCE(slab_is_available())) 1584 - return kzalloc_node(size, GFP_NOWAIT, nid); 1585 1569 1586 1570 if (max_addr > memblock.current_limit) 1587 1571 max_addr = memblock.current_limit; ··· 2033 2031 * downwards. 2034 2032 */ 2035 2033 pg = PAGE_ALIGN(__pa(start_pg)); 2036 - pgend = __pa(end_pg) & PAGE_MASK; 2034 + pgend = PAGE_ALIGN_DOWN(__pa(end_pg)); 2037 2035 2038 2036 /* 2039 2037 * If there are free pages between these, free the section of the ··· 2235 2233 pages = free_low_memory_core_early(); 2236 2234 totalram_pages_add(pages); 2237 2235 } 2236 + 2237 + /* Keep a table to reserve named memory */ 2238 + #define RESERVE_MEM_MAX_ENTRIES 8 2239 + #define RESERVE_MEM_NAME_SIZE 16 2240 + struct reserve_mem_table { 2241 + char name[RESERVE_MEM_NAME_SIZE]; 2242 + phys_addr_t start; 2243 + phys_addr_t size; 2244 + }; 2245 + static struct reserve_mem_table reserved_mem_table[RESERVE_MEM_MAX_ENTRIES]; 2246 + static int reserved_mem_count; 2247 + 2248 + /* Add wildcard region with a lookup name */ 2249 + static void __init reserved_mem_add(phys_addr_t start, phys_addr_t size, 2250 + const char *name) 2251 + { 2252 + struct reserve_mem_table *map; 2253 + 2254 + map = &reserved_mem_table[reserved_mem_count++]; 2255 + map->start = start; 2256 + map->size = size; 2257 + strscpy(map->name, name); 2258 + } 2259 + 2260 + /** 2261 + * reserve_mem_find_by_name - Find reserved memory region with a given name 2262 + * @name: The name that is attached to a reserved memory region 2263 + * @start: If found, holds the start address 2264 + * @size: If found, holds the size of the address. 2265 + * 2266 + * @start and @size are only updated if @name is found. 2267 + * 2268 + * Returns: 1 if found or 0 if not found. 2269 + */ 2270 + int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size) 2271 + { 2272 + struct reserve_mem_table *map; 2273 + int i; 2274 + 2275 + for (i = 0; i < reserved_mem_count; i++) { 2276 + map = &reserved_mem_table[i]; 2277 + if (!map->size) 2278 + continue; 2279 + if (strcmp(name, map->name) == 0) { 2280 + *start = map->start; 2281 + *size = map->size; 2282 + return 1; 2283 + } 2284 + } 2285 + return 0; 2286 + } 2287 + EXPORT_SYMBOL_GPL(reserve_mem_find_by_name); 2288 + 2289 + /* 2290 + * Parse reserve_mem=nn:align:name 2291 + */ 2292 + static int __init reserve_mem(char *p) 2293 + { 2294 + phys_addr_t start, size, align, tmp; 2295 + char *name; 2296 + char *oldp; 2297 + int len; 2298 + 2299 + if (!p) 2300 + return -EINVAL; 2301 + 2302 + /* Check if there's room for more reserved memory */ 2303 + if (reserved_mem_count >= RESERVE_MEM_MAX_ENTRIES) 2304 + return -EBUSY; 2305 + 2306 + oldp = p; 2307 + size = memparse(p, &p); 2308 + if (!size || p == oldp) 2309 + return -EINVAL; 2310 + 2311 + if (*p != ':') 2312 + return -EINVAL; 2313 + 2314 + align = memparse(p+1, &p); 2315 + if (*p != ':') 2316 + return -EINVAL; 2317 + 2318 + /* 2319 + * memblock_phys_alloc() doesn't like a zero size align, 2320 + * but it is OK for this command to have it. 2321 + */ 2322 + if (align < SMP_CACHE_BYTES) 2323 + align = SMP_CACHE_BYTES; 2324 + 2325 + name = p + 1; 2326 + len = strlen(name); 2327 + 2328 + /* name needs to have length but not too big */ 2329 + if (!len || len >= RESERVE_MEM_NAME_SIZE) 2330 + return -EINVAL; 2331 + 2332 + /* Make sure that name has text */ 2333 + for (p = name; *p; p++) { 2334 + if (!isspace(*p)) 2335 + break; 2336 + } 2337 + if (!*p) 2338 + return -EINVAL; 2339 + 2340 + /* Make sure the name is not already used */ 2341 + if (reserve_mem_find_by_name(name, &start, &tmp)) 2342 + return -EBUSY; 2343 + 2344 + start = memblock_phys_alloc(size, align); 2345 + if (!start) 2346 + return -ENOMEM; 2347 + 2348 + reserved_mem_add(start, size, name); 2349 + 2350 + return 1; 2351 + } 2352 + __setup("reserve_mem=", reserve_mem); 2238 2353 2239 2354 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK) 2240 2355 static const char * const flagname[] = {
+31 -38
mm/mm_init.c
··· 363 363 364 364 nid = memblock_get_region_node(r); 365 365 366 - usable_startpfn = PFN_DOWN(r->base); 366 + usable_startpfn = memblock_region_memory_base_pfn(r); 367 367 zone_movable_pfn[nid] = zone_movable_pfn[nid] ? 368 368 min(usable_startpfn, zone_movable_pfn[nid]) : 369 369 usable_startpfn; ··· 676 676 677 677 if (early_page_ext_enabled()) 678 678 return false; 679 + 680 + /* Always populate low zones for address-constrained allocations */ 681 + if (end_pfn < pgdat_end_pfn(NODE_DATA(nid))) 682 + return false; 683 + 684 + if (NODE_DATA(nid)->first_deferred_pfn != ULONG_MAX) 685 + return true; 686 + 679 687 /* 680 688 * prev_end_pfn static that contains the end of previous zone 681 689 * No need to protect because called very early in boot before smp_init. ··· 693 685 nr_initialised = 0; 694 686 } 695 687 696 - /* Always populate low zones for address-constrained allocations */ 697 - if (end_pfn < pgdat_end_pfn(NODE_DATA(nid))) 698 - return false; 699 - 700 - if (NODE_DATA(nid)->first_deferred_pfn != ULONG_MAX) 701 - return true; 702 688 /* 703 689 * We start only with one section of pages, more pages are added as 704 690 * needed until the rest of deferred pages are initialized. ··· 759 757 struct page *page = pfn_to_page(start_pfn); 760 758 761 759 init_reserved_page(start_pfn, nid); 762 - 763 - /* Avoid false-positive PageTail() */ 764 - INIT_LIST_HEAD(&page->lru); 765 760 766 761 /* 767 762 * no need for atomic set_bit because the struct ··· 2018 2019 } 2019 2020 2020 2021 /* 2021 - * This function is meant to pre-load the iterator for the zone init. 2022 - * Specifically it walks through the ranges until we are caught up to the 2023 - * first_init_pfn value and exits there. If we never encounter the value we 2024 - * return false indicating there are no valid ranges left. 2022 + * This function is meant to pre-load the iterator for the zone init from 2023 + * a given point. 2024 + * Specifically it walks through the ranges starting with initial index 2025 + * passed to it until we are caught up to the first_init_pfn value and 2026 + * exits there. If we never encounter the value we return false indicating 2027 + * there are no valid ranges left. 2025 2028 */ 2026 2029 static bool __init 2027 2030 deferred_init_mem_pfn_range_in_zone(u64 *i, struct zone *zone, 2028 2031 unsigned long *spfn, unsigned long *epfn, 2029 2032 unsigned long first_init_pfn) 2030 2033 { 2031 - u64 j; 2034 + u64 j = *i; 2035 + 2036 + if (j == 0) 2037 + __next_mem_pfn_range_in_zone(&j, zone, spfn, epfn); 2032 2038 2033 2039 /* 2034 2040 * Start out by walking through the ranges in this zone that have 2035 2041 * already been initialized. We don't need to do anything with them 2036 2042 * so we just need to flush them out of the system. 2037 2043 */ 2038 - for_each_free_mem_pfn_range_in_zone(j, zone, spfn, epfn) { 2044 + for_each_free_mem_pfn_range_in_zone_from(j, zone, spfn, epfn) { 2039 2045 if (*epfn <= first_init_pfn) 2040 2046 continue; 2041 2047 if (*spfn < first_init_pfn) ··· 2112 2108 { 2113 2109 unsigned long spfn, epfn; 2114 2110 struct zone *zone = arg; 2115 - u64 i; 2111 + u64 i = 0; 2116 2112 2117 2113 deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn, start_pfn); 2118 2114 ··· 2142 2138 unsigned long first_init_pfn, flags; 2143 2139 unsigned long start = jiffies; 2144 2140 struct zone *zone; 2145 - int zid, max_threads; 2146 - u64 i; 2141 + int max_threads; 2142 + u64 i = 0; 2147 2143 2148 2144 /* Bind memory initialisation thread to a local node if possible */ 2149 2145 if (!cpumask_empty(cpumask)) ··· 2169 2165 */ 2170 2166 pgdat_resize_unlock(pgdat, &flags); 2171 2167 2172 - /* Only the highest zone is deferred so find it */ 2173 - for (zid = 0; zid < MAX_NR_ZONES; zid++) { 2174 - zone = pgdat->node_zones + zid; 2175 - if (first_init_pfn < zone_end_pfn(zone)) 2176 - break; 2177 - } 2178 - 2179 - /* If the zone is empty somebody else may have cleared out the zone */ 2180 - if (!deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn, 2181 - first_init_pfn)) 2182 - goto zone_empty; 2168 + /* Only the highest zone is deferred */ 2169 + zone = pgdat->node_zones + pgdat->nr_zones - 1; 2183 2170 2184 2171 max_threads = deferred_page_init_max_threads(cpumask); 2185 2172 2186 - while (spfn < epfn) { 2187 - unsigned long epfn_align = ALIGN(epfn, PAGES_PER_SECTION); 2173 + while (deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn, first_init_pfn)) { 2174 + first_init_pfn = ALIGN(epfn, PAGES_PER_SECTION); 2188 2175 struct padata_mt_job job = { 2189 2176 .thread_fn = deferred_init_memmap_chunk, 2190 2177 .fn_arg = zone, 2191 2178 .start = spfn, 2192 - .size = epfn_align - spfn, 2179 + .size = first_init_pfn - spfn, 2193 2180 .align = PAGES_PER_SECTION, 2194 2181 .min_chunk = PAGES_PER_SECTION, 2195 2182 .max_threads = max_threads, ··· 2188 2193 }; 2189 2194 2190 2195 padata_do_multithreaded(&job); 2191 - deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn, 2192 - epfn_align); 2193 2196 } 2194 - zone_empty: 2197 + 2195 2198 /* Sanity check that the next zone really is unpopulated */ 2196 - WARN_ON(++zid < MAX_NR_ZONES && populated_zone(++zone)); 2199 + WARN_ON(pgdat->nr_zones < MAX_NR_ZONES && populated_zone(++zone)); 2197 2200 2198 2201 pr_info("node %d deferred pages initialised in %ums\n", 2199 2202 pgdat->node_id, jiffies_to_msecs(jiffies - start)); ··· 2218 2225 unsigned long first_deferred_pfn = pgdat->first_deferred_pfn; 2219 2226 unsigned long spfn, epfn, flags; 2220 2227 unsigned long nr_pages = 0; 2221 - u64 i; 2228 + u64 i = 0; 2222 2229 2223 2230 /* Only the last zone may have deferred pages */ 2224 2231 if (zone_end_pfn(zone) != pgdat_end_pfn(pgdat))
+1
tools/include/linux/mm.h
··· 12 12 #define PHYS_ADDR_MAX (~(phys_addr_t)0) 13 13 14 14 #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) 15 + #define PAGE_ALIGN_DOWN(addr) ALIGN_DOWN(addr, PAGE_SIZE) 15 16 16 17 #define __va(x) ((void *)((unsigned long)(x))) 17 18 #define __pa(x) ((unsigned long)(x))
+5
tools/include/linux/numa.h
··· 13 13 14 14 #define NUMA_NO_NODE (-1) 15 15 16 + static inline bool numa_valid_node(int nid) 17 + { 18 + return nid >= 0 && nid < MAX_NUMNODES; 19 + } 20 + 16 21 #endif /* _LINUX_NUMA_H */
+310 -4
tools/testing/memblock/tests/basic_api.c
··· 15 15 PREFIX_PUSH(); 16 16 17 17 ASSERT_NE(memblock.memory.regions, NULL); 18 - ASSERT_EQ(memblock.memory.cnt, 1); 18 + ASSERT_EQ(memblock.memory.cnt, 0); 19 19 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 20 20 ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0); 21 21 22 22 ASSERT_NE(memblock.reserved.regions, NULL); 23 - ASSERT_EQ(memblock.reserved.cnt, 1); 23 + ASSERT_EQ(memblock.reserved.cnt, 0); 24 24 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 25 25 ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0); 26 26 ··· 982 982 return 0; 983 983 } 984 984 985 + 986 + /* 987 + * A test that trying to reserve the 129th memory block at all locations. 988 + * Expect to trigger memblock_double_array() to double the 989 + * memblock.memory.max, find a new valid memory as reserved.regions. 990 + * 991 + * 0 1 2 128 992 + * +-------+ +-------+ +-------+ +-------+ 993 + * | 32K | | 32K | | 32K | ... | 32K | 994 + * +-------+-------+-------+-------+-------+ +-------+ 995 + * |<-32K->| |<-32K->| 996 + * 997 + */ 998 + /* Keep the gap so these memory region will not be merged. */ 999 + #define MEMORY_BASE(idx) (SZ_128K + (MEM_SIZE * 2) * (idx)) 1000 + static int memblock_reserve_all_locations_check(void) 1001 + { 1002 + int i, skip; 1003 + void *orig_region; 1004 + struct region r = { 1005 + .base = SZ_16K, 1006 + .size = SZ_16K, 1007 + }; 1008 + phys_addr_t new_reserved_regions_size; 1009 + 1010 + PREFIX_PUSH(); 1011 + 1012 + /* Reserve the 129th memory block for all possible positions*/ 1013 + for (skip = 0; skip < INIT_MEMBLOCK_REGIONS + 1; skip++) { 1014 + reset_memblock_regions(); 1015 + memblock_allow_resize(); 1016 + 1017 + /* Add a valid memory region used by double_array(). */ 1018 + dummy_physical_memory_init(); 1019 + memblock_add(dummy_physical_memory_base(), MEM_SIZE); 1020 + 1021 + for (i = 0; i < INIT_MEMBLOCK_REGIONS + 1; i++) { 1022 + if (i == skip) 1023 + continue; 1024 + 1025 + /* Reserve some fakes memory region to fulfill the memblock. */ 1026 + memblock_reserve(MEMORY_BASE(i), MEM_SIZE); 1027 + 1028 + if (i < skip) { 1029 + ASSERT_EQ(memblock.reserved.cnt, i + 1); 1030 + ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE); 1031 + } else { 1032 + ASSERT_EQ(memblock.reserved.cnt, i); 1033 + ASSERT_EQ(memblock.reserved.total_size, i * MEM_SIZE); 1034 + } 1035 + } 1036 + 1037 + orig_region = memblock.reserved.regions; 1038 + 1039 + /* This reserve the 129 memory_region, and makes it double array. */ 1040 + memblock_reserve(MEMORY_BASE(skip), MEM_SIZE); 1041 + 1042 + /* 1043 + * This is the memory region size used by the doubled reserved.regions, 1044 + * and it has been reserved due to it has been used. The size is used to 1045 + * calculate the total_size that the memblock.reserved have now. 1046 + */ 1047 + new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) * 1048 + sizeof(struct memblock_region)); 1049 + /* 1050 + * The double_array() will find a free memory region as the new 1051 + * reserved.regions, and the used memory region will be reserved, so 1052 + * there will be one more region exist in the reserved memblock. And the 1053 + * one more reserved region's size is new_reserved_regions_size. 1054 + */ 1055 + ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2); 1056 + ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 1057 + new_reserved_regions_size); 1058 + ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 1059 + 1060 + /* 1061 + * Now memblock_double_array() works fine. Let's check after the 1062 + * double_array(), the memblock_reserve() still works as normal. 1063 + */ 1064 + memblock_reserve(r.base, r.size); 1065 + ASSERT_EQ(memblock.reserved.regions[0].base, r.base); 1066 + ASSERT_EQ(memblock.reserved.regions[0].size, r.size); 1067 + 1068 + ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3); 1069 + ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 1070 + new_reserved_regions_size + 1071 + r.size); 1072 + ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 1073 + 1074 + dummy_physical_memory_cleanup(); 1075 + 1076 + /* 1077 + * The current reserved.regions is occupying a range of memory that 1078 + * allocated from dummy_physical_memory_init(). After free the memory, 1079 + * we must not use it. So restore the origin memory region to make sure 1080 + * the tests can run as normal and not affected by the double array. 1081 + */ 1082 + memblock.reserved.regions = orig_region; 1083 + memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS; 1084 + } 1085 + 1086 + test_pass_pop(); 1087 + 1088 + return 0; 1089 + } 1090 + 1091 + /* 1092 + * A test that trying to reserve the 129th memory block at all locations. 1093 + * Expect to trigger memblock_double_array() to double the 1094 + * memblock.memory.max, find a new valid memory as reserved.regions. And make 1095 + * sure it doesn't conflict with the range we want to reserve. 1096 + * 1097 + * For example, we have 128 regions in reserved and now want to reserve 1098 + * the skipped one. Since reserved is full, memblock_double_array() would find 1099 + * an available range in memory for the new array. We intended to put two 1100 + * ranges in memory with one is the exact range of the skipped one. Before 1101 + * commit 48c3b583bbdd ("mm/memblock: fix overlapping allocation when doubling 1102 + * reserved array"), the new array would sits in the skipped range which is a 1103 + * conflict. The expected new array should be allocated from memory.regions[0]. 1104 + * 1105 + * 0 1 1106 + * memory +-------+ +-------+ 1107 + * | 32K | | 32K | 1108 + * +-------+ ------+-------+-------+-------+ 1109 + * |<-32K->|<-32K->|<-32K->| 1110 + * 1111 + * 0 skipped 127 1112 + * reserved +-------+ ......... +-------+ 1113 + * | 32K | . 32K . ... | 32K | 1114 + * +-------+-------+-------+ +-------+ 1115 + * |<-32K->| 1116 + * ^ 1117 + * | 1118 + * | 1119 + * skipped one 1120 + */ 1121 + /* Keep the gap so these memory region will not be merged. */ 1122 + #define MEMORY_BASE_OFFSET(idx, offset) ((offset) + (MEM_SIZE * 2) * (idx)) 1123 + static int memblock_reserve_many_may_conflict_check(void) 1124 + { 1125 + int i, skip; 1126 + void *orig_region; 1127 + struct region r = { 1128 + .base = SZ_16K, 1129 + .size = SZ_16K, 1130 + }; 1131 + phys_addr_t new_reserved_regions_size; 1132 + 1133 + /* 1134 + * 0 1 129 1135 + * +---+ +---+ +---+ 1136 + * |32K| |32K| .. |32K| 1137 + * +---+ +---+ +---+ 1138 + * 1139 + * Pre-allocate the range for 129 memory block + one range for double 1140 + * memblock.reserved.regions at idx 0. 1141 + */ 1142 + dummy_physical_memory_init(); 1143 + phys_addr_t memory_base = dummy_physical_memory_base(); 1144 + phys_addr_t offset = PAGE_ALIGN(memory_base); 1145 + 1146 + PREFIX_PUSH(); 1147 + 1148 + /* Reserve the 129th memory block for all possible positions*/ 1149 + for (skip = 1; skip <= INIT_MEMBLOCK_REGIONS + 1; skip++) { 1150 + reset_memblock_regions(); 1151 + memblock_allow_resize(); 1152 + 1153 + reset_memblock_attributes(); 1154 + /* Add a valid memory region used by double_array(). */ 1155 + memblock_add(MEMORY_BASE_OFFSET(0, offset), MEM_SIZE); 1156 + /* 1157 + * Add a memory region which will be reserved as 129th memory 1158 + * region. This is not expected to be used by double_array(). 1159 + */ 1160 + memblock_add(MEMORY_BASE_OFFSET(skip, offset), MEM_SIZE); 1161 + 1162 + for (i = 1; i <= INIT_MEMBLOCK_REGIONS + 1; i++) { 1163 + if (i == skip) 1164 + continue; 1165 + 1166 + /* Reserve some fakes memory region to fulfill the memblock. */ 1167 + memblock_reserve(MEMORY_BASE_OFFSET(i, offset), MEM_SIZE); 1168 + 1169 + if (i < skip) { 1170 + ASSERT_EQ(memblock.reserved.cnt, i); 1171 + ASSERT_EQ(memblock.reserved.total_size, i * MEM_SIZE); 1172 + } else { 1173 + ASSERT_EQ(memblock.reserved.cnt, i - 1); 1174 + ASSERT_EQ(memblock.reserved.total_size, (i - 1) * MEM_SIZE); 1175 + } 1176 + } 1177 + 1178 + orig_region = memblock.reserved.regions; 1179 + 1180 + /* This reserve the 129 memory_region, and makes it double array. */ 1181 + memblock_reserve(MEMORY_BASE_OFFSET(skip, offset), MEM_SIZE); 1182 + 1183 + /* 1184 + * This is the memory region size used by the doubled reserved.regions, 1185 + * and it has been reserved due to it has been used. The size is used to 1186 + * calculate the total_size that the memblock.reserved have now. 1187 + */ 1188 + new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) * 1189 + sizeof(struct memblock_region)); 1190 + /* 1191 + * The double_array() will find a free memory region as the new 1192 + * reserved.regions, and the used memory region will be reserved, so 1193 + * there will be one more region exist in the reserved memblock. And the 1194 + * one more reserved region's size is new_reserved_regions_size. 1195 + */ 1196 + ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2); 1197 + ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 1198 + new_reserved_regions_size); 1199 + ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 1200 + 1201 + /* 1202 + * The first reserved region is allocated for double array 1203 + * with the size of new_reserved_regions_size and the base to be 1204 + * MEMORY_BASE_OFFSET(0, offset) + SZ_32K - new_reserved_regions_size 1205 + */ 1206 + ASSERT_EQ(memblock.reserved.regions[0].base + memblock.reserved.regions[0].size, 1207 + MEMORY_BASE_OFFSET(0, offset) + SZ_32K); 1208 + ASSERT_EQ(memblock.reserved.regions[0].size, new_reserved_regions_size); 1209 + 1210 + /* 1211 + * Now memblock_double_array() works fine. Let's check after the 1212 + * double_array(), the memblock_reserve() still works as normal. 1213 + */ 1214 + memblock_reserve(r.base, r.size); 1215 + ASSERT_EQ(memblock.reserved.regions[0].base, r.base); 1216 + ASSERT_EQ(memblock.reserved.regions[0].size, r.size); 1217 + 1218 + ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3); 1219 + ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 1220 + new_reserved_regions_size + 1221 + r.size); 1222 + ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 1223 + 1224 + /* 1225 + * The current reserved.regions is occupying a range of memory that 1226 + * allocated from dummy_physical_memory_init(). After free the memory, 1227 + * we must not use it. So restore the origin memory region to make sure 1228 + * the tests can run as normal and not affected by the double array. 1229 + */ 1230 + memblock.reserved.regions = orig_region; 1231 + memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS; 1232 + } 1233 + 1234 + dummy_physical_memory_cleanup(); 1235 + 1236 + test_pass_pop(); 1237 + 1238 + return 0; 1239 + } 1240 + 985 1241 static int memblock_reserve_checks(void) 986 1242 { 987 1243 prefix_reset(); ··· 1253 997 memblock_reserve_between_check(); 1254 998 memblock_reserve_near_max_check(); 1255 999 memblock_reserve_many_check(); 1000 + memblock_reserve_all_locations_check(); 1001 + memblock_reserve_many_may_conflict_check(); 1256 1002 1257 1003 prefix_pop(); 1258 1004 ··· 1553 1295 ASSERT_EQ(rgn->base, 0); 1554 1296 ASSERT_EQ(rgn->size, 0); 1555 1297 1556 - ASSERT_EQ(memblock.memory.cnt, 1); 1298 + ASSERT_EQ(memblock.memory.cnt, 0); 1557 1299 ASSERT_EQ(memblock.memory.total_size, 0); 1558 1300 1559 1301 test_pass_pop(); ··· 1981 1723 ASSERT_EQ(rgn->base, 0); 1982 1724 ASSERT_EQ(rgn->size, 0); 1983 1725 1984 - ASSERT_EQ(memblock.reserved.cnt, 1); 1726 + ASSERT_EQ(memblock.reserved.cnt, 0); 1985 1727 ASSERT_EQ(memblock.reserved.total_size, 0); 1986 1728 1987 1729 test_pass_pop(); ··· 2387 2129 return 0; 2388 2130 } 2389 2131 2132 + static int memblock_overlaps_region_check(void) 2133 + { 2134 + struct region r = { 2135 + .base = SZ_1G, 2136 + .size = SZ_4M 2137 + }; 2138 + 2139 + PREFIX_PUSH(); 2140 + 2141 + reset_memblock_regions(); 2142 + memblock_add(r.base, r.size); 2143 + 2144 + /* Far Away */ 2145 + ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1M, SZ_1M)); 2146 + ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_2G, SZ_1M)); 2147 + 2148 + /* Neighbor */ 2149 + ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_1M, SZ_1M)); 2150 + ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_4M, SZ_1M)); 2151 + 2152 + /* Partial Overlap */ 2153 + ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_1M, SZ_2M)); 2154 + ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_2M, SZ_2M)); 2155 + 2156 + /* Totally Overlap */ 2157 + ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G, SZ_4M)); 2158 + ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_2M, SZ_8M)); 2159 + ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_1M, SZ_1M)); 2160 + 2161 + test_pass_pop(); 2162 + 2163 + return 0; 2164 + } 2165 + 2166 + static int memblock_overlaps_region_checks(void) 2167 + { 2168 + prefix_reset(); 2169 + prefix_push("memblock_overlaps_region"); 2170 + test_print("Running memblock_overlaps_region tests...\n"); 2171 + 2172 + memblock_overlaps_region_check(); 2173 + 2174 + prefix_pop(); 2175 + 2176 + return 0; 2177 + } 2178 + 2390 2179 int memblock_basic_checks(void) 2391 2180 { 2392 2181 memblock_initialization_check(); ··· 2443 2138 memblock_free_checks(); 2444 2139 memblock_bottom_up_checks(); 2445 2140 memblock_trim_memory_checks(); 2141 + memblock_overlaps_region_checks(); 2446 2142 2447 2143 return 0; 2448 2144 }
+4 -4
tools/testing/memblock/tests/common.c
··· 40 40 { 41 41 memset(memblock.memory.regions, 0, 42 42 memblock.memory.cnt * sizeof(struct memblock_region)); 43 - memblock.memory.cnt = 1; 43 + memblock.memory.cnt = 0; 44 44 memblock.memory.max = INIT_MEMBLOCK_REGIONS; 45 45 memblock.memory.total_size = 0; 46 46 47 47 memset(memblock.reserved.regions, 0, 48 48 memblock.reserved.cnt * sizeof(struct memblock_region)); 49 - memblock.reserved.cnt = 1; 49 + memblock.reserved.cnt = 0; 50 50 memblock.reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS; 51 51 memblock.reserved.total_size = 0; 52 52 } ··· 61 61 62 62 static inline void fill_memblock(void) 63 63 { 64 - memset(memory_block.base, 1, MEM_SIZE); 64 + memset(memory_block.base, 1, PHYS_MEM_SIZE); 65 65 } 66 66 67 67 void setup_memblock(void) ··· 103 103 104 104 void dummy_physical_memory_init(void) 105 105 { 106 - memory_block.base = malloc(MEM_SIZE); 106 + memory_block.base = malloc(PHYS_MEM_SIZE); 107 107 assert(memory_block.base); 108 108 fill_memblock(); 109 109 }
+4
tools/testing/memblock/tests/common.h
··· 12 12 #include <../selftests/kselftest.h> 13 13 14 14 #define MEM_SIZE SZ_32K 15 + #define PHYS_MEM_SIZE SZ_16M 15 16 #define NUMA_NODES 8 16 17 17 18 #define INIT_MEMBLOCK_REGIONS 128 ··· 39 38 test_fail(); \ 40 39 assert((_expected) == (_seen)); \ 41 40 } while (0) 41 + 42 + #define ASSERT_TRUE(_seen) ASSERT_EQ(true, _seen) 43 + #define ASSERT_FALSE(_seen) ASSERT_EQ(false, _seen) 42 44 43 45 /** 44 46 * ASSERT_NE():