1b3a7bb71SKees Cook // SPDX-License-Identifier: GPL-2.0-only 2b3a7bb71SKees Cook /* 3b3a7bb71SKees Cook * KUnit tests for ffs()-family functions 4b3a7bb71SKees Cook */ 5b3a7bb71SKees Cook #include <kunit/test.h> 6b3a7bb71SKees Cook #include <linux/bitops.h> 7b3a7bb71SKees Cook 8b3a7bb71SKees Cook /* 9b3a7bb71SKees Cook * Test data structures 10b3a7bb71SKees Cook */ 11b3a7bb71SKees Cook struct ffs_test_case { 12b3a7bb71SKees Cook unsigned long input; 13b3a7bb71SKees Cook int expected_ffs; /* ffs() result (1-based) */ 14b3a7bb71SKees Cook int expected_fls; /* fls() result (1-based) */ 15b3a7bb71SKees Cook const char *description; 16b3a7bb71SKees Cook }; 17b3a7bb71SKees Cook 18b3a7bb71SKees Cook struct ffs64_test_case { 19b3a7bb71SKees Cook u64 input; 20b3a7bb71SKees Cook int expected_fls64; /* fls64() result (1-based) */ 21b3a7bb71SKees Cook unsigned int expected_ffs64_0based; /* __ffs64() result (0-based) */ 22b3a7bb71SKees Cook const char *description; 23b3a7bb71SKees Cook }; 24b3a7bb71SKees Cook 25b3a7bb71SKees Cook /* 26b3a7bb71SKees Cook * Basic edge cases - core functionality validation 27b3a7bb71SKees Cook */ 28b3a7bb71SKees Cook static const struct ffs_test_case basic_test_cases[] = { 29b3a7bb71SKees Cook /* Zero case - special handling */ 30b3a7bb71SKees Cook {0x00000000, 0, 0, "zero value"}, 31b3a7bb71SKees Cook 32b3a7bb71SKees Cook /* Single bit patterns - powers of 2 */ 33b3a7bb71SKees Cook {0x00000001, 1, 1, "bit 0 set"}, 34b3a7bb71SKees Cook {0x00000002, 2, 2, "bit 1 set"}, 35b3a7bb71SKees Cook {0x00000004, 3, 3, "bit 2 set"}, 36b3a7bb71SKees Cook {0x00000008, 4, 4, "bit 3 set"}, 37b3a7bb71SKees Cook {0x00000010, 5, 5, "bit 4 set"}, 38b3a7bb71SKees Cook {0x00000020, 6, 6, "bit 5 set"}, 39b3a7bb71SKees Cook {0x00000040, 7, 7, "bit 6 set"}, 40b3a7bb71SKees Cook {0x00000080, 8, 8, "bit 7 set"}, 41b3a7bb71SKees Cook {0x00000100, 9, 9, "bit 8 set"}, 42b3a7bb71SKees Cook {0x00008000, 16, 16, "bit 15 set"}, 43b3a7bb71SKees Cook {0x00010000, 17, 17, "bit 16 set"}, 44b3a7bb71SKees Cook {0x40000000, 31, 31, "bit 30 set"}, 45b3a7bb71SKees Cook {0x80000000, 32, 32, "bit 31 set (sign bit)"}, 46b3a7bb71SKees Cook 47b3a7bb71SKees Cook /* Maximum values */ 48b3a7bb71SKees Cook {0xFFFFFFFF, 1, 32, "all bits set"}, 49b3a7bb71SKees Cook 50b3a7bb71SKees Cook /* Multiple bit patterns */ 51b3a7bb71SKees Cook {0x00000003, 1, 2, "bits 0-1 set"}, 52b3a7bb71SKees Cook {0x00000007, 1, 3, "bits 0-2 set"}, 53b3a7bb71SKees Cook {0x0000000F, 1, 4, "bits 0-3 set"}, 54b3a7bb71SKees Cook {0x000000FF, 1, 8, "bits 0-7 set"}, 55b3a7bb71SKees Cook {0x0000FFFF, 1, 16, "bits 0-15 set"}, 56b3a7bb71SKees Cook {0x7FFFFFFF, 1, 31, "bits 0-30 set"}, 57b3a7bb71SKees Cook 58b3a7bb71SKees Cook /* Sparse patterns */ 59b3a7bb71SKees Cook {0x00000101, 1, 9, "bits 0,8 set"}, 60b3a7bb71SKees Cook {0x00001001, 1, 13, "bits 0,12 set"}, 61b3a7bb71SKees Cook {0x80000001, 1, 32, "bits 0,31 set"}, 62b3a7bb71SKees Cook {0x40000002, 2, 31, "bits 1,30 set"}, 63b3a7bb71SKees Cook }; 64b3a7bb71SKees Cook 65b3a7bb71SKees Cook /* 66b3a7bb71SKees Cook * 64-bit test cases 67b3a7bb71SKees Cook */ 68b3a7bb71SKees Cook static const struct ffs64_test_case ffs64_test_cases[] = { 69b3a7bb71SKees Cook /* Zero case */ 70b3a7bb71SKees Cook {0x0000000000000000ULL, 0, 0, "zero value"}, 71b3a7bb71SKees Cook 72b3a7bb71SKees Cook /* Single bit patterns */ 73b3a7bb71SKees Cook {0x0000000000000001ULL, 1, 0, "bit 0 set"}, 74b3a7bb71SKees Cook {0x0000000000000002ULL, 2, 1, "bit 1 set"}, 75b3a7bb71SKees Cook {0x0000000000000004ULL, 3, 2, "bit 2 set"}, 76b3a7bb71SKees Cook {0x0000000000000008ULL, 4, 3, "bit 3 set"}, 77b3a7bb71SKees Cook {0x0000000000008000ULL, 16, 15, "bit 15 set"}, 78b3a7bb71SKees Cook {0x0000000000010000ULL, 17, 16, "bit 16 set"}, 79b3a7bb71SKees Cook {0x0000000080000000ULL, 32, 31, "bit 31 set"}, 80b3a7bb71SKees Cook {0x0000000100000000ULL, 33, 32, "bit 32 set"}, 81b3a7bb71SKees Cook {0x0000000200000000ULL, 34, 33, "bit 33 set"}, 82b3a7bb71SKees Cook {0x4000000000000000ULL, 63, 62, "bit 62 set"}, 83b3a7bb71SKees Cook {0x8000000000000000ULL, 64, 63, "bit 63 set (sign bit)"}, 84b3a7bb71SKees Cook 85b3a7bb71SKees Cook /* Maximum values */ 86b3a7bb71SKees Cook {0xFFFFFFFFFFFFFFFFULL, 64, 0, "all bits set"}, 87b3a7bb71SKees Cook 88b3a7bb71SKees Cook /* Cross 32-bit boundary patterns */ 89b3a7bb71SKees Cook {0x00000000FFFFFFFFULL, 32, 0, "lower 32 bits set"}, 90b3a7bb71SKees Cook {0xFFFFFFFF00000000ULL, 64, 32, "upper 32 bits set"}, 91b3a7bb71SKees Cook {0x8000000000000001ULL, 64, 0, "bits 0,63 set"}, 92b3a7bb71SKees Cook {0x4000000000000002ULL, 63, 1, "bits 1,62 set"}, 93b3a7bb71SKees Cook 94b3a7bb71SKees Cook /* Mixed patterns */ 95b3a7bb71SKees Cook {0x00000001FFFFFFFFULL, 33, 0, "bit 32 + lower 32 bits"}, 96b3a7bb71SKees Cook {0xFFFFFFFF80000000ULL, 64, 31, "upper 32 bits + bit 31"}, 97b3a7bb71SKees Cook }; 98b3a7bb71SKees Cook 99b3a7bb71SKees Cook /* 100b3a7bb71SKees Cook * Helper function to validate ffs results with detailed error messages 101b3a7bb71SKees Cook */ 102b3a7bb71SKees Cook static void validate_ffs_result(struct kunit *test, unsigned long input, 103b3a7bb71SKees Cook int actual, int expected, const char *func_name, 104b3a7bb71SKees Cook const char *description) 105b3a7bb71SKees Cook { 106b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, actual, expected, 107b3a7bb71SKees Cook "%s(0x%08lx) [%s]: expected %d, got %d", 108b3a7bb71SKees Cook func_name, input, description, expected, actual); 109b3a7bb71SKees Cook } 110b3a7bb71SKees Cook 111b3a7bb71SKees Cook /* 112b3a7bb71SKees Cook * Helper function to validate 64-bit ffs results 113b3a7bb71SKees Cook */ 114b3a7bb71SKees Cook static void validate_ffs64_result(struct kunit *test, u64 input, 115b3a7bb71SKees Cook int actual, int expected, const char *func_name, 116b3a7bb71SKees Cook const char *description) 117b3a7bb71SKees Cook { 118b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, actual, expected, 119b3a7bb71SKees Cook "%s(0x%016llx) [%s]: expected %d, got %d", 120b3a7bb71SKees Cook func_name, input, description, expected, actual); 121b3a7bb71SKees Cook } 122b3a7bb71SKees Cook 123b3a7bb71SKees Cook /* 124b3a7bb71SKees Cook * Helper function to validate mathematical relationships between functions 125b3a7bb71SKees Cook */ 126b3a7bb71SKees Cook static void validate_ffs_relationships(struct kunit *test, unsigned long input) 127b3a7bb71SKees Cook { 128b3a7bb71SKees Cook int ffs_result; 129b3a7bb71SKees Cook int fls_result; 130b3a7bb71SKees Cook unsigned int ffs_0based; 131b3a7bb71SKees Cook unsigned int fls_0based; 132b3a7bb71SKees Cook 133b3a7bb71SKees Cook if (input == 0) { 134b3a7bb71SKees Cook /* Special case: zero input */ 135b3a7bb71SKees Cook KUNIT_EXPECT_EQ(test, ffs(input), 0); 136b3a7bb71SKees Cook KUNIT_EXPECT_EQ(test, fls(input), 0); 137b3a7bb71SKees Cook /* __ffs and __fls are undefined for 0, but often return specific values */ 138b3a7bb71SKees Cook return; 139b3a7bb71SKees Cook } 140b3a7bb71SKees Cook 141b3a7bb71SKees Cook ffs_result = ffs(input); 142b3a7bb71SKees Cook fls_result = fls(input); 143b3a7bb71SKees Cook ffs_0based = __ffs(input); 144b3a7bb71SKees Cook fls_0based = __fls(input); 145b3a7bb71SKees Cook 146b3a7bb71SKees Cook /* Relationship: ffs(x) == __ffs(x) + 1 for x != 0 */ 147b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, ffs_result, ffs_0based + 1, 148b3a7bb71SKees Cook "ffs(0x%08lx) != __ffs(0x%08lx) + 1: %d != %u + 1", 149b3a7bb71SKees Cook input, input, ffs_result, ffs_0based); 150b3a7bb71SKees Cook 151b3a7bb71SKees Cook /* Relationship: fls(x) == __fls(x) + 1 for x != 0 */ 152b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, fls_result, fls_0based + 1, 153b3a7bb71SKees Cook "fls(0x%08lx) != __fls(0x%08lx) + 1: %d != %u + 1", 154b3a7bb71SKees Cook input, input, fls_result, fls_0based); 155b3a7bb71SKees Cook 156b3a7bb71SKees Cook /* Range validation */ 157b3a7bb71SKees Cook KUNIT_EXPECT_GE(test, ffs_result, 1); 158b3a7bb71SKees Cook KUNIT_EXPECT_LE(test, ffs_result, BITS_PER_LONG); 159b3a7bb71SKees Cook KUNIT_EXPECT_GE(test, fls_result, 1); 160b3a7bb71SKees Cook KUNIT_EXPECT_LE(test, fls_result, BITS_PER_LONG); 161b3a7bb71SKees Cook } 162b3a7bb71SKees Cook 163b3a7bb71SKees Cook /* 164b3a7bb71SKees Cook * Helper function to validate 64-bit relationships 165b3a7bb71SKees Cook */ 166b3a7bb71SKees Cook static void validate_ffs64_relationships(struct kunit *test, u64 input) 167b3a7bb71SKees Cook { 168b3a7bb71SKees Cook int fls64_result; 169b3a7bb71SKees Cook unsigned int ffs64_0based; 170b3a7bb71SKees Cook 171b3a7bb71SKees Cook if (input == 0) { 172b3a7bb71SKees Cook KUNIT_EXPECT_EQ(test, fls64(input), 0); 173b3a7bb71SKees Cook return; 174b3a7bb71SKees Cook } 175b3a7bb71SKees Cook 176b3a7bb71SKees Cook fls64_result = fls64(input); 177b3a7bb71SKees Cook ffs64_0based = __ffs64(input); 178b3a7bb71SKees Cook 179b3a7bb71SKees Cook /* Range validation */ 180b3a7bb71SKees Cook KUNIT_EXPECT_GE(test, fls64_result, 1); 181b3a7bb71SKees Cook KUNIT_EXPECT_LE(test, fls64_result, 64); 182b3a7bb71SKees Cook KUNIT_EXPECT_LT(test, ffs64_0based, 64); 183b3a7bb71SKees Cook 184b3a7bb71SKees Cook /* 185b3a7bb71SKees Cook * Relationships with 32-bit functions should hold for small values 186b3a7bb71SKees Cook * on all architectures. 187b3a7bb71SKees Cook */ 188b3a7bb71SKees Cook if (input <= 0xFFFFFFFFULL) { 189b3a7bb71SKees Cook unsigned long input_32 = (unsigned long)input; 190b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, fls64(input), fls(input_32), 191b3a7bb71SKees Cook "fls64(0x%llx) != fls(0x%lx): %d != %d", 192b3a7bb71SKees Cook input, input_32, fls64(input), fls(input_32)); 193b3a7bb71SKees Cook 194b3a7bb71SKees Cook if (input != 0) { 195b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, __ffs64(input), __ffs(input_32), 196b3a7bb71SKees Cook "__ffs64(0x%llx) != __ffs(0x%lx): %lu != %lu", 197b3a7bb71SKees Cook input, input_32, 198b3a7bb71SKees Cook (unsigned long)__ffs64(input), 199b3a7bb71SKees Cook (unsigned long)__ffs(input_32)); 200b3a7bb71SKees Cook } 201b3a7bb71SKees Cook } 202b3a7bb71SKees Cook } 203b3a7bb71SKees Cook 204b3a7bb71SKees Cook /* 205b3a7bb71SKees Cook * Test basic correctness of all ffs-family functions 206b3a7bb71SKees Cook */ 207b3a7bb71SKees Cook static void ffs_basic_correctness_test(struct kunit *test) 208b3a7bb71SKees Cook { 209b3a7bb71SKees Cook int i; 210b3a7bb71SKees Cook 211b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(basic_test_cases); i++) { 212b3a7bb71SKees Cook const struct ffs_test_case *tc = &basic_test_cases[i]; 213b3a7bb71SKees Cook 214b3a7bb71SKees Cook /* Test ffs() */ 215b3a7bb71SKees Cook validate_ffs_result(test, tc->input, ffs(tc->input), 216b3a7bb71SKees Cook tc->expected_ffs, "ffs", tc->description); 217b3a7bb71SKees Cook 218b3a7bb71SKees Cook /* Test fls() */ 219b3a7bb71SKees Cook validate_ffs_result(test, tc->input, fls(tc->input), 220b3a7bb71SKees Cook tc->expected_fls, "fls", tc->description); 221b3a7bb71SKees Cook 222b3a7bb71SKees Cook /* Test __ffs() - skip zero case as it's undefined */ 223b3a7bb71SKees Cook if (tc->input != 0) { 224b3a7bb71SKees Cook /* Calculate expected __ffs() result: __ffs(x) == ffs(x) - 1 */ 225b3a7bb71SKees Cook unsigned int expected_ffs_0based = tc->expected_ffs - 1; 226b3a7bb71SKees Cook validate_ffs_result(test, tc->input, __ffs(tc->input), 227b3a7bb71SKees Cook expected_ffs_0based, "__ffs", tc->description); 228b3a7bb71SKees Cook } 229b3a7bb71SKees Cook 230b3a7bb71SKees Cook /* Test __fls() - skip zero case as it's undefined */ 231b3a7bb71SKees Cook if (tc->input != 0) { 232b3a7bb71SKees Cook /* Calculate expected __fls() result: __fls(x) == fls(x) - 1 */ 233b3a7bb71SKees Cook unsigned int expected_fls_0based = tc->expected_fls - 1; 234b3a7bb71SKees Cook validate_ffs_result(test, tc->input, __fls(tc->input), 235b3a7bb71SKees Cook expected_fls_0based, "__fls", tc->description); 236b3a7bb71SKees Cook } 237b3a7bb71SKees Cook } 238b3a7bb71SKees Cook } 239b3a7bb71SKees Cook 240b3a7bb71SKees Cook /* 241b3a7bb71SKees Cook * Test 64-bit function correctness 242b3a7bb71SKees Cook */ 243b3a7bb71SKees Cook static void ffs64_correctness_test(struct kunit *test) 244b3a7bb71SKees Cook { 245b3a7bb71SKees Cook int i; 246b3a7bb71SKees Cook 247b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(ffs64_test_cases); i++) { 248b3a7bb71SKees Cook const struct ffs64_test_case *tc = &ffs64_test_cases[i]; 249b3a7bb71SKees Cook 250b3a7bb71SKees Cook /* Test fls64() */ 251b3a7bb71SKees Cook validate_ffs64_result(test, tc->input, fls64(tc->input), 252b3a7bb71SKees Cook tc->expected_fls64, "fls64", tc->description); 253b3a7bb71SKees Cook 254b3a7bb71SKees Cook /* Test __ffs64() - skip zero case as it's undefined */ 255b3a7bb71SKees Cook if (tc->input != 0) { 256b3a7bb71SKees Cook validate_ffs64_result(test, tc->input, __ffs64(tc->input), 257b3a7bb71SKees Cook tc->expected_ffs64_0based, "__ffs64", 258b3a7bb71SKees Cook tc->description); 259b3a7bb71SKees Cook } 260b3a7bb71SKees Cook } 261b3a7bb71SKees Cook } 262b3a7bb71SKees Cook 263b3a7bb71SKees Cook /* 264b3a7bb71SKees Cook * Test mathematical relationships between functions 265b3a7bb71SKees Cook */ 266b3a7bb71SKees Cook static void ffs_mathematical_relationships_test(struct kunit *test) 267b3a7bb71SKees Cook { 268b3a7bb71SKees Cook int i; 269b3a7bb71SKees Cook 270b3a7bb71SKees Cook /* Test basic cases */ 271b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(basic_test_cases); i++) { 272b3a7bb71SKees Cook validate_ffs_relationships(test, basic_test_cases[i].input); 273b3a7bb71SKees Cook } 274b3a7bb71SKees Cook 275b3a7bb71SKees Cook /* Test 64-bit cases */ 276b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(ffs64_test_cases); i++) { 277b3a7bb71SKees Cook validate_ffs64_relationships(test, ffs64_test_cases[i].input); 278b3a7bb71SKees Cook } 279b3a7bb71SKees Cook } 280b3a7bb71SKees Cook 281b3a7bb71SKees Cook /* 282b3a7bb71SKees Cook * Test edge cases and boundary conditions 283b3a7bb71SKees Cook */ 284b3a7bb71SKees Cook static void ffs_edge_cases_test(struct kunit *test) 285b3a7bb71SKees Cook { 286b3a7bb71SKees Cook unsigned long test_patterns[] = { 287b3a7bb71SKees Cook /* Powers of 2 */ 288b3a7bb71SKees Cook 1UL, 2UL, 4UL, 8UL, 16UL, 32UL, 64UL, 128UL, 289b3a7bb71SKees Cook 256UL, 512UL, 1024UL, 2048UL, 4096UL, 8192UL, 290b3a7bb71SKees Cook 291b3a7bb71SKees Cook /* Powers of 2 minus 1 */ 292b3a7bb71SKees Cook 1UL, 3UL, 7UL, 15UL, 31UL, 63UL, 127UL, 255UL, 293b3a7bb71SKees Cook 511UL, 1023UL, 2047UL, 4095UL, 8191UL, 294b3a7bb71SKees Cook 295b3a7bb71SKees Cook /* Boundary values */ 296b3a7bb71SKees Cook 0x7FFFFFFFUL, /* Maximum positive 32-bit */ 297b3a7bb71SKees Cook 0x80000000UL, /* Minimum negative 32-bit */ 298b3a7bb71SKees Cook 0xFFFFFFFFUL, /* Maximum 32-bit unsigned */ 299b3a7bb71SKees Cook }; 300b3a7bb71SKees Cook int i; 301b3a7bb71SKees Cook 302b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(test_patterns); i++) { 303b3a7bb71SKees Cook validate_ffs_relationships(test, test_patterns[i]); 304b3a7bb71SKees Cook } 305b3a7bb71SKees Cook } 306b3a7bb71SKees Cook 307b3a7bb71SKees Cook /* 308b3a7bb71SKees Cook * Test 64-bit edge cases 309b3a7bb71SKees Cook */ 310b3a7bb71SKees Cook static void ffs64_edge_cases_test(struct kunit *test) 311b3a7bb71SKees Cook { 312b3a7bb71SKees Cook u64 test_patterns_64[] = { 313b3a7bb71SKees Cook /* 64-bit powers of 2 */ 314b3a7bb71SKees Cook 0x0000000100000000ULL, /* 2^32 */ 315b3a7bb71SKees Cook 0x0000000200000000ULL, /* 2^33 */ 316b3a7bb71SKees Cook 0x0000000400000000ULL, /* 2^34 */ 317b3a7bb71SKees Cook 0x0000001000000000ULL, /* 2^36 */ 318b3a7bb71SKees Cook 0x0000010000000000ULL, /* 2^40 */ 319b3a7bb71SKees Cook 0x0001000000000000ULL, /* 2^48 */ 320b3a7bb71SKees Cook 0x0100000000000000ULL, /* 2^56 */ 321b3a7bb71SKees Cook 0x4000000000000000ULL, /* 2^62 */ 322b3a7bb71SKees Cook 0x8000000000000000ULL, /* 2^63 */ 323b3a7bb71SKees Cook 324b3a7bb71SKees Cook /* Cross-boundary patterns */ 325b3a7bb71SKees Cook 0x00000000FFFFFFFFULL, /* Lower 32 bits */ 326b3a7bb71SKees Cook 0xFFFFFFFF00000000ULL, /* Upper 32 bits */ 327b3a7bb71SKees Cook 0x7FFFFFFFFFFFFFFFULL, /* Maximum positive 64-bit */ 328b3a7bb71SKees Cook 0xFFFFFFFFFFFFFFFFULL, /* Maximum 64-bit unsigned */ 329b3a7bb71SKees Cook }; 330b3a7bb71SKees Cook int i; 331b3a7bb71SKees Cook 332b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(test_patterns_64); i++) { 333b3a7bb71SKees Cook validate_ffs64_relationships(test, test_patterns_64[i]); 334b3a7bb71SKees Cook } 335b3a7bb71SKees Cook } 336b3a7bb71SKees Cook 337b3a7bb71SKees Cook /* 338b3a7bb71SKees Cook * ffz() test data - Find First Zero bit test cases 339b3a7bb71SKees Cook */ 340b3a7bb71SKees Cook struct ffz_test_case { 341b3a7bb71SKees Cook unsigned long input; 342b3a7bb71SKees Cook unsigned long expected_ffz; 343b3a7bb71SKees Cook const char *description; 344b3a7bb71SKees Cook }; 345b3a7bb71SKees Cook 346b3a7bb71SKees Cook static const struct ffz_test_case ffz_test_cases[] = { 347b3a7bb71SKees Cook /* Zero bits in specific positions */ 348b3a7bb71SKees Cook {0xFFFFFFFE, 0, "bit 0 is zero"}, /* ...11111110 */ 349b3a7bb71SKees Cook {0xFFFFFFFD, 1, "bit 1 is zero"}, /* ...11111101 */ 350b3a7bb71SKees Cook {0xFFFFFFFB, 2, "bit 2 is zero"}, /* ...11111011 */ 351b3a7bb71SKees Cook {0xFFFFFFF7, 3, "bit 3 is zero"}, /* ...11110111 */ 352b3a7bb71SKees Cook {0xFFFFFFEF, 4, "bit 4 is zero"}, /* ...11101111 */ 353b3a7bb71SKees Cook {0xFFFFFFDF, 5, "bit 5 is zero"}, /* ...11011111 */ 354b3a7bb71SKees Cook {0xFFFFFFBF, 6, "bit 6 is zero"}, /* ...10111111 */ 355b3a7bb71SKees Cook {0xFFFFFF7F, 7, "bit 7 is zero"}, /* ...01111111 */ 356b3a7bb71SKees Cook {0xFFFFFEFF, 8, "bit 8 is zero"}, /* Gap in bit 8 */ 357b3a7bb71SKees Cook {0xFFFF7FFF, 15, "bit 15 is zero"}, /* Gap in bit 15 */ 358b3a7bb71SKees Cook {0xFFFEFFFF, 16, "bit 16 is zero"}, /* Gap in bit 16 */ 359b3a7bb71SKees Cook {0xBFFFFFFF, 30, "bit 30 is zero"}, /* Gap in bit 30 */ 360b3a7bb71SKees Cook {0x7FFFFFFF, 31, "bit 31 is zero"}, /* 01111111... */ 361b3a7bb71SKees Cook 362b3a7bb71SKees Cook /* Multiple zero patterns */ 363b3a7bb71SKees Cook {0xFFFFFFFC, 0, "bits 0-1 are zero"}, /* ...11111100 */ 364b3a7bb71SKees Cook {0xFFFFFFF8, 0, "bits 0-2 are zero"}, /* ...11111000 */ 365b3a7bb71SKees Cook {0xFFFFFFF0, 0, "bits 0-3 are zero"}, /* ...11110000 */ 366b3a7bb71SKees Cook {0xFFFFFF00, 0, "bits 0-7 are zero"}, /* ...00000000 */ 367b3a7bb71SKees Cook {0xFFFF0000, 0, "bits 0-15 are zero"}, /* Lower 16 bits zero */ 368b3a7bb71SKees Cook 369b3a7bb71SKees Cook /* All zeros (special case) */ 370b3a7bb71SKees Cook {0x00000000, 0, "all bits zero"}, 371b3a7bb71SKees Cook 372b3a7bb71SKees Cook /* Complex patterns */ 373b3a7bb71SKees Cook {0xFFFDFFFF, 17, "bit 17 is zero"}, /* Gap in bit 17 */ 374b3a7bb71SKees Cook {0xFFF7FFFF, 19, "bit 19 is zero"}, /* Gap in bit 19 */ 375b3a7bb71SKees Cook {0xF7FFFFFF, 27, "bit 27 is zero"}, /* Gap in bit 27 */ 376b3a7bb71SKees Cook {0xDFFFFFFF, 29, "bit 29 is zero"}, /* Gap in bit 29 */ 377b3a7bb71SKees Cook }; 378b3a7bb71SKees Cook 379b3a7bb71SKees Cook /* 380b3a7bb71SKees Cook * Test basic correctness of ffz() function 381b3a7bb71SKees Cook */ 382b3a7bb71SKees Cook static void ffz_basic_correctness_test(struct kunit *test) 383b3a7bb71SKees Cook { 384b3a7bb71SKees Cook int i; 385b3a7bb71SKees Cook 386b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(ffz_test_cases); i++) { 387b3a7bb71SKees Cook const struct ffz_test_case *tc = &ffz_test_cases[i]; 388b3a7bb71SKees Cook unsigned long result = ffz(tc->input); 389b3a7bb71SKees Cook 390b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, result, tc->expected_ffz, 391b3a7bb71SKees Cook "ffz(0x%08lx) [%s]: expected %lu, got %lu", 392b3a7bb71SKees Cook tc->input, tc->description, tc->expected_ffz, result); 393b3a7bb71SKees Cook } 394b3a7bb71SKees Cook } 395b3a7bb71SKees Cook 396b3a7bb71SKees Cook /* 397b3a7bb71SKees Cook * Test mathematical relationships between ffz() and other functions 398b3a7bb71SKees Cook */ 399b3a7bb71SKees Cook static void validate_ffz_relationships(struct kunit *test, unsigned long input) 400b3a7bb71SKees Cook { 401b3a7bb71SKees Cook unsigned long ffz_result; 402b3a7bb71SKees Cook 403b3a7bb71SKees Cook if (input == 0) { 404b3a7bb71SKees Cook /* ffz(0) should return 0 (first zero bit is at position 0) */ 405b3a7bb71SKees Cook KUNIT_EXPECT_EQ(test, ffz(input), 0); 406b3a7bb71SKees Cook return; 407b3a7bb71SKees Cook } 408b3a7bb71SKees Cook 409b3a7bb71SKees Cook if (input == ~0UL) { 410b3a7bb71SKees Cook /* ffz(~0) is undefined (no zero bits) - just verify it doesn't crash */ 411b3a7bb71SKees Cook ffz_result = ffz(input); 412b3a7bb71SKees Cook /* Implementation-defined behavior, just ensure it completes */ 413b3a7bb71SKees Cook return; 414b3a7bb71SKees Cook } 415b3a7bb71SKees Cook 416b3a7bb71SKees Cook ffz_result = ffz(input); 417b3a7bb71SKees Cook 418b3a7bb71SKees Cook /* Range validation - result should be within valid bit range */ 419b3a7bb71SKees Cook KUNIT_EXPECT_LT(test, ffz_result, BITS_PER_LONG); 420b3a7bb71SKees Cook 421b3a7bb71SKees Cook /* Verify the bit at ffz_result position is actually zero */ 422b3a7bb71SKees Cook KUNIT_EXPECT_EQ_MSG(test, (input >> ffz_result) & 1, 0, 423b3a7bb71SKees Cook "ffz(0x%08lx) = %lu, but bit %lu is not zero", 424b3a7bb71SKees Cook input, ffz_result, ffz_result); 425b3a7bb71SKees Cook 426b3a7bb71SKees Cook /* Core relationship: if we set the ffz bit, ffz should find a different bit */ 427b3a7bb71SKees Cook if (ffz_result < BITS_PER_LONG - 1) { 428b3a7bb71SKees Cook unsigned long modified = input | (1UL << ffz_result); 429b3a7bb71SKees Cook if (modified != ~0UL) { /* Skip if all bits would be set */ 430b3a7bb71SKees Cook unsigned long new_ffz = ffz(modified); 431b3a7bb71SKees Cook KUNIT_EXPECT_NE_MSG(test, new_ffz, ffz_result, 432b3a7bb71SKees Cook "ffz(0x%08lx) = %lu, but setting that bit doesn't change ffz result", 433b3a7bb71SKees Cook input, ffz_result); 434b3a7bb71SKees Cook } 435b3a7bb71SKees Cook } 436b3a7bb71SKees Cook } 437b3a7bb71SKees Cook 438b3a7bb71SKees Cook static void ffz_mathematical_relationships_test(struct kunit *test) 439b3a7bb71SKees Cook { 440b3a7bb71SKees Cook unsigned long test_patterns[] = { 441b3a7bb71SKees Cook /* Powers of 2 with one bit clear */ 442b3a7bb71SKees Cook 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7, 443b3a7bb71SKees Cook 0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F, 444b3a7bb71SKees Cook 445b3a7bb71SKees Cook /* Multiple patterns */ 446b3a7bb71SKees Cook 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000, 447b3a7bb71SKees Cook 0x7FFFFFFF, 0x3FFFFFFF, 0x1FFFFFFF, 0x0FFFFFFF, 448b3a7bb71SKees Cook 449b3a7bb71SKees Cook /* Complex bit patterns */ 450b3a7bb71SKees Cook 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 451b3a7bb71SKees Cook 0xF0F0F0F0, 0x0F0F0F0F, 0xFF00FF00, 0x00FF00FF, 452b3a7bb71SKees Cook }; 453b3a7bb71SKees Cook int i; 454b3a7bb71SKees Cook 455b3a7bb71SKees Cook /* Test basic test cases */ 456b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(ffz_test_cases); i++) { 457b3a7bb71SKees Cook validate_ffz_relationships(test, ffz_test_cases[i].input); 458b3a7bb71SKees Cook } 459b3a7bb71SKees Cook 460b3a7bb71SKees Cook /* Test additional patterns */ 461b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(test_patterns); i++) { 462b3a7bb71SKees Cook validate_ffz_relationships(test, test_patterns[i]); 463b3a7bb71SKees Cook } 464b3a7bb71SKees Cook } 465b3a7bb71SKees Cook 466b3a7bb71SKees Cook /* 467b3a7bb71SKees Cook * Test edge cases and boundary conditions for ffz() 468b3a7bb71SKees Cook */ 469b3a7bb71SKees Cook static void ffz_edge_cases_test(struct kunit *test) 470b3a7bb71SKees Cook { 471b3a7bb71SKees Cook unsigned long edge_patterns[] = { 472b3a7bb71SKees Cook /* Boundary values */ 473b3a7bb71SKees Cook 0x00000000, /* All zeros */ 474b3a7bb71SKees Cook 0x80000000, /* Only MSB set */ 475b3a7bb71SKees Cook 0x00000001, /* Only LSB set */ 476b3a7bb71SKees Cook 0x7FFFFFFF, /* MSB clear */ 477b3a7bb71SKees Cook 0xFFFFFFFE, /* LSB clear */ 478b3a7bb71SKees Cook 479b3a7bb71SKees Cook /* Powers of 2 complement patterns (one zero bit each) */ 480b3a7bb71SKees Cook ~(1UL << 0), ~(1UL << 1), ~(1UL << 2), ~(1UL << 3), 481b3a7bb71SKees Cook ~(1UL << 4), ~(1UL << 8), ~(1UL << 16), ~(1UL << 31), 482b3a7bb71SKees Cook 483b3a7bb71SKees Cook /* Walking zero patterns */ 484b3a7bb71SKees Cook 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7, 485b3a7bb71SKees Cook 0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F, 486b3a7bb71SKees Cook 0xFFFFFEFF, 0xFFFFFDFF, 0xFFFFFBFF, 0xFFFFF7FF, 487b3a7bb71SKees Cook 488b3a7bb71SKees Cook /* Multiple zeros */ 489b3a7bb71SKees Cook 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000, 490b3a7bb71SKees Cook 0xFF000000, 0xF0000000, 0x00000000, 491b3a7bb71SKees Cook }; 492b3a7bb71SKees Cook int i; 493b3a7bb71SKees Cook 494b3a7bb71SKees Cook for (i = 0; i < ARRAY_SIZE(edge_patterns); i++) { 495b3a7bb71SKees Cook validate_ffz_relationships(test, edge_patterns[i]); 496b3a7bb71SKees Cook } 497b3a7bb71SKees Cook } 498b3a7bb71SKees Cook 499b3a7bb71SKees Cook /* 500*95719dfaSKees Cook * To have useful build error output, split the tests into separate 501*95719dfaSKees Cook * functions so it's clear which are missing __attribute_const__. 502*95719dfaSKees Cook */ 503*95719dfaSKees Cook #define CREATE_WRAPPER(func) \ 504*95719dfaSKees Cook static noinline bool build_test_##func(void) \ 505*95719dfaSKees Cook { \ 506*95719dfaSKees Cook int init_##func = 32; \ 507*95719dfaSKees Cook int result_##func = func(6); \ 508*95719dfaSKees Cook \ 509*95719dfaSKees Cook /* Does the static initializer vanish after calling func? */ \ 510*95719dfaSKees Cook BUILD_BUG_ON(init_##func < 32); \ 511*95719dfaSKees Cook \ 512*95719dfaSKees Cook /* "Consume" the results so optimizer doesn't drop them. */ \ 513*95719dfaSKees Cook barrier_data(&init_##func); \ 514*95719dfaSKees Cook barrier_data(&result_##func); \ 515*95719dfaSKees Cook \ 516*95719dfaSKees Cook return true; \ 517*95719dfaSKees Cook } 518*95719dfaSKees Cook CREATE_WRAPPER(ffs) 519*95719dfaSKees Cook CREATE_WRAPPER(fls) 520*95719dfaSKees Cook CREATE_WRAPPER(__ffs) 521*95719dfaSKees Cook CREATE_WRAPPER(__fls) 522*95719dfaSKees Cook CREATE_WRAPPER(ffz) 523*95719dfaSKees Cook #undef CREATE_WRAPPER 524*95719dfaSKees Cook 525*95719dfaSKees Cook /* 526*95719dfaSKees Cook * Make sure that __attribute_const__ has be applied to all the 527*95719dfaSKees Cook * functions. This is a regression test for: 528*95719dfaSKees Cook * https://github.com/KSPP/linux/issues/364 529*95719dfaSKees Cook */ 530*95719dfaSKees Cook static void ffs_attribute_const_test(struct kunit *test) 531*95719dfaSKees Cook { 532*95719dfaSKees Cook KUNIT_EXPECT_TRUE(test, build_test_ffs()); 533*95719dfaSKees Cook KUNIT_EXPECT_TRUE(test, build_test_fls()); 534*95719dfaSKees Cook KUNIT_EXPECT_TRUE(test, build_test___ffs()); 535*95719dfaSKees Cook KUNIT_EXPECT_TRUE(test, build_test___fls()); 536*95719dfaSKees Cook KUNIT_EXPECT_TRUE(test, build_test_ffz()); 537*95719dfaSKees Cook } 538*95719dfaSKees Cook 539*95719dfaSKees Cook /* 540b3a7bb71SKees Cook * KUnit test case definitions 541b3a7bb71SKees Cook */ 542b3a7bb71SKees Cook static struct kunit_case ffs_test_cases[] = { 543b3a7bb71SKees Cook KUNIT_CASE(ffs_basic_correctness_test), 544b3a7bb71SKees Cook KUNIT_CASE(ffs64_correctness_test), 545b3a7bb71SKees Cook KUNIT_CASE(ffs_mathematical_relationships_test), 546b3a7bb71SKees Cook KUNIT_CASE(ffs_edge_cases_test), 547b3a7bb71SKees Cook KUNIT_CASE(ffs64_edge_cases_test), 548b3a7bb71SKees Cook KUNIT_CASE(ffz_basic_correctness_test), 549b3a7bb71SKees Cook KUNIT_CASE(ffz_mathematical_relationships_test), 550b3a7bb71SKees Cook KUNIT_CASE(ffz_edge_cases_test), 551b3a7bb71SKees Cook KUNIT_CASE(ffs_attribute_const_test), 552b3a7bb71SKees Cook {} 553b3a7bb71SKees Cook }; 554b3a7bb71SKees Cook 555b3a7bb71SKees Cook /* 556b3a7bb71SKees Cook * KUnit test suite definition 557b3a7bb71SKees Cook */ 558b3a7bb71SKees Cook static struct kunit_suite ffs_test_suite = { 559b3a7bb71SKees Cook .name = "ffs", 560b3a7bb71SKees Cook .test_cases = ffs_test_cases, 561b3a7bb71SKees Cook }; 562b3a7bb71SKees Cook 563b3a7bb71SKees Cook kunit_test_suites(&ffs_test_suite); 564b3a7bb71SKees Cook 565b3a7bb71SKees Cook MODULE_DESCRIPTION("KUnit tests for ffs()-family functions"); 566b3a7bb71SKees Cook MODULE_LICENSE("GPL"); 567