1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Test cases for printf facility. 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 25 static bool __init 26 __check_eq_uint(const char *srcfile, unsigned int line, 27 const unsigned int exp_uint, unsigned int x) 28 { 29 if (exp_uint != x) { 30 pr_err("[%s:%u] expected %u, got %u\n", 31 srcfile, line, exp_uint, x); 32 return false; 33 } 34 return true; 35 } 36 37 38 static bool __init 39 __check_eq_bitmap(const char *srcfile, unsigned int line, 40 const unsigned long *exp_bmap, const unsigned long *bmap, 41 unsigned int nbits) 42 { 43 if (!bitmap_equal(exp_bmap, bmap, nbits)) { 44 pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n", 45 srcfile, line, 46 nbits, exp_bmap, nbits, bmap); 47 return false; 48 } 49 return true; 50 } 51 52 static bool __init 53 __check_eq_pbl(const char *srcfile, unsigned int line, 54 const char *expected_pbl, 55 const unsigned long *bitmap, unsigned int nbits) 56 { 57 snprintf(pbl_buffer, sizeof(pbl_buffer), "%*pbl", nbits, bitmap); 58 if (strcmp(expected_pbl, pbl_buffer)) { 59 pr_warn("[%s:%u] expected \"%s\", got \"%s\"\n", 60 srcfile, line, 61 expected_pbl, pbl_buffer); 62 return false; 63 } 64 return true; 65 } 66 67 static bool __init 68 __check_eq_u32_array(const char *srcfile, unsigned int line, 69 const u32 *exp_arr, unsigned int exp_len, 70 const u32 *arr, unsigned int len) __used; 71 static bool __init 72 __check_eq_u32_array(const char *srcfile, unsigned int line, 73 const u32 *exp_arr, unsigned int exp_len, 74 const u32 *arr, unsigned int len) 75 { 76 if (exp_len != len) { 77 pr_warn("[%s:%u] array length differ: expected %u, got %u\n", 78 srcfile, line, 79 exp_len, len); 80 return false; 81 } 82 83 if (memcmp(exp_arr, arr, len*sizeof(*arr))) { 84 pr_warn("[%s:%u] array contents differ\n", srcfile, line); 85 print_hex_dump(KERN_WARNING, " exp: ", DUMP_PREFIX_OFFSET, 86 32, 4, exp_arr, exp_len*sizeof(*exp_arr), false); 87 print_hex_dump(KERN_WARNING, " got: ", DUMP_PREFIX_OFFSET, 88 32, 4, arr, len*sizeof(*arr), false); 89 return false; 90 } 91 92 return true; 93 } 94 95 static bool __init __check_eq_clump8(const char *srcfile, unsigned int line, 96 const unsigned int offset, 97 const unsigned int size, 98 const unsigned char *const clump_exp, 99 const unsigned long *const clump) 100 { 101 unsigned long exp; 102 103 if (offset >= size) { 104 pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected less than %u, got %u\n", 105 srcfile, line, size, offset); 106 return false; 107 } 108 109 exp = clump_exp[offset / 8]; 110 if (!exp) { 111 pr_warn("[%s:%u] bit offset for zero clump: expected nonzero clump, got bit offset %u with clump value 0", 112 srcfile, line, offset); 113 return false; 114 } 115 116 if (*clump != exp) { 117 pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value of 0x%lX", 118 srcfile, line, exp, *clump); 119 return false; 120 } 121 122 return true; 123 } 124 125 #define __expect_eq(suffix, ...) \ 126 ({ \ 127 int result = 0; \ 128 total_tests++; \ 129 if (!__check_eq_ ## suffix(__FILE__, __LINE__, \ 130 ##__VA_ARGS__)) { \ 131 failed_tests++; \ 132 result = 1; \ 133 } \ 134 result; \ 135 }) 136 137 #define expect_eq_uint(...) __expect_eq(uint, ##__VA_ARGS__) 138 #define expect_eq_bitmap(...) __expect_eq(bitmap, ##__VA_ARGS__) 139 #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__) 140 #define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__) 141 #define expect_eq_clump8(...) __expect_eq(clump8, ##__VA_ARGS__) 142 143 static void __init test_zero_clear(void) 144 { 145 DECLARE_BITMAP(bmap, 1024); 146 147 /* Known way to set all bits */ 148 memset(bmap, 0xff, 128); 149 150 expect_eq_pbl("0-22", bmap, 23); 151 expect_eq_pbl("0-1023", bmap, 1024); 152 153 /* single-word bitmaps */ 154 bitmap_clear(bmap, 0, 9); 155 expect_eq_pbl("9-1023", bmap, 1024); 156 157 bitmap_zero(bmap, 35); 158 expect_eq_pbl("64-1023", bmap, 1024); 159 160 /* cross boundaries operations */ 161 bitmap_clear(bmap, 79, 19); 162 expect_eq_pbl("64-78,98-1023", bmap, 1024); 163 164 bitmap_zero(bmap, 115); 165 expect_eq_pbl("128-1023", bmap, 1024); 166 167 /* Zeroing entire area */ 168 bitmap_zero(bmap, 1024); 169 expect_eq_pbl("", bmap, 1024); 170 } 171 172 static void __init test_fill_set(void) 173 { 174 DECLARE_BITMAP(bmap, 1024); 175 176 /* Known way to clear all bits */ 177 memset(bmap, 0x00, 128); 178 179 expect_eq_pbl("", bmap, 23); 180 expect_eq_pbl("", bmap, 1024); 181 182 /* single-word bitmaps */ 183 bitmap_set(bmap, 0, 9); 184 expect_eq_pbl("0-8", bmap, 1024); 185 186 bitmap_fill(bmap, 35); 187 expect_eq_pbl("0-63", bmap, 1024); 188 189 /* cross boundaries operations */ 190 bitmap_set(bmap, 79, 19); 191 expect_eq_pbl("0-63,79-97", bmap, 1024); 192 193 bitmap_fill(bmap, 115); 194 expect_eq_pbl("0-127", bmap, 1024); 195 196 /* Zeroing entire area */ 197 bitmap_fill(bmap, 1024); 198 expect_eq_pbl("0-1023", bmap, 1024); 199 } 200 201 static void __init test_copy(void) 202 { 203 DECLARE_BITMAP(bmap1, 1024); 204 DECLARE_BITMAP(bmap2, 1024); 205 206 bitmap_zero(bmap1, 1024); 207 bitmap_zero(bmap2, 1024); 208 209 /* single-word bitmaps */ 210 bitmap_set(bmap1, 0, 19); 211 bitmap_copy(bmap2, bmap1, 23); 212 expect_eq_pbl("0-18", bmap2, 1024); 213 214 bitmap_set(bmap2, 0, 23); 215 bitmap_copy(bmap2, bmap1, 23); 216 expect_eq_pbl("0-18", bmap2, 1024); 217 218 /* multi-word bitmaps */ 219 bitmap_set(bmap1, 0, 109); 220 bitmap_copy(bmap2, bmap1, 1024); 221 expect_eq_pbl("0-108", bmap2, 1024); 222 223 bitmap_fill(bmap2, 1024); 224 bitmap_copy(bmap2, bmap1, 1024); 225 expect_eq_pbl("0-108", bmap2, 1024); 226 227 /* the following tests assume a 32- or 64-bit arch (even 128b 228 * if we care) 229 */ 230 231 bitmap_fill(bmap2, 1024); 232 bitmap_copy(bmap2, bmap1, 109); /* ... but 0-padded til word length */ 233 expect_eq_pbl("0-108,128-1023", bmap2, 1024); 234 235 bitmap_fill(bmap2, 1024); 236 bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */ 237 expect_eq_pbl("0-108,128-1023", bmap2, 1024); 238 } 239 240 #define PARSE_TIME 0x1 241 242 struct test_bitmap_parselist{ 243 const int errno; 244 const char *in; 245 const unsigned long *expected; 246 const int nbits; 247 const int flags; 248 }; 249 250 static const unsigned long exp[] __initconst = { 251 BITMAP_FROM_U64(1), 252 BITMAP_FROM_U64(2), 253 BITMAP_FROM_U64(0x0000ffff), 254 BITMAP_FROM_U64(0xffff0000), 255 BITMAP_FROM_U64(0x55555555), 256 BITMAP_FROM_U64(0xaaaaaaaa), 257 BITMAP_FROM_U64(0x11111111), 258 BITMAP_FROM_U64(0x22222222), 259 BITMAP_FROM_U64(0xffffffff), 260 BITMAP_FROM_U64(0xfffffffe), 261 BITMAP_FROM_U64(0x3333333311111111ULL), 262 BITMAP_FROM_U64(0xffffffff77777777ULL), 263 BITMAP_FROM_U64(0), 264 }; 265 266 static const unsigned long exp2[] __initconst = { 267 BITMAP_FROM_U64(0x3333333311111111ULL), 268 BITMAP_FROM_U64(0xffffffff77777777ULL) 269 }; 270 271 static const struct test_bitmap_parselist parselist_tests[] __initconst = { 272 #define step (sizeof(u64) / sizeof(unsigned long)) 273 274 {0, "0", &exp[0], 8, 0}, 275 {0, "1", &exp[1 * step], 8, 0}, 276 {0, "0-15", &exp[2 * step], 32, 0}, 277 {0, "16-31", &exp[3 * step], 32, 0}, 278 {0, "0-31:1/2", &exp[4 * step], 32, 0}, 279 {0, "1-31:1/2", &exp[5 * step], 32, 0}, 280 {0, "0-31:1/4", &exp[6 * step], 32, 0}, 281 {0, "1-31:1/4", &exp[7 * step], 32, 0}, 282 {0, "0-31:4/4", &exp[8 * step], 32, 0}, 283 {0, "1-31:4/4", &exp[9 * step], 32, 0}, 284 {0, "0-31:1/4,32-63:2/4", &exp[10 * step], 64, 0}, 285 {0, "0-31:3/4,32-63:4/4", &exp[11 * step], 64, 0}, 286 {0, " ,, 0-31:3/4 ,, 32-63:4/4 ,, ", &exp[11 * step], 64, 0}, 287 288 {0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4", exp2, 128, 0}, 289 290 {0, "0-2047:128/256", NULL, 2048, PARSE_TIME}, 291 292 {0, "", &exp[12 * step], 8, 0}, 293 {0, "\n", &exp[12 * step], 8, 0}, 294 {0, ",, ,, , , ,", &exp[12 * step], 8, 0}, 295 {0, " , ,, , , ", &exp[12 * step], 8, 0}, 296 {0, " , ,, , , \n", &exp[12 * step], 8, 0}, 297 298 {-EINVAL, "-1", NULL, 8, 0}, 299 {-EINVAL, "-0", NULL, 8, 0}, 300 {-EINVAL, "10-1", NULL, 8, 0}, 301 {-EINVAL, "0-31:", NULL, 8, 0}, 302 {-EINVAL, "0-31:0", NULL, 8, 0}, 303 {-EINVAL, "0-31:0/", NULL, 8, 0}, 304 {-EINVAL, "0-31:0/0", NULL, 8, 0}, 305 {-EINVAL, "0-31:1/0", NULL, 8, 0}, 306 {-EINVAL, "0-31:10/1", NULL, 8, 0}, 307 {-EOVERFLOW, "0-98765432123456789:10/1", NULL, 8, 0}, 308 309 {-EINVAL, "a-31", NULL, 8, 0}, 310 {-EINVAL, "0-a1", NULL, 8, 0}, 311 {-EINVAL, "a-31:10/1", NULL, 8, 0}, 312 {-EINVAL, "0-31:a/1", NULL, 8, 0}, 313 {-EINVAL, "0-\n", NULL, 8, 0}, 314 }; 315 316 static void __init __test_bitmap_parselist(int is_user) 317 { 318 int i; 319 int err; 320 ktime_t time; 321 DECLARE_BITMAP(bmap, 2048); 322 char *mode = is_user ? "_user" : ""; 323 324 for (i = 0; i < ARRAY_SIZE(parselist_tests); i++) { 325 #define ptest parselist_tests[i] 326 327 if (is_user) { 328 mm_segment_t orig_fs = get_fs(); 329 size_t len = strlen(ptest.in); 330 331 set_fs(KERNEL_DS); 332 time = ktime_get(); 333 err = bitmap_parselist_user(ptest.in, len, 334 bmap, ptest.nbits); 335 time = ktime_get() - time; 336 set_fs(orig_fs); 337 } else { 338 time = ktime_get(); 339 err = bitmap_parselist(ptest.in, bmap, ptest.nbits); 340 time = ktime_get() - time; 341 } 342 343 if (err != ptest.errno) { 344 pr_err("parselist%s: %d: input is %s, errno is %d, expected %d\n", 345 mode, i, ptest.in, err, ptest.errno); 346 continue; 347 } 348 349 if (!err && ptest.expected 350 && !__bitmap_equal(bmap, ptest.expected, ptest.nbits)) { 351 pr_err("parselist%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n", 352 mode, i, ptest.in, bmap[0], 353 *ptest.expected); 354 continue; 355 } 356 357 if (ptest.flags & PARSE_TIME) 358 pr_err("parselist%s: %d: input is '%s' OK, Time: %llu\n", 359 mode, i, ptest.in, time); 360 } 361 } 362 363 static void __init test_bitmap_parselist(void) 364 { 365 __test_bitmap_parselist(0); 366 } 367 368 static void __init test_bitmap_parselist_user(void) 369 { 370 __test_bitmap_parselist(1); 371 } 372 373 #define EXP_BYTES (sizeof(exp) * 8) 374 375 static void __init test_bitmap_arr32(void) 376 { 377 unsigned int nbits, next_bit; 378 u32 arr[sizeof(exp) / 4]; 379 DECLARE_BITMAP(bmap2, EXP_BYTES); 380 381 memset(arr, 0xa5, sizeof(arr)); 382 383 for (nbits = 0; nbits < EXP_BYTES; ++nbits) { 384 bitmap_to_arr32(arr, exp, nbits); 385 bitmap_from_arr32(bmap2, arr, nbits); 386 expect_eq_bitmap(bmap2, exp, nbits); 387 388 next_bit = find_next_bit(bmap2, 389 round_up(nbits, BITS_PER_LONG), nbits); 390 if (next_bit < round_up(nbits, BITS_PER_LONG)) 391 pr_err("bitmap_copy_arr32(nbits == %d:" 392 " tail is not safely cleared: %d\n", 393 nbits, next_bit); 394 395 if (nbits < EXP_BYTES - 32) 396 expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)], 397 0xa5a5a5a5); 398 } 399 } 400 401 static void noinline __init test_mem_optimisations(void) 402 { 403 DECLARE_BITMAP(bmap1, 1024); 404 DECLARE_BITMAP(bmap2, 1024); 405 unsigned int start, nbits; 406 407 for (start = 0; start < 1024; start += 8) { 408 for (nbits = 0; nbits < 1024 - start; nbits += 8) { 409 memset(bmap1, 0x5a, sizeof(bmap1)); 410 memset(bmap2, 0x5a, sizeof(bmap2)); 411 412 bitmap_set(bmap1, start, nbits); 413 __bitmap_set(bmap2, start, nbits); 414 if (!bitmap_equal(bmap1, bmap2, 1024)) { 415 printk("set not equal %d %d\n", start, nbits); 416 failed_tests++; 417 } 418 if (!__bitmap_equal(bmap1, bmap2, 1024)) { 419 printk("set not __equal %d %d\n", start, nbits); 420 failed_tests++; 421 } 422 423 bitmap_clear(bmap1, start, nbits); 424 __bitmap_clear(bmap2, start, nbits); 425 if (!bitmap_equal(bmap1, bmap2, 1024)) { 426 printk("clear not equal %d %d\n", start, nbits); 427 failed_tests++; 428 } 429 if (!__bitmap_equal(bmap1, bmap2, 1024)) { 430 printk("clear not __equal %d %d\n", start, 431 nbits); 432 failed_tests++; 433 } 434 } 435 } 436 } 437 438 static const unsigned char clump_exp[] __initconst = { 439 0x01, /* 1 bit set */ 440 0x02, /* non-edge 1 bit set */ 441 0x00, /* zero bits set */ 442 0x38, /* 3 bits set across 4-bit boundary */ 443 0x38, /* Repeated clump */ 444 0x0F, /* 4 bits set */ 445 0xFF, /* all bits set */ 446 0x05, /* non-adjacent 2 bits set */ 447 }; 448 449 static void __init test_for_each_set_clump8(void) 450 { 451 #define CLUMP_EXP_NUMBITS 64 452 DECLARE_BITMAP(bits, CLUMP_EXP_NUMBITS); 453 unsigned int start; 454 unsigned long clump; 455 456 /* set bitmap to test case */ 457 bitmap_zero(bits, CLUMP_EXP_NUMBITS); 458 bitmap_set(bits, 0, 1); /* 0x01 */ 459 bitmap_set(bits, 9, 1); /* 0x02 */ 460 bitmap_set(bits, 27, 3); /* 0x28 */ 461 bitmap_set(bits, 35, 3); /* 0x28 */ 462 bitmap_set(bits, 40, 4); /* 0x0F */ 463 bitmap_set(bits, 48, 8); /* 0xFF */ 464 bitmap_set(bits, 56, 1); /* 0x05 - part 1 */ 465 bitmap_set(bits, 58, 1); /* 0x05 - part 2 */ 466 467 for_each_set_clump8(start, clump, bits, CLUMP_EXP_NUMBITS) 468 expect_eq_clump8(start, CLUMP_EXP_NUMBITS, clump_exp, &clump); 469 } 470 471 static void __init selftest(void) 472 { 473 test_zero_clear(); 474 test_fill_set(); 475 test_copy(); 476 test_bitmap_arr32(); 477 test_bitmap_parselist(); 478 test_bitmap_parselist_user(); 479 test_mem_optimisations(); 480 test_for_each_set_clump8(); 481 } 482 483 KSTM_MODULE_LOADERS(test_bitmap); 484 MODULE_AUTHOR("david decotigny <david.decotigny@googlers.com>"); 485 MODULE_LICENSE("GPL"); 486