1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #include <string.h> 3 #include <linux/memblock.h> 4 #include <linux/sizes.h> 5 #include "basic_api.h" 6 7 #define EXPECTED_MEMBLOCK_REGIONS 128 8 9 static int memblock_initialization_check(void) 10 { 11 reset_memblock(); 12 13 assert(memblock.memory.regions); 14 assert(memblock.memory.cnt == 1); 15 assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS); 16 assert(strcmp(memblock.memory.name, "memory") == 0); 17 18 assert(memblock.reserved.regions); 19 assert(memblock.reserved.cnt == 1); 20 assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS); 21 assert(strcmp(memblock.reserved.name, "reserved") == 0); 22 23 assert(!memblock.bottom_up); 24 assert(memblock.current_limit == MEMBLOCK_ALLOC_ANYWHERE); 25 26 return 0; 27 } 28 29 /* 30 * A simple test that adds a memory block of a specified base address 31 * and size to the collection of available memory regions (memblock.memory). 32 * It checks if a new entry was created and if region counter and total memory 33 * were correctly updated. 34 */ 35 static int memblock_add_simple_check(void) 36 { 37 struct memblock_region *rgn; 38 39 rgn = &memblock.memory.regions[0]; 40 41 struct region r = { 42 .base = SZ_1G, 43 .size = SZ_4M 44 }; 45 46 reset_memblock(); 47 memblock_add(r.base, r.size); 48 49 assert(rgn->base == r.base); 50 assert(rgn->size == r.size); 51 52 assert(memblock.memory.cnt == 1); 53 assert(memblock.memory.total_size == r.size); 54 55 return 0; 56 } 57 58 /* 59 * A test that tries to add two memory blocks that don't overlap with one 60 * another. It checks if two correctly initialized entries were added to the 61 * collection of available memory regions (memblock.memory) and if this 62 * change was reflected in memblock.memory's total size and region counter. 63 */ 64 static int memblock_add_disjoint_check(void) 65 { 66 struct memblock_region *rgn1, *rgn2; 67 68 rgn1 = &memblock.memory.regions[0]; 69 rgn2 = &memblock.memory.regions[1]; 70 71 struct region r1 = { 72 .base = SZ_1G, 73 .size = SZ_8K 74 }; 75 struct region r2 = { 76 .base = SZ_1G + SZ_16K, 77 .size = SZ_8K 78 }; 79 80 reset_memblock(); 81 memblock_add(r1.base, r1.size); 82 memblock_add(r2.base, r2.size); 83 84 assert(rgn1->base == r1.base); 85 assert(rgn1->size == r1.size); 86 87 assert(rgn2->base == r2.base); 88 assert(rgn2->size == r2.size); 89 90 assert(memblock.memory.cnt == 2); 91 assert(memblock.memory.total_size == r1.size + r2.size); 92 93 return 0; 94 } 95 96 /* 97 * A test that tries to add two memory blocks, where the second one overlaps 98 * with the beginning of the first entry (that is r1.base < r2.base + r2.size). 99 * After this, it checks if two entries are merged into one region that starts 100 * at r2.base and has size of two regions minus their intersection. It also 101 * verifies the reported total size of the available memory and region counter. 102 */ 103 static int memblock_add_overlap_top_check(void) 104 { 105 struct memblock_region *rgn; 106 phys_addr_t total_size; 107 108 rgn = &memblock.memory.regions[0]; 109 110 struct region r1 = { 111 .base = SZ_512M, 112 .size = SZ_1G 113 }; 114 struct region r2 = { 115 .base = SZ_256M, 116 .size = SZ_512M 117 }; 118 119 total_size = (r1.base - r2.base) + r1.size; 120 121 reset_memblock(); 122 memblock_add(r1.base, r1.size); 123 memblock_add(r2.base, r2.size); 124 125 assert(rgn->base == r2.base); 126 assert(rgn->size == total_size); 127 128 assert(memblock.memory.cnt == 1); 129 assert(memblock.memory.total_size == total_size); 130 131 return 0; 132 } 133 134 /* 135 * A test that tries to add two memory blocks, where the second one overlaps 136 * with the end of the first entry (that is r2.base < r1.base + r1.size). 137 * After this, it checks if two entries are merged into one region that starts 138 * at r1.base and has size of two regions minus their intersection. It verifies 139 * that memblock can still see only one entry and has a correct total size of 140 * the available memory. 141 */ 142 static int memblock_add_overlap_bottom_check(void) 143 { 144 struct memblock_region *rgn; 145 phys_addr_t total_size; 146 147 rgn = &memblock.memory.regions[0]; 148 149 struct region r1 = { 150 .base = SZ_128M, 151 .size = SZ_512M 152 }; 153 struct region r2 = { 154 .base = SZ_256M, 155 .size = SZ_1G 156 }; 157 158 total_size = (r2.base - r1.base) + r2.size; 159 160 reset_memblock(); 161 memblock_add(r1.base, r1.size); 162 memblock_add(r2.base, r2.size); 163 164 assert(rgn->base == r1.base); 165 assert(rgn->size == total_size); 166 167 assert(memblock.memory.cnt == 1); 168 assert(memblock.memory.total_size == total_size); 169 170 return 0; 171 } 172 173 /* 174 * A test that tries to add two memory blocks, where the second one is 175 * within the range of the first entry (that is r1.base < r2.base && 176 * r2.base + r2.size < r1.base + r1.size). It checks if two entries are merged 177 * into one region that stays the same. The counter and total size of available 178 * memory are expected to not be updated. 179 */ 180 static int memblock_add_within_check(void) 181 { 182 struct memblock_region *rgn; 183 184 rgn = &memblock.memory.regions[0]; 185 186 struct region r1 = { 187 .base = SZ_8M, 188 .size = SZ_32M 189 }; 190 struct region r2 = { 191 .base = SZ_16M, 192 .size = SZ_1M 193 }; 194 195 reset_memblock(); 196 memblock_add(r1.base, r1.size); 197 memblock_add(r2.base, r2.size); 198 199 assert(rgn->base == r1.base); 200 assert(rgn->size == r1.size); 201 202 assert(memblock.memory.cnt == 1); 203 assert(memblock.memory.total_size == r1.size); 204 205 return 0; 206 } 207 208 /* 209 * A simple test that tries to add the same memory block twice. The counter 210 * and total size of available memory are expected to not be updated. 211 */ 212 static int memblock_add_twice_check(void) 213 { 214 struct region r = { 215 .base = SZ_16K, 216 .size = SZ_2M 217 }; 218 219 reset_memblock(); 220 221 memblock_add(r.base, r.size); 222 memblock_add(r.base, r.size); 223 224 assert(memblock.memory.cnt == 1); 225 assert(memblock.memory.total_size == r.size); 226 227 return 0; 228 } 229 230 static int memblock_add_checks(void) 231 { 232 memblock_add_simple_check(); 233 memblock_add_disjoint_check(); 234 memblock_add_overlap_top_check(); 235 memblock_add_overlap_bottom_check(); 236 memblock_add_within_check(); 237 memblock_add_twice_check(); 238 239 return 0; 240 } 241 242 /* 243 * A simple test that marks a memory block of a specified base address 244 * and size as reserved and to the collection of reserved memory regions 245 * (memblock.reserved). It checks if a new entry was created and if region 246 * counter and total memory size were correctly updated. 247 */ 248 static int memblock_reserve_simple_check(void) 249 { 250 struct memblock_region *rgn; 251 252 rgn = &memblock.reserved.regions[0]; 253 254 struct region r = { 255 .base = SZ_2G, 256 .size = SZ_128M 257 }; 258 259 reset_memblock(); 260 memblock_reserve(r.base, r.size); 261 262 assert(rgn->base == r.base); 263 assert(rgn->size == r.size); 264 265 return 0; 266 } 267 268 /* 269 * A test that tries to mark two memory blocks that don't overlap as reserved 270 * and checks if two entries were correctly added to the collection of reserved 271 * memory regions (memblock.reserved) and if this change was reflected in 272 * memblock.reserved's total size and region counter. 273 */ 274 static int memblock_reserve_disjoint_check(void) 275 { 276 struct memblock_region *rgn1, *rgn2; 277 278 rgn1 = &memblock.reserved.regions[0]; 279 rgn2 = &memblock.reserved.regions[1]; 280 281 struct region r1 = { 282 .base = SZ_256M, 283 .size = SZ_16M 284 }; 285 struct region r2 = { 286 .base = SZ_512M, 287 .size = SZ_512M 288 }; 289 290 reset_memblock(); 291 memblock_reserve(r1.base, r1.size); 292 memblock_reserve(r2.base, r2.size); 293 294 assert(rgn1->base == r1.base); 295 assert(rgn1->size == r1.size); 296 297 assert(rgn2->base == r2.base); 298 assert(rgn2->size == r2.size); 299 300 assert(memblock.reserved.cnt == 2); 301 assert(memblock.reserved.total_size == r1.size + r2.size); 302 303 return 0; 304 } 305 306 /* 307 * A test that tries to mark two memory blocks as reserved, where the 308 * second one overlaps with the beginning of the first (that is 309 * r1.base < r2.base + r2.size). 310 * It checks if two entries are merged into one region that starts at r2.base 311 * and has size of two regions minus their intersection. The test also verifies 312 * that memblock can still see only one entry and has a correct total size of 313 * the reserved memory. 314 */ 315 static int memblock_reserve_overlap_top_check(void) 316 { 317 struct memblock_region *rgn; 318 phys_addr_t total_size; 319 320 rgn = &memblock.reserved.regions[0]; 321 322 struct region r1 = { 323 .base = SZ_1G, 324 .size = SZ_1G 325 }; 326 struct region r2 = { 327 .base = SZ_128M, 328 .size = SZ_1G 329 }; 330 331 total_size = (r1.base - r2.base) + r1.size; 332 333 reset_memblock(); 334 memblock_reserve(r1.base, r1.size); 335 memblock_reserve(r2.base, r2.size); 336 337 assert(rgn->base == r2.base); 338 assert(rgn->size == total_size); 339 340 assert(memblock.reserved.cnt == 1); 341 assert(memblock.reserved.total_size == total_size); 342 343 return 0; 344 } 345 346 /* 347 * A test that tries to mark two memory blocks as reserved, where the 348 * second one overlaps with the end of the first entry (that is 349 * r2.base < r1.base + r1.size). 350 * It checks if two entries are merged into one region that starts at r1.base 351 * and has size of two regions minus their intersection. It verifies that 352 * memblock can still see only one entry and has a correct total size of the 353 * reserved memory. 354 */ 355 static int memblock_reserve_overlap_bottom_check(void) 356 { 357 struct memblock_region *rgn; 358 phys_addr_t total_size; 359 360 rgn = &memblock.reserved.regions[0]; 361 362 struct region r1 = { 363 .base = SZ_2K, 364 .size = SZ_128K 365 }; 366 struct region r2 = { 367 .base = SZ_128K, 368 .size = SZ_128K 369 }; 370 371 total_size = (r2.base - r1.base) + r2.size; 372 373 reset_memblock(); 374 memblock_reserve(r1.base, r1.size); 375 memblock_reserve(r2.base, r2.size); 376 377 assert(rgn->base == r1.base); 378 assert(rgn->size == total_size); 379 380 assert(memblock.reserved.cnt == 1); 381 assert(memblock.reserved.total_size == total_size); 382 383 return 0; 384 } 385 386 /* 387 * A test that tries to mark two memory blocks as reserved, where the second 388 * one is within the range of the first entry (that is 389 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)). 390 * It checks if two entries are merged into one region that stays the 391 * same. The counter and total size of available memory are expected to not be 392 * updated. 393 */ 394 static int memblock_reserve_within_check(void) 395 { 396 struct memblock_region *rgn; 397 398 rgn = &memblock.reserved.regions[0]; 399 400 struct region r1 = { 401 .base = SZ_1M, 402 .size = SZ_8M 403 }; 404 struct region r2 = { 405 .base = SZ_2M, 406 .size = SZ_64K 407 }; 408 409 reset_memblock(); 410 memblock_reserve(r1.base, r1.size); 411 memblock_reserve(r2.base, r2.size); 412 413 assert(rgn->base == r1.base); 414 assert(rgn->size == r1.size); 415 416 assert(memblock.reserved.cnt == 1); 417 assert(memblock.reserved.total_size == r1.size); 418 419 return 0; 420 } 421 422 /* 423 * A simple test that tries to reserve the same memory block twice. 424 * The region counter and total size of reserved memory are expected to not 425 * be updated. 426 */ 427 static int memblock_reserve_twice_check(void) 428 { 429 struct region r = { 430 .base = SZ_16K, 431 .size = SZ_2M 432 }; 433 434 reset_memblock(); 435 436 memblock_reserve(r.base, r.size); 437 memblock_reserve(r.base, r.size); 438 439 assert(memblock.reserved.cnt == 1); 440 assert(memblock.reserved.total_size == r.size); 441 442 return 0; 443 } 444 445 static int memblock_reserve_checks(void) 446 { 447 memblock_reserve_simple_check(); 448 memblock_reserve_disjoint_check(); 449 memblock_reserve_overlap_top_check(); 450 memblock_reserve_overlap_bottom_check(); 451 memblock_reserve_within_check(); 452 memblock_reserve_twice_check(); 453 454 return 0; 455 } 456 457 int memblock_basic_checks(void) 458 { 459 memblock_initialization_check(); 460 memblock_add_checks(); 461 memblock_reserve_checks(); 462 463 return 0; 464 } 465