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

memblock tests: add memblock_reserve_all_locations_check()

Instead of adding 129th memory block at the last position, let's try all
possible position.

Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Link: https://lore.kernel.org/r/20240507075833.6346-2-richard.weiyang@gmail.com
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>

authored by

Wei Yang and committed by
Mike Rapoport (IBM)
3d316519 721f4a65

+107
+107
tools/testing/memblock/tests/basic_api.c
··· 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 + 985 1091 static int memblock_reserve_checks(void) 986 1092 { 987 1093 prefix_reset(); ··· 1103 997 memblock_reserve_between_check(); 1104 998 memblock_reserve_near_max_check(); 1105 999 memblock_reserve_many_check(); 1000 + memblock_reserve_all_locations_check(); 1106 1001 1107 1002 prefix_pop(); 1108 1003