1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Test cases for bitmap API. 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <linux/bitmap.h> 9 #include <linux/init.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/printk.h> 13 #include <linux/slab.h> 14 #include <linux/string.h> 15 #include <linux/uaccess.h> 16 17 #include "../tools/testing/selftests/kselftest_module.h" 18 19 static unsigned total_tests __initdata; 20 static unsigned failed_tests __initdata; 21 22 static char pbl_buffer[PAGE_SIZE] __initdata; 23 24 static const unsigned long exp1[] __initconst = { 25 BITMAP_FROM_U64(1), 26 BITMAP_FROM_U64(2), 27 BITMAP_FROM_U64(0x0000ffff), 28 BITMAP_FROM_U64(0xffff0000), 29 BITMAP_FROM_U64(0x55555555), 30 BITMAP_FROM_U64(0xaaaaaaaa), 31 BITMAP_FROM_U64(0x11111111), 32 BITMAP_FROM_U64(0x22222222), 33 BITMAP_FROM_U64(0xffffffff), 34 BITMAP_FROM_U64(0xfffffffe), 35 BITMAP_FROM_U64(0x3333333311111111ULL), 36 BITMAP_FROM_U64(0xffffffff77777777ULL), 37 BITMAP_FROM_U64(0), 38 }; 39 40 static const unsigned long exp2[] __initconst = { 41 BITMAP_FROM_U64(0x3333333311111111ULL), 42 BITMAP_FROM_U64(0xffffffff77777777ULL), 43 }; 44 45 /* Fibonacci sequence */ 46 static const unsigned long exp2_to_exp3_mask[] __initconst = { 47 BITMAP_FROM_U64(0x008000020020212eULL), 48 }; 49 /* exp3_0_1 = (exp2[0] & ~exp2_to_exp3_mask) | (exp2[1] & exp2_to_exp3_mask) */ 50 static const unsigned long exp3_0_1[] __initconst = { 51 BITMAP_FROM_U64(0x33b3333311313137ULL), 52 }; 53 /* exp3_1_0 = (exp2[1] & ~exp2_to_exp3_mask) | (exp2[0] & exp2_to_exp3_mask) */ 54 static const unsigned long exp3_1_0[] __initconst = { 55 BITMAP_FROM_U64(0xff7fffff77575751ULL), 56 }; 57 58 static bool __init 59 __check_eq_uint(const char *srcfile, unsigned int line, 60 const unsigned int exp_uint, unsigned int x) 61 { 62 if (exp_uint != x) { 63 pr_err("[%s:%u] expected %u, got %u\n", 64 srcfile, line, exp_uint, x); 65 return false; 66 } 67 return true; 68 } 69 70 71 static bool __init 72 __check_eq_bitmap(const char *srcfile, unsigned int line, 73 const unsigned long *exp_bmap, const unsigned long *bmap, 74 unsigned int nbits) 75 { 76 if (!bitmap_equal(exp_bmap, bmap, nbits)) { 77 pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n", 78 srcfile, line, 79 nbits, exp_bmap, nbits, bmap); 80 return false; 81 } 82 return true; 83 } 84 85 static bool __init 86 __check_eq_pbl(const char *srcfile, unsigned int line, 87 const char *expected_pbl, 88 const unsigned long *bitmap, unsigned int nbits) 89 { 90 snprintf(pbl_buffer, sizeof(pbl_buffer), "%*pbl", nbits, bitmap); 91 if (strcmp(expected_pbl, pbl_buffer)) { 92 pr_warn("[%s:%u] expected \"%s\", got \"%s\"\n", 93 srcfile, line, 94 expected_pbl, pbl_buffer); 95 return false; 96 } 97 return true; 98 } 99 100 static bool __init 101 __check_eq_u32_array(const char *srcfile, unsigned int line, 102 const u32 *exp_arr, unsigned int exp_len, 103 const u32 *arr, unsigned int len) __used; 104 static bool __init 105 __check_eq_u32_array(const char *srcfile, unsigned int line, 106 const u32 *exp_arr, unsigned int exp_len, 107 const u32 *arr, unsigned int len) 108 { 109 if (exp_len != len) { 110 pr_warn("[%s:%u] array length differ: expected %u, got %u\n", 111 srcfile, line, 112 exp_len, len); 113 return false; 114 } 115 116 if (memcmp(exp_arr, arr, len*sizeof(*arr))) { 117 pr_warn("[%s:%u] array contents differ\n", srcfile, line); 118 print_hex_dump(KERN_WARNING, " exp: ", DUMP_PREFIX_OFFSET, 119 32, 4, exp_arr, exp_len*sizeof(*exp_arr), false); 120 print_hex_dump(KERN_WARNING, " got: ", DUMP_PREFIX_OFFSET, 121 32, 4, arr, len*sizeof(*arr), false); 122 return false; 123 } 124 125 return true; 126 } 127 128 static bool __init __check_eq_clump8(const char *srcfile, unsigned int line, 129 const unsigned int offset, 130 const unsigned int size, 131 const unsigned char *const clump_exp, 132 const unsigned long *const clump) 133 { 134 unsigned long exp; 135 136 if (offset >= size) { 137 pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected less than %u, got %u\n", 138 srcfile, line, size, offset); 139 return false; 140 } 141 142 exp = clump_exp[offset / 8]; 143 if (!exp) { 144 pr_warn("[%s:%u] bit offset for zero clump: expected nonzero clump, got bit offset %u with clump value 0", 145 srcfile, line, offset); 146 return false; 147 } 148 149 if (*clump != exp) { 150 pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value of 0x%lX", 151 srcfile, line, exp, *clump); 152 return false; 153 } 154 155 return true; 156 } 157 158 #define __expect_eq(suffix, ...) \ 159 ({ \ 160 int result = 0; \ 161 total_tests++; \ 162 if (!__check_eq_ ## suffix(__FILE__, __LINE__, \ 163 ##__VA_ARGS__)) { \ 164 failed_tests++; \ 165 result = 1; \ 166 } \ 167 result; \ 168 }) 169 170 #define expect_eq_uint(...) __expect_eq(uint, ##__VA_ARGS__) 171 #define expect_eq_bitmap(...) __expect_eq(bitmap, ##__VA_ARGS__) 172 #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__) 173 #define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__) 174 #define expect_eq_clump8(...) __expect_eq(clump8, ##__VA_ARGS__) 175 176 static void __init test_zero_clear(void) 177 { 178 DECLARE_BITMAP(bmap, 1024); 179 180 /* Known way to set all bits */ 181 memset(bmap, 0xff, 128); 182 183 expect_eq_pbl("0-22", bmap, 23); 184 expect_eq_pbl("0-1023", bmap, 1024); 185 186 /* single-word bitmaps */ 187 bitmap_clear(bmap, 0, 9); 188 expect_eq_pbl("9-1023", bmap, 1024); 189 190 bitmap_zero(bmap, 35); 191 expect_eq_pbl("64-1023", bmap, 1024); 192 193 /* cross boundaries operations */ 194 bitmap_clear(bmap, 79, 19); 195 expect_eq_pbl("64-78,98-1023", bmap, 1024); 196 197 bitmap_zero(bmap, 115); 198 expect_eq_pbl("128-1023", bmap, 1024); 199 200 /* Zeroing entire area */ 201 bitmap_zero(bmap, 1024); 202 expect_eq_pbl("", bmap, 1024); 203 } 204 205 static void __init test_fill_set(void) 206 { 207 DECLARE_BITMAP(bmap, 1024); 208 209 /* Known way to clear all bits */ 210 memset(bmap, 0x00, 128); 211 212 expect_eq_pbl("", bmap, 23); 213 expect_eq_pbl("", bmap, 1024); 214 215 /* single-word bitmaps */ 216 bitmap_set(bmap, 0, 9); 217 expect_eq_pbl("0-8", bmap, 1024); 218 219 bitmap_fill(bmap, 35); 220 expect_eq_pbl("0-63", bmap, 1024); 221 222 /* cross boundaries operations */ 223 bitmap_set(bmap, 79, 19); 224 expect_eq_pbl("0-63,79-97", bmap, 1024); 225 226 bitmap_fill(bmap, 115); 227 expect_eq_pbl("0-127", bmap, 1024); 228 229 /* Zeroing entire area */ 230 bitmap_fill(bmap, 1024); 231 expect_eq_pbl("0-1023", bmap, 1024); 232 } 233 234 static void __init test_copy(void) 235 { 236 DECLARE_BITMAP(bmap1, 1024); 237 DECLARE_BITMAP(bmap2, 1024); 238 239 bitmap_zero(bmap1, 1024); 240 bitmap_zero(bmap2, 1024); 241 242 /* single-word bitmaps */ 243 bitmap_set(bmap1, 0, 19); 244 bitmap_copy(bmap2, bmap1, 23); 245 expect_eq_pbl("0-18", bmap2, 1024); 246 247 bitmap_set(bmap2, 0, 23); 248 bitmap_copy(bmap2, bmap1, 23); 249 expect_eq_pbl("0-18", bmap2, 1024); 250 251 /* multi-word bitmaps */ 252 bitmap_set(bmap1, 0, 109); 253 bitmap_copy(bmap2, bmap1, 1024); 254 expect_eq_pbl("0-108", bmap2, 1024); 255 256 bitmap_fill(bmap2, 1024); 257 bitmap_copy(bmap2, bmap1, 1024); 258 expect_eq_pbl("0-108", bmap2, 1024); 259 260 /* the following tests assume a 32- or 64-bit arch (even 128b 261 * if we care) 262 */ 263 264 bitmap_fill(bmap2, 1024); 265 bitmap_copy(bmap2, bmap1, 109); /* ... but 0-padded til word length */ 266 expect_eq_pbl("0-108,128-1023", bmap2, 1024); 267 268 bitmap_fill(bmap2, 1024); 269 bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */ 270 expect_eq_pbl("0-108,128-1023", bmap2, 1024); 271 } 272 273 #define EXP2_IN_BITS (sizeof(exp2) * 8) 274 275 static void __init test_replace(void) 276 { 277 unsigned int nbits = 64; 278 unsigned int nlongs = DIV_ROUND_UP(nbits, BITS_PER_LONG); 279 DECLARE_BITMAP(bmap, 1024); 280 281 BUILD_BUG_ON(EXP2_IN_BITS < nbits * 2); 282 283 bitmap_zero(bmap, 1024); 284 bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits); 285 expect_eq_bitmap(bmap, exp3_0_1, nbits); 286 287 bitmap_zero(bmap, 1024); 288 bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits); 289 expect_eq_bitmap(bmap, exp3_1_0, nbits); 290 291 bitmap_fill(bmap, 1024); 292 bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits); 293 expect_eq_bitmap(bmap, exp3_0_1, nbits); 294 295 bitmap_fill(bmap, 1024); 296 bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits); 297 expect_eq_bitmap(bmap, exp3_1_0, nbits); 298 } 299 300 #define PARSE_TIME 0x1 301 #define NO_LEN 0x2 302 303 struct test_bitmap_parselist{ 304 const int errno; 305 const char *in; 306 const unsigned long *expected; 307 const int nbits; 308 const int flags; 309 }; 310 311 static const struct test_bitmap_parselist parselist_tests[] __initconst = { 312 #define step (sizeof(u64) / sizeof(unsigned long)) 313 314 {0, "0", &exp1[0], 8, 0}, 315 {0, "1", &exp1[1 * step], 8, 0}, 316 {0, "0-15", &exp1[2 * step], 32, 0}, 317 {0, "16-31", &exp1[3 * step], 32, 0}, 318 {0, "0-31:1/2", &exp1[4 * step], 32, 0}, 319 {0, "1-31:1/2", &exp1[5 * step], 32, 0}, 320 {0, "0-31:1/4", &exp1[6 * step], 32, 0}, 321 {0, "1-31:1/4", &exp1[7 * step], 32, 0}, 322 {0, "0-31:4/4", &exp1[8 * step], 32, 0}, 323 {0, "1-31:4/4", &exp1[9 * step], 32, 0}, 324 {0, "0-31:1/4,32-63:2/4", &exp1[10 * step], 64, 0}, 325 {0, "0-31:3/4,32-63:4/4", &exp1[11 * step], 64, 0}, 326 {0, " ,, 0-31:3/4 ,, 32-63:4/4 ,, ", &exp1[11 * step], 64, 0}, 327 328 {0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4", exp2, 128, 0}, 329 330 {0, "0-2047:128/256", NULL, 2048, PARSE_TIME}, 331 332 {0, "", &exp1[12 * step], 8, 0}, 333 {0, "\n", &exp1[12 * step], 8, 0}, 334 {0, ",, ,, , , ,", &exp1[12 * step], 8, 0}, 335 {0, " , ,, , , ", &exp1[12 * step], 8, 0}, 336 {0, " , ,, , , \n", &exp1[12 * step], 8, 0}, 337 338 {-EINVAL, "-1", NULL, 8, 0}, 339 {-EINVAL, "-0", NULL, 8, 0}, 340 {-EINVAL, "10-1", NULL, 8, 0}, 341 {-EINVAL, "0-31:", NULL, 8, 0}, 342 {-EINVAL, "0-31:0", NULL, 8, 0}, 343 {-EINVAL, "0-31:0/", NULL, 8, 0}, 344 {-EINVAL, "0-31:0/0", NULL, 8, 0}, 345 {-EINVAL, "0-31:1/0", NULL, 8, 0}, 346 {-EINVAL, "0-31:10/1", NULL, 8, 0}, 347 {-EOVERFLOW, "0-98765432123456789:10/1", NULL, 8, 0}, 348 349 {-EINVAL, "a-31", NULL, 8, 0}, 350 {-EINVAL, "0-a1", NULL, 8, 0}, 351 {-EINVAL, "a-31:10/1", NULL, 8, 0}, 352 {-EINVAL, "0-31:a/1", NULL, 8, 0}, 353 {-EINVAL, "0-\n", NULL, 8, 0}, 354 355 }; 356 357 static void __init __test_bitmap_parselist(int is_user) 358 { 359 int i; 360 int err; 361 ktime_t time; 362 DECLARE_BITMAP(bmap, 2048); 363 char *mode = is_user ? "_user" : ""; 364 365 for (i = 0; i < ARRAY_SIZE(parselist_tests); i++) { 366 #define ptest parselist_tests[i] 367 368 if (is_user) { 369 mm_segment_t orig_fs = get_fs(); 370 size_t len = strlen(ptest.in); 371 372 set_fs(KERNEL_DS); 373 time = ktime_get(); 374 err = bitmap_parselist_user((__force const char __user *)ptest.in, len, 375 bmap, ptest.nbits); 376 time = ktime_get() - time; 377 set_fs(orig_fs); 378 } else { 379 time = ktime_get(); 380 err = bitmap_parselist(ptest.in, bmap, ptest.nbits); 381 time = ktime_get() - time; 382 } 383 384 if (err != ptest.errno) { 385 pr_err("parselist%s: %d: input is %s, errno is %d, expected %d\n", 386 mode, i, ptest.in, err, ptest.errno); 387 continue; 388 } 389 390 if (!err && ptest.expected 391 && !__bitmap_equal(bmap, ptest.expected, ptest.nbits)) { 392 pr_err("parselist%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n", 393 mode, i, ptest.in, bmap[0], 394 *ptest.expected); 395 continue; 396 } 397 398 if (ptest.flags & PARSE_TIME) 399 pr_err("parselist%s: %d: input is '%s' OK, Time: %llu\n", 400 mode, i, ptest.in, time); 401 402 #undef ptest 403 } 404 } 405 406 static const unsigned long parse_test[] __initconst = { 407 BITMAP_FROM_U64(0), 408 BITMAP_FROM_U64(1), 409 BITMAP_FROM_U64(0xdeadbeef), 410 BITMAP_FROM_U64(0x100000000ULL), 411 }; 412 413 static const unsigned long parse_test2[] __initconst = { 414 BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xdeadbeef), 415 BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xbaadf00ddeadbeef), 416 BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0x0badf00ddeadbeef), 417 }; 418 419 static const struct test_bitmap_parselist parse_tests[] __initconst = { 420 {0, "", &parse_test[0 * step], 32, 0}, 421 {0, " ", &parse_test[0 * step], 32, 0}, 422 {0, "0", &parse_test[0 * step], 32, 0}, 423 {0, "0\n", &parse_test[0 * step], 32, 0}, 424 {0, "1", &parse_test[1 * step], 32, 0}, 425 {0, "deadbeef", &parse_test[2 * step], 32, 0}, 426 {0, "1,0", &parse_test[3 * step], 33, 0}, 427 {0, "deadbeef,\n,0,1", &parse_test[2 * step], 96, 0}, 428 429 {0, "deadbeef,1,0", &parse_test2[0 * 2 * step], 96, 0}, 430 {0, "baadf00d,deadbeef,1,0", &parse_test2[1 * 2 * step], 128, 0}, 431 {0, "badf00d,deadbeef,1,0", &parse_test2[2 * 2 * step], 124, 0}, 432 {0, "badf00d,deadbeef,1,0", &parse_test2[2 * 2 * step], 124, NO_LEN}, 433 {0, " badf00d,deadbeef,1,0 ", &parse_test2[2 * 2 * step], 124, 0}, 434 {0, " , badf00d,deadbeef,1,0 , ", &parse_test2[2 * 2 * step], 124, 0}, 435 {0, " , badf00d, ,, ,,deadbeef,1,0 , ", &parse_test2[2 * 2 * step], 124, 0}, 436 437 {-EINVAL, "goodfood,deadbeef,1,0", NULL, 128, 0}, 438 {-EOVERFLOW, "3,0", NULL, 33, 0}, 439 {-EOVERFLOW, "123badf00d,deadbeef,1,0", NULL, 128, 0}, 440 {-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 90, 0}, 441 {-EOVERFLOW, "fbadf00d,deadbeef,1,0", NULL, 95, 0}, 442 {-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 100, 0}, 443 #undef step 444 }; 445 446 static void __init __test_bitmap_parse(int is_user) 447 { 448 int i; 449 int err; 450 ktime_t time; 451 DECLARE_BITMAP(bmap, 2048); 452 char *mode = is_user ? "_user" : ""; 453 454 for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { 455 struct test_bitmap_parselist test = parse_tests[i]; 456 457 if (is_user) { 458 size_t len = strlen(test.in); 459 mm_segment_t orig_fs = get_fs(); 460 461 set_fs(KERNEL_DS); 462 time = ktime_get(); 463 err = bitmap_parse_user((__force const char __user *)test.in, len, 464 bmap, test.nbits); 465 time = ktime_get() - time; 466 set_fs(orig_fs); 467 } else { 468 size_t len = test.flags & NO_LEN ? 469 UINT_MAX : strlen(test.in); 470 time = ktime_get(); 471 err = bitmap_parse(test.in, len, bmap, test.nbits); 472 time = ktime_get() - time; 473 } 474 475 if (err != test.errno) { 476 pr_err("parse%s: %d: input is %s, errno is %d, expected %d\n", 477 mode, i, test.in, err, test.errno); 478 continue; 479 } 480 481 if (!err && test.expected 482 && !__bitmap_equal(bmap, test.expected, test.nbits)) { 483 pr_err("parse%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n", 484 mode, i, test.in, bmap[0], 485 *test.expected); 486 continue; 487 } 488 489 if (test.flags & PARSE_TIME) 490 pr_err("parse%s: %d: input is '%s' OK, Time: %llu\n", 491 mode, i, test.in, time); 492 } 493 } 494 495 static void __init test_bitmap_parselist(void) 496 { 497 __test_bitmap_parselist(0); 498 } 499 500 static void __init test_bitmap_parselist_user(void) 501 { 502 __test_bitmap_parselist(1); 503 } 504 505 static void __init test_bitmap_parse(void) 506 { 507 __test_bitmap_parse(0); 508 } 509 510 static void __init test_bitmap_parse_user(void) 511 { 512 __test_bitmap_parse(1); 513 } 514 515 #define EXP1_IN_BITS (sizeof(exp1) * 8) 516 517 static void __init test_bitmap_arr32(void) 518 { 519 unsigned int nbits, next_bit; 520 u32 arr[EXP1_IN_BITS / 32]; 521 DECLARE_BITMAP(bmap2, EXP1_IN_BITS); 522 523 memset(arr, 0xa5, sizeof(arr)); 524 525 for (nbits = 0; nbits < EXP1_IN_BITS; ++nbits) { 526 bitmap_to_arr32(arr, exp1, nbits); 527 bitmap_from_arr32(bmap2, arr, nbits); 528 expect_eq_bitmap(bmap2, exp1, nbits); 529 530 next_bit = find_next_bit(bmap2, 531 round_up(nbits, BITS_PER_LONG), nbits); 532 if (next_bit < round_up(nbits, BITS_PER_LONG)) 533 pr_err("bitmap_copy_arr32(nbits == %d:" 534 " tail is not safely cleared: %d\n", 535 nbits, next_bit); 536 537 if (nbits < EXP1_IN_BITS - 32) 538 expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)], 539 0xa5a5a5a5); 540 } 541 } 542 543 static void noinline __init test_mem_optimisations(void) 544 { 545 DECLARE_BITMAP(bmap1, 1024); 546 DECLARE_BITMAP(bmap2, 1024); 547 unsigned int start, nbits; 548 549 for (start = 0; start < 1024; start += 8) { 550 for (nbits = 0; nbits < 1024 - start; nbits += 8) { 551 memset(bmap1, 0x5a, sizeof(bmap1)); 552 memset(bmap2, 0x5a, sizeof(bmap2)); 553 554 bitmap_set(bmap1, start, nbits); 555 __bitmap_set(bmap2, start, nbits); 556 if (!bitmap_equal(bmap1, bmap2, 1024)) { 557 printk("set not equal %d %d\n", start, nbits); 558 failed_tests++; 559 } 560 if (!__bitmap_equal(bmap1, bmap2, 1024)) { 561 printk("set not __equal %d %d\n", start, nbits); 562 failed_tests++; 563 } 564 565 bitmap_clear(bmap1, start, nbits); 566 __bitmap_clear(bmap2, start, nbits); 567 if (!bitmap_equal(bmap1, bmap2, 1024)) { 568 printk("clear not equal %d %d\n", start, nbits); 569 failed_tests++; 570 } 571 if (!__bitmap_equal(bmap1, bmap2, 1024)) { 572 printk("clear not __equal %d %d\n", start, 573 nbits); 574 failed_tests++; 575 } 576 } 577 } 578 } 579 580 static const unsigned char clump_exp[] __initconst = { 581 0x01, /* 1 bit set */ 582 0x02, /* non-edge 1 bit set */ 583 0x00, /* zero bits set */ 584 0x38, /* 3 bits set across 4-bit boundary */ 585 0x38, /* Repeated clump */ 586 0x0F, /* 4 bits set */ 587 0xFF, /* all bits set */ 588 0x05, /* non-adjacent 2 bits set */ 589 }; 590 591 static void __init test_for_each_set_clump8(void) 592 { 593 #define CLUMP_EXP_NUMBITS 64 594 DECLARE_BITMAP(bits, CLUMP_EXP_NUMBITS); 595 unsigned int start; 596 unsigned long clump; 597 598 /* set bitmap to test case */ 599 bitmap_zero(bits, CLUMP_EXP_NUMBITS); 600 bitmap_set(bits, 0, 1); /* 0x01 */ 601 bitmap_set(bits, 9, 1); /* 0x02 */ 602 bitmap_set(bits, 27, 3); /* 0x28 */ 603 bitmap_set(bits, 35, 3); /* 0x28 */ 604 bitmap_set(bits, 40, 4); /* 0x0F */ 605 bitmap_set(bits, 48, 8); /* 0xFF */ 606 bitmap_set(bits, 56, 1); /* 0x05 - part 1 */ 607 bitmap_set(bits, 58, 1); /* 0x05 - part 2 */ 608 609 for_each_set_clump8(start, clump, bits, CLUMP_EXP_NUMBITS) 610 expect_eq_clump8(start, CLUMP_EXP_NUMBITS, clump_exp, &clump); 611 } 612 613 struct test_bitmap_cut { 614 unsigned int first; 615 unsigned int cut; 616 unsigned int nbits; 617 unsigned long in[4]; 618 unsigned long expected[4]; 619 }; 620 621 static struct test_bitmap_cut test_cut[] = { 622 { 0, 0, 8, { 0x0000000aUL, }, { 0x0000000aUL, }, }, 623 { 0, 0, 32, { 0xdadadeadUL, }, { 0xdadadeadUL, }, }, 624 { 0, 3, 8, { 0x000000aaUL, }, { 0x00000015UL, }, }, 625 { 3, 3, 8, { 0x000000aaUL, }, { 0x00000012UL, }, }, 626 { 0, 1, 32, { 0xa5a5a5a5UL, }, { 0x52d2d2d2UL, }, }, 627 { 0, 8, 32, { 0xdeadc0deUL, }, { 0x00deadc0UL, }, }, 628 { 1, 1, 32, { 0x5a5a5a5aUL, }, { 0x2d2d2d2cUL, }, }, 629 { 0, 15, 32, { 0xa5a5a5a5UL, }, { 0x00014b4bUL, }, }, 630 { 0, 16, 32, { 0xa5a5a5a5UL, }, { 0x0000a5a5UL, }, }, 631 { 15, 15, 32, { 0xa5a5a5a5UL, }, { 0x000125a5UL, }, }, 632 { 15, 16, 32, { 0xa5a5a5a5UL, }, { 0x0000a5a5UL, }, }, 633 { 16, 15, 32, { 0xa5a5a5a5UL, }, { 0x0001a5a5UL, }, }, 634 635 { BITS_PER_LONG, BITS_PER_LONG, BITS_PER_LONG, 636 { 0xa5a5a5a5UL, 0xa5a5a5a5UL, }, 637 { 0xa5a5a5a5UL, 0xa5a5a5a5UL, }, 638 }, 639 { 1, BITS_PER_LONG - 1, BITS_PER_LONG, 640 { 0xa5a5a5a5UL, 0xa5a5a5a5UL, }, 641 { 0x00000001UL, 0x00000001UL, }, 642 }, 643 644 { 0, BITS_PER_LONG * 2, BITS_PER_LONG * 2 + 1, 645 { 0xa5a5a5a5UL, 0x00000001UL, 0x00000001UL, 0x00000001UL }, 646 { 0x00000001UL, }, 647 }, 648 { 16, BITS_PER_LONG * 2 + 1, BITS_PER_LONG * 2 + 1 + 16, 649 { 0x0000ffffUL, 0x5a5a5a5aUL, 0x5a5a5a5aUL, 0x5a5a5a5aUL }, 650 { 0x2d2dffffUL, }, 651 }, 652 }; 653 654 static void __init test_bitmap_cut(void) 655 { 656 unsigned long b[5], *in = &b[1], *out = &b[0]; /* Partial overlap */ 657 int i; 658 659 for (i = 0; i < ARRAY_SIZE(test_cut); i++) { 660 struct test_bitmap_cut *t = &test_cut[i]; 661 662 memcpy(in, t->in, sizeof(t->in)); 663 664 bitmap_cut(out, in, t->first, t->cut, t->nbits); 665 666 expect_eq_bitmap(t->expected, out, t->nbits); 667 } 668 } 669 670 static void __init selftest(void) 671 { 672 test_zero_clear(); 673 test_fill_set(); 674 test_copy(); 675 test_replace(); 676 test_bitmap_arr32(); 677 test_bitmap_parse(); 678 test_bitmap_parse_user(); 679 test_bitmap_parselist(); 680 test_bitmap_parselist_user(); 681 test_mem_optimisations(); 682 test_for_each_set_clump8(); 683 test_bitmap_cut(); 684 } 685 686 KSTM_MODULE_LOADERS(test_bitmap); 687 MODULE_AUTHOR("david decotigny <david.decotigny@googlers.com>"); 688 MODULE_LICENSE("GPL"); 689