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.

memblock tests: add additional tests for basic api and memblock_alloc

Add tests for memblock_add(), memblock_reserve(), memblock_remove(),
memblock_free(), and memblock_alloc() for the following test scenarios.

memblock_add() and memblock_reserve():
- add/reserve a memory block in the gap between two existing memory
blocks, and check that the blocks are merged into one region
- try to add/reserve memblock regions that extend past PHYS_ADDR_MAX

memblock_remove() and memblock_free():
- remove/free a region when it is the only available region
+ These tests ensure that the first region is overwritten with a
"dummy" region when the last remaining region of that type is
removed or freed.
- remove/free() a region that overlaps with two existing regions of the
relevant type
- try to remove/free memblock regions that extend past PHYS_ADDR_MAX

memblock_alloc():
- try to allocate a region that is larger than the total size of available
memory (memblock.memory)

Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Shaoqin Huang <shaoqin.huang@intel.com>
Signed-off-by: Rebecca Mckeever <remckee0@gmail.com>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Link: https://lore.kernel.org/r/c23c0393c5b9a53fe7f676996913c629495e9727.1661578349.git.remckee0@gmail.com

authored by

Rebecca Mckeever and committed by
Mike Rapoport
21a233f6 fb2e97fe

+543
+44
tools/testing/memblock/tests/alloc_api.c
··· 470 470 } 471 471 472 472 /* 473 + * A test that tries to allocate a region that is larger than the total size of 474 + * available memory (memblock.memory): 475 + * 476 + * +-----------------------------------+ 477 + * | new | 478 + * +-----------------------------------+ 479 + * | | 480 + * | | 481 + * +---------------------------------+ 482 + * 483 + * Expect no allocation to happen. 484 + */ 485 + static int alloc_too_large_generic_check(void) 486 + { 487 + struct memblock_region *rgn = &memblock.reserved.regions[0]; 488 + void *allocated_ptr = NULL; 489 + 490 + PREFIX_PUSH(); 491 + 492 + setup_memblock(); 493 + 494 + allocated_ptr = memblock_alloc(MEM_SIZE + SZ_2, SMP_CACHE_BYTES); 495 + 496 + ASSERT_EQ(allocated_ptr, NULL); 497 + ASSERT_EQ(rgn->size, 0); 498 + ASSERT_EQ(rgn->base, 0); 499 + ASSERT_EQ(memblock.reserved.total_size, 0); 500 + 501 + test_pass_pop(); 502 + 503 + return 0; 504 + } 505 + 506 + /* 473 507 * A simple test that tries to allocate a small memory region. 474 508 * Expect to allocate an aligned region at the beginning of the available 475 509 * memory. ··· 847 813 return 0; 848 814 } 849 815 816 + static int alloc_too_large_check(void) 817 + { 818 + test_print("\tRunning %s...\n", __func__); 819 + run_top_down(alloc_too_large_generic_check); 820 + run_bottom_up(alloc_too_large_generic_check); 821 + 822 + return 0; 823 + } 824 + 850 825 int memblock_alloc_checks(void) 851 826 { 852 827 const char *func_testing = "memblock_alloc"; ··· 878 835 alloc_no_space_check(); 879 836 alloc_limited_space_check(); 880 837 alloc_no_memory_check(); 838 + alloc_too_large_check(); 881 839 882 840 dummy_physical_memory_cleanup(); 883 841
+499
tools/testing/memblock/tests/basic_api.c
··· 326 326 return 0; 327 327 } 328 328 329 + /* 330 + * A test that tries to add two memory blocks that don't overlap with one 331 + * another and then add a third memory block in the space between the first two: 332 + * 333 + * | +--------+--------+--------+ | 334 + * | | r1 | r3 | r2 | | 335 + * +--------+--------+--------+--------+--+ 336 + * 337 + * Expect to merge the three entries into one region that starts at r1.base 338 + * and has size of r1.size + r2.size + r3.size. The region counter and total 339 + * size of the available memory are updated. 340 + */ 341 + static int memblock_add_between_check(void) 342 + { 343 + struct memblock_region *rgn; 344 + phys_addr_t total_size; 345 + 346 + rgn = &memblock.memory.regions[0]; 347 + 348 + struct region r1 = { 349 + .base = SZ_1G, 350 + .size = SZ_8K 351 + }; 352 + struct region r2 = { 353 + .base = SZ_1G + SZ_16K, 354 + .size = SZ_8K 355 + }; 356 + struct region r3 = { 357 + .base = SZ_1G + SZ_8K, 358 + .size = SZ_8K 359 + }; 360 + 361 + PREFIX_PUSH(); 362 + 363 + total_size = r1.size + r2.size + r3.size; 364 + 365 + reset_memblock_regions(); 366 + memblock_add(r1.base, r1.size); 367 + memblock_add(r2.base, r2.size); 368 + memblock_add(r3.base, r3.size); 369 + 370 + ASSERT_EQ(rgn->base, r1.base); 371 + ASSERT_EQ(rgn->size, total_size); 372 + 373 + ASSERT_EQ(memblock.memory.cnt, 1); 374 + ASSERT_EQ(memblock.memory.total_size, total_size); 375 + 376 + test_pass_pop(); 377 + 378 + return 0; 379 + } 380 + 381 + /* 382 + * A simple test that tries to add a memory block r when r extends past 383 + * PHYS_ADDR_MAX: 384 + * 385 + * +--------+ 386 + * | r | 387 + * +--------+ 388 + * | +----+ 389 + * | | rgn| 390 + * +----------------------------+----+ 391 + * 392 + * Expect to add a memory block of size PHYS_ADDR_MAX - r.base. Expect the 393 + * total size of available memory and the counter to be updated. 394 + */ 395 + static int memblock_add_near_max_check(void) 396 + { 397 + struct memblock_region *rgn; 398 + phys_addr_t total_size; 399 + 400 + rgn = &memblock.memory.regions[0]; 401 + 402 + struct region r = { 403 + .base = PHYS_ADDR_MAX - SZ_1M, 404 + .size = SZ_2M 405 + }; 406 + 407 + PREFIX_PUSH(); 408 + 409 + total_size = PHYS_ADDR_MAX - r.base; 410 + 411 + reset_memblock_regions(); 412 + memblock_add(r.base, r.size); 413 + 414 + ASSERT_EQ(rgn->base, r.base); 415 + ASSERT_EQ(rgn->size, total_size); 416 + 417 + ASSERT_EQ(memblock.memory.cnt, 1); 418 + ASSERT_EQ(memblock.memory.total_size, total_size); 419 + 420 + test_pass_pop(); 421 + 422 + return 0; 423 + } 424 + 329 425 static int memblock_add_checks(void) 330 426 { 331 427 prefix_reset(); ··· 435 339 memblock_add_overlap_bottom_check(); 436 340 memblock_add_within_check(); 437 341 memblock_add_twice_check(); 342 + memblock_add_between_check(); 343 + memblock_add_near_max_check(); 438 344 439 345 prefix_pop(); 440 346 ··· 702 604 return 0; 703 605 } 704 606 607 + /* 608 + * A test that tries to mark two memory blocks that don't overlap as reserved 609 + * and then reserve a third memory block in the space between the first two: 610 + * 611 + * | +--------+--------+--------+ | 612 + * | | r1 | r3 | r2 | | 613 + * +--------+--------+--------+--------+--+ 614 + * 615 + * Expect to merge the three entries into one reserved region that starts at 616 + * r1.base and has size of r1.size + r2.size + r3.size. The region counter and 617 + * total for memblock.reserved are updated. 618 + */ 619 + static int memblock_reserve_between_check(void) 620 + { 621 + struct memblock_region *rgn; 622 + phys_addr_t total_size; 623 + 624 + rgn = &memblock.reserved.regions[0]; 625 + 626 + struct region r1 = { 627 + .base = SZ_1G, 628 + .size = SZ_8K 629 + }; 630 + struct region r2 = { 631 + .base = SZ_1G + SZ_16K, 632 + .size = SZ_8K 633 + }; 634 + struct region r3 = { 635 + .base = SZ_1G + SZ_8K, 636 + .size = SZ_8K 637 + }; 638 + 639 + PREFIX_PUSH(); 640 + 641 + total_size = r1.size + r2.size + r3.size; 642 + 643 + reset_memblock_regions(); 644 + memblock_reserve(r1.base, r1.size); 645 + memblock_reserve(r2.base, r2.size); 646 + memblock_reserve(r3.base, r3.size); 647 + 648 + ASSERT_EQ(rgn->base, r1.base); 649 + ASSERT_EQ(rgn->size, total_size); 650 + 651 + ASSERT_EQ(memblock.reserved.cnt, 1); 652 + ASSERT_EQ(memblock.reserved.total_size, total_size); 653 + 654 + test_pass_pop(); 655 + 656 + return 0; 657 + } 658 + 659 + /* 660 + * A simple test that tries to reserve a memory block r when r extends past 661 + * PHYS_ADDR_MAX: 662 + * 663 + * +--------+ 664 + * | r | 665 + * +--------+ 666 + * | +----+ 667 + * | | rgn| 668 + * +----------------------------+----+ 669 + * 670 + * Expect to reserve a memory block of size PHYS_ADDR_MAX - r.base. Expect the 671 + * total size of reserved memory and the counter to be updated. 672 + */ 673 + static int memblock_reserve_near_max_check(void) 674 + { 675 + struct memblock_region *rgn; 676 + phys_addr_t total_size; 677 + 678 + rgn = &memblock.reserved.regions[0]; 679 + 680 + struct region r = { 681 + .base = PHYS_ADDR_MAX - SZ_1M, 682 + .size = SZ_2M 683 + }; 684 + 685 + PREFIX_PUSH(); 686 + 687 + total_size = PHYS_ADDR_MAX - r.base; 688 + 689 + reset_memblock_regions(); 690 + memblock_reserve(r.base, r.size); 691 + 692 + ASSERT_EQ(rgn->base, r.base); 693 + ASSERT_EQ(rgn->size, total_size); 694 + 695 + ASSERT_EQ(memblock.reserved.cnt, 1); 696 + ASSERT_EQ(memblock.reserved.total_size, total_size); 697 + 698 + test_pass_pop(); 699 + 700 + return 0; 701 + } 702 + 705 703 static int memblock_reserve_checks(void) 706 704 { 707 705 prefix_reset(); ··· 810 616 memblock_reserve_overlap_bottom_check(); 811 617 memblock_reserve_within_check(); 812 618 memblock_reserve_twice_check(); 619 + memblock_reserve_between_check(); 620 + memblock_reserve_near_max_check(); 813 621 814 622 prefix_pop(); 815 623 ··· 1083 887 return 0; 1084 888 } 1085 889 890 + /* 891 + * A simple test that tries to remove a region r1 from the array of 892 + * available memory regions when r1 is the only available region. 893 + * Expect to add a memory block r1 and then remove r1 so that a dummy 894 + * region is added. The region counter stays the same, and the total size 895 + * is updated. 896 + */ 897 + static int memblock_remove_only_region_check(void) 898 + { 899 + struct memblock_region *rgn; 900 + 901 + rgn = &memblock.memory.regions[0]; 902 + 903 + struct region r1 = { 904 + .base = SZ_2K, 905 + .size = SZ_4K 906 + }; 907 + 908 + PREFIX_PUSH(); 909 + 910 + reset_memblock_regions(); 911 + memblock_add(r1.base, r1.size); 912 + memblock_remove(r1.base, r1.size); 913 + 914 + ASSERT_EQ(rgn->base, 0); 915 + ASSERT_EQ(rgn->size, 0); 916 + 917 + ASSERT_EQ(memblock.memory.cnt, 1); 918 + ASSERT_EQ(memblock.memory.total_size, 0); 919 + 920 + test_pass_pop(); 921 + 922 + return 0; 923 + } 924 + 925 + /* 926 + * A simple test that tries remove a region r2 from the array of available 927 + * memory regions when r2 extends past PHYS_ADDR_MAX: 928 + * 929 + * +--------+ 930 + * | r2 | 931 + * +--------+ 932 + * | +---+....+ 933 + * | |rgn| | 934 + * +------------------------+---+----+ 935 + * 936 + * Expect that only the portion between PHYS_ADDR_MAX and r2.base is removed. 937 + * Expect the total size of available memory to be updated and the counter to 938 + * not be updated. 939 + */ 940 + static int memblock_remove_near_max_check(void) 941 + { 942 + struct memblock_region *rgn; 943 + phys_addr_t total_size; 944 + 945 + rgn = &memblock.memory.regions[0]; 946 + 947 + struct region r1 = { 948 + .base = PHYS_ADDR_MAX - SZ_2M, 949 + .size = SZ_2M 950 + }; 951 + 952 + struct region r2 = { 953 + .base = PHYS_ADDR_MAX - SZ_1M, 954 + .size = SZ_2M 955 + }; 956 + 957 + PREFIX_PUSH(); 958 + 959 + total_size = r1.size - (PHYS_ADDR_MAX - r2.base); 960 + 961 + reset_memblock_regions(); 962 + memblock_add(r1.base, r1.size); 963 + memblock_remove(r2.base, r2.size); 964 + 965 + ASSERT_EQ(rgn->base, r1.base); 966 + ASSERT_EQ(rgn->size, total_size); 967 + 968 + ASSERT_EQ(memblock.memory.cnt, 1); 969 + ASSERT_EQ(memblock.memory.total_size, total_size); 970 + 971 + test_pass_pop(); 972 + 973 + return 0; 974 + } 975 + 976 + /* 977 + * A test that tries to remove a region r3 that overlaps with two existing 978 + * regions r1 and r2: 979 + * 980 + * +----------------+ 981 + * | r3 | 982 + * +----------------+ 983 + * | +----+..... ........+--------+ 984 + * | | |r1 : : |r2 | | 985 + * +----+----+----+---+-------+--------+-----+ 986 + * 987 + * Expect that only the intersections of r1 with r3 and r2 with r3 are removed 988 + * from the available memory pool. Expect the total size of available memory to 989 + * be updated and the counter to not be updated. 990 + */ 991 + static int memblock_remove_overlap_two_check(void) 992 + { 993 + struct memblock_region *rgn1, *rgn2; 994 + phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size; 995 + 996 + rgn1 = &memblock.memory.regions[0]; 997 + rgn2 = &memblock.memory.regions[1]; 998 + 999 + struct region r1 = { 1000 + .base = SZ_16M, 1001 + .size = SZ_32M 1002 + }; 1003 + struct region r2 = { 1004 + .base = SZ_64M, 1005 + .size = SZ_64M 1006 + }; 1007 + struct region r3 = { 1008 + .base = SZ_32M, 1009 + .size = SZ_64M 1010 + }; 1011 + 1012 + PREFIX_PUSH(); 1013 + 1014 + r2_end = r2.base + r2.size; 1015 + r3_end = r3.base + r3.size; 1016 + new_r1_size = r3.base - r1.base; 1017 + new_r2_size = r2_end - r3_end; 1018 + total_size = new_r1_size + new_r2_size; 1019 + 1020 + reset_memblock_regions(); 1021 + memblock_add(r1.base, r1.size); 1022 + memblock_add(r2.base, r2.size); 1023 + memblock_remove(r3.base, r3.size); 1024 + 1025 + ASSERT_EQ(rgn1->base, r1.base); 1026 + ASSERT_EQ(rgn1->size, new_r1_size); 1027 + 1028 + ASSERT_EQ(rgn2->base, r3_end); 1029 + ASSERT_EQ(rgn2->size, new_r2_size); 1030 + 1031 + ASSERT_EQ(memblock.memory.cnt, 2); 1032 + ASSERT_EQ(memblock.memory.total_size, total_size); 1033 + 1034 + test_pass_pop(); 1035 + 1036 + return 0; 1037 + } 1038 + 1086 1039 static int memblock_remove_checks(void) 1087 1040 { 1088 1041 prefix_reset(); ··· 1243 898 memblock_remove_overlap_top_check(); 1244 899 memblock_remove_overlap_bottom_check(); 1245 900 memblock_remove_within_check(); 901 + memblock_remove_only_region_check(); 902 + memblock_remove_near_max_check(); 903 + memblock_remove_overlap_two_check(); 1246 904 1247 905 prefix_pop(); 1248 906 ··· 1511 1163 return 0; 1512 1164 } 1513 1165 1166 + /* 1167 + * A simple test that tries to free a memory block r1 that was marked 1168 + * earlier as reserved when r1 is the only available region. 1169 + * Expect to reserve a memory block r1 and then free r1 so that r1 is 1170 + * overwritten with a dummy region. The region counter stays the same, 1171 + * and the total size is updated. 1172 + */ 1173 + static int memblock_free_only_region_check(void) 1174 + { 1175 + struct memblock_region *rgn; 1176 + 1177 + rgn = &memblock.reserved.regions[0]; 1178 + 1179 + struct region r1 = { 1180 + .base = SZ_2K, 1181 + .size = SZ_4K 1182 + }; 1183 + 1184 + PREFIX_PUSH(); 1185 + 1186 + reset_memblock_regions(); 1187 + memblock_reserve(r1.base, r1.size); 1188 + memblock_free((void *)r1.base, r1.size); 1189 + 1190 + ASSERT_EQ(rgn->base, 0); 1191 + ASSERT_EQ(rgn->size, 0); 1192 + 1193 + ASSERT_EQ(memblock.reserved.cnt, 1); 1194 + ASSERT_EQ(memblock.reserved.total_size, 0); 1195 + 1196 + test_pass_pop(); 1197 + 1198 + return 0; 1199 + } 1200 + 1201 + /* 1202 + * A simple test that tries free a region r2 when r2 extends past PHYS_ADDR_MAX: 1203 + * 1204 + * +--------+ 1205 + * | r2 | 1206 + * +--------+ 1207 + * | +---+....+ 1208 + * | |rgn| | 1209 + * +------------------------+---+----+ 1210 + * 1211 + * Expect that only the portion between PHYS_ADDR_MAX and r2.base is freed. 1212 + * Expect the total size of reserved memory to be updated and the counter to 1213 + * not be updated. 1214 + */ 1215 + static int memblock_free_near_max_check(void) 1216 + { 1217 + struct memblock_region *rgn; 1218 + phys_addr_t total_size; 1219 + 1220 + rgn = &memblock.reserved.regions[0]; 1221 + 1222 + struct region r1 = { 1223 + .base = PHYS_ADDR_MAX - SZ_2M, 1224 + .size = SZ_2M 1225 + }; 1226 + 1227 + struct region r2 = { 1228 + .base = PHYS_ADDR_MAX - SZ_1M, 1229 + .size = SZ_2M 1230 + }; 1231 + 1232 + PREFIX_PUSH(); 1233 + 1234 + total_size = r1.size - (PHYS_ADDR_MAX - r2.base); 1235 + 1236 + reset_memblock_regions(); 1237 + memblock_reserve(r1.base, r1.size); 1238 + memblock_free((void *)r2.base, r2.size); 1239 + 1240 + ASSERT_EQ(rgn->base, r1.base); 1241 + ASSERT_EQ(rgn->size, total_size); 1242 + 1243 + ASSERT_EQ(memblock.reserved.cnt, 1); 1244 + ASSERT_EQ(memblock.reserved.total_size, total_size); 1245 + 1246 + test_pass_pop(); 1247 + 1248 + return 0; 1249 + } 1250 + 1251 + /* 1252 + * A test that tries to free a reserved region r3 that overlaps with two 1253 + * existing reserved regions r1 and r2: 1254 + * 1255 + * +----------------+ 1256 + * | r3 | 1257 + * +----------------+ 1258 + * | +----+..... ........+--------+ 1259 + * | | |r1 : : |r2 | | 1260 + * +----+----+----+---+-------+--------+-----+ 1261 + * 1262 + * Expect that only the intersections of r1 with r3 and r2 with r3 are freed 1263 + * from the collection of reserved memory. Expect the total size of reserved 1264 + * memory to be updated and the counter to not be updated. 1265 + */ 1266 + static int memblock_free_overlap_two_check(void) 1267 + { 1268 + struct memblock_region *rgn1, *rgn2; 1269 + phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size; 1270 + 1271 + rgn1 = &memblock.reserved.regions[0]; 1272 + rgn2 = &memblock.reserved.regions[1]; 1273 + 1274 + struct region r1 = { 1275 + .base = SZ_16M, 1276 + .size = SZ_32M 1277 + }; 1278 + struct region r2 = { 1279 + .base = SZ_64M, 1280 + .size = SZ_64M 1281 + }; 1282 + struct region r3 = { 1283 + .base = SZ_32M, 1284 + .size = SZ_64M 1285 + }; 1286 + 1287 + PREFIX_PUSH(); 1288 + 1289 + r2_end = r2.base + r2.size; 1290 + r3_end = r3.base + r3.size; 1291 + new_r1_size = r3.base - r1.base; 1292 + new_r2_size = r2_end - r3_end; 1293 + total_size = new_r1_size + new_r2_size; 1294 + 1295 + reset_memblock_regions(); 1296 + memblock_reserve(r1.base, r1.size); 1297 + memblock_reserve(r2.base, r2.size); 1298 + memblock_free((void *)r3.base, r3.size); 1299 + 1300 + ASSERT_EQ(rgn1->base, r1.base); 1301 + ASSERT_EQ(rgn1->size, new_r1_size); 1302 + 1303 + ASSERT_EQ(rgn2->base, r3_end); 1304 + ASSERT_EQ(rgn2->size, new_r2_size); 1305 + 1306 + ASSERT_EQ(memblock.reserved.cnt, 2); 1307 + ASSERT_EQ(memblock.reserved.total_size, total_size); 1308 + 1309 + test_pass_pop(); 1310 + 1311 + return 0; 1312 + } 1313 + 1514 1314 static int memblock_free_checks(void) 1515 1315 { 1516 1316 prefix_reset(); ··· 1670 1174 memblock_free_overlap_top_check(); 1671 1175 memblock_free_overlap_bottom_check(); 1672 1176 memblock_free_within_check(); 1177 + memblock_free_only_region_check(); 1178 + memblock_free_near_max_check(); 1179 + memblock_free_overlap_two_check(); 1673 1180 1674 1181 prefix_pop(); 1675 1182