109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25fd003f5SDavid Decotigny /*
3780ff33bSAndy Shevchenko * Test cases for bitmap API.
45fd003f5SDavid Decotigny */
55fd003f5SDavid Decotigny
65fd003f5SDavid Decotigny #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
75fd003f5SDavid Decotigny
85fd003f5SDavid Decotigny #include <linux/bitmap.h>
95fd003f5SDavid Decotigny #include <linux/init.h>
105fd003f5SDavid Decotigny #include <linux/kernel.h>
115fd003f5SDavid Decotigny #include <linux/module.h>
125fd003f5SDavid Decotigny #include <linux/printk.h>
135fd003f5SDavid Decotigny #include <linux/slab.h>
145fd003f5SDavid Decotigny #include <linux/string.h>
156ea86bdfSYury Norov #include <linux/uaccess.h>
165fd003f5SDavid Decotigny
176b1a4d5bSTobin C. Harding #include "../tools/testing/selftests/kselftest_module.h"
186b1a4d5bSTobin C. Harding
19e3783c80SYury Norov #define EXP1_IN_BITS (sizeof(exp1) * 8)
20e3783c80SYury Norov
214e89a787STimur Tabi KSTM_MODULE_GLOBALS();
225fd003f5SDavid Decotigny
235fd003f5SDavid Decotigny static char pbl_buffer[PAGE_SIZE] __initdata;
24291f93caSBarry Song static char print_buf[PAGE_SIZE * 2] __initdata;
255fd003f5SDavid Decotigny
26c21dd8a7SAndy Shevchenko static const unsigned long exp1[] __initconst = {
27c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(1),
28c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(2),
29c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x0000ffff),
30c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xffff0000),
31c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x55555555),
32c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xaaaaaaaa),
33c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x11111111),
34c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x22222222),
35c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xffffffff),
36c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xfffffffe),
37c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x3333333311111111ULL),
38c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xffffffff77777777ULL),
39c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0),
4097330db3SPaul Gortmaker BITMAP_FROM_U64(0x00008000),
4197330db3SPaul Gortmaker BITMAP_FROM_U64(0x80000000),
42c21dd8a7SAndy Shevchenko };
43c21dd8a7SAndy Shevchenko
44c21dd8a7SAndy Shevchenko static const unsigned long exp2[] __initconst = {
45c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0x3333333311111111ULL),
46c21dd8a7SAndy Shevchenko BITMAP_FROM_U64(0xffffffff77777777ULL),
47c21dd8a7SAndy Shevchenko };
485fd003f5SDavid Decotigny
4930544ed5SAndy Shevchenko /* Fibonacci sequence */
5030544ed5SAndy Shevchenko static const unsigned long exp2_to_exp3_mask[] __initconst = {
5130544ed5SAndy Shevchenko BITMAP_FROM_U64(0x008000020020212eULL),
5230544ed5SAndy Shevchenko };
5330544ed5SAndy Shevchenko /* exp3_0_1 = (exp2[0] & ~exp2_to_exp3_mask) | (exp2[1] & exp2_to_exp3_mask) */
5430544ed5SAndy Shevchenko static const unsigned long exp3_0_1[] __initconst = {
5530544ed5SAndy Shevchenko BITMAP_FROM_U64(0x33b3333311313137ULL),
5630544ed5SAndy Shevchenko };
5730544ed5SAndy Shevchenko /* exp3_1_0 = (exp2[1] & ~exp2_to_exp3_mask) | (exp2[0] & exp2_to_exp3_mask) */
5830544ed5SAndy Shevchenko static const unsigned long exp3_1_0[] __initconst = {
5930544ed5SAndy Shevchenko BITMAP_FROM_U64(0xff7fffff77575751ULL),
6030544ed5SAndy Shevchenko };
6130544ed5SAndy Shevchenko
625fd003f5SDavid Decotigny static bool __init
__check_eq_uint(const char * srcfile,unsigned int line,const unsigned int exp_uint,unsigned int x)635fd003f5SDavid Decotigny __check_eq_uint(const char *srcfile, unsigned int line,
645fd003f5SDavid Decotigny const unsigned int exp_uint, unsigned int x)
655fd003f5SDavid Decotigny {
665fd003f5SDavid Decotigny if (exp_uint != x) {
673aa56885SYury Norov pr_err("[%s:%u] expected %u, got %u\n",
685fd003f5SDavid Decotigny srcfile, line, exp_uint, x);
695fd003f5SDavid Decotigny return false;
705fd003f5SDavid Decotigny }
715fd003f5SDavid Decotigny return true;
725fd003f5SDavid Decotigny }
735fd003f5SDavid Decotigny
745fd003f5SDavid Decotigny
755fd003f5SDavid Decotigny static bool __init
__check_eq_bitmap(const char * srcfile,unsigned int line,const unsigned long * exp_bmap,const unsigned long * bmap,unsigned int nbits)765fd003f5SDavid Decotigny __check_eq_bitmap(const char *srcfile, unsigned int line,
773aa56885SYury Norov const unsigned long *exp_bmap, const unsigned long *bmap,
783aa56885SYury Norov unsigned int nbits)
795fd003f5SDavid Decotigny {
805fd003f5SDavid Decotigny if (!bitmap_equal(exp_bmap, bmap, nbits)) {
815fd003f5SDavid Decotigny pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n",
825fd003f5SDavid Decotigny srcfile, line,
833aa56885SYury Norov nbits, exp_bmap, nbits, bmap);
845fd003f5SDavid Decotigny return false;
855fd003f5SDavid Decotigny }
865fd003f5SDavid Decotigny return true;
875fd003f5SDavid Decotigny }
885fd003f5SDavid Decotigny
895fd003f5SDavid Decotigny static bool __init
__check_eq_pbl(const char * srcfile,unsigned int line,const char * expected_pbl,const unsigned long * bitmap,unsigned int nbits)905fd003f5SDavid Decotigny __check_eq_pbl(const char *srcfile, unsigned int line,
915fd003f5SDavid Decotigny const char *expected_pbl,
925fd003f5SDavid Decotigny const unsigned long *bitmap, unsigned int nbits)
935fd003f5SDavid Decotigny {
945fd003f5SDavid Decotigny snprintf(pbl_buffer, sizeof(pbl_buffer), "%*pbl", nbits, bitmap);
955fd003f5SDavid Decotigny if (strcmp(expected_pbl, pbl_buffer)) {
965fd003f5SDavid Decotigny pr_warn("[%s:%u] expected \"%s\", got \"%s\"\n",
975fd003f5SDavid Decotigny srcfile, line,
985fd003f5SDavid Decotigny expected_pbl, pbl_buffer);
995fd003f5SDavid Decotigny return false;
1005fd003f5SDavid Decotigny }
1015fd003f5SDavid Decotigny return true;
1025fd003f5SDavid Decotigny }
1035fd003f5SDavid Decotigny
1045fd003f5SDavid Decotigny static bool __init
1055fd003f5SDavid Decotigny __check_eq_u32_array(const char *srcfile, unsigned int line,
1065fd003f5SDavid Decotigny const u32 *exp_arr, unsigned int exp_len,
1073aa56885SYury Norov const u32 *arr, unsigned int len) __used;
1083aa56885SYury Norov static bool __init
__check_eq_u32_array(const char * srcfile,unsigned int line,const u32 * exp_arr,unsigned int exp_len,const u32 * arr,unsigned int len)1093aa56885SYury Norov __check_eq_u32_array(const char *srcfile, unsigned int line,
1103aa56885SYury Norov const u32 *exp_arr, unsigned int exp_len,
1115fd003f5SDavid Decotigny const u32 *arr, unsigned int len)
1125fd003f5SDavid Decotigny {
1135fd003f5SDavid Decotigny if (exp_len != len) {
1145fd003f5SDavid Decotigny pr_warn("[%s:%u] array length differ: expected %u, got %u\n",
1155fd003f5SDavid Decotigny srcfile, line,
1165fd003f5SDavid Decotigny exp_len, len);
1175fd003f5SDavid Decotigny return false;
1185fd003f5SDavid Decotigny }
1195fd003f5SDavid Decotigny
1205fd003f5SDavid Decotigny if (memcmp(exp_arr, arr, len*sizeof(*arr))) {
1215fd003f5SDavid Decotigny pr_warn("[%s:%u] array contents differ\n", srcfile, line);
1225fd003f5SDavid Decotigny print_hex_dump(KERN_WARNING, " exp: ", DUMP_PREFIX_OFFSET,
1235fd003f5SDavid Decotigny 32, 4, exp_arr, exp_len*sizeof(*exp_arr), false);
1245fd003f5SDavid Decotigny print_hex_dump(KERN_WARNING, " got: ", DUMP_PREFIX_OFFSET,
1255fd003f5SDavid Decotigny 32, 4, arr, len*sizeof(*arr), false);
1265fd003f5SDavid Decotigny return false;
1275fd003f5SDavid Decotigny }
1285fd003f5SDavid Decotigny
1295fd003f5SDavid Decotigny return true;
1305fd003f5SDavid Decotigny }
1315fd003f5SDavid Decotigny
__check_eq_clump8(const char * srcfile,unsigned int line,const unsigned int offset,const unsigned int size,const unsigned char * const clump_exp,const unsigned long * const clump)132e4aa168dSWilliam Breathitt Gray static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,
133e4aa168dSWilliam Breathitt Gray const unsigned int offset,
134e4aa168dSWilliam Breathitt Gray const unsigned int size,
135e4aa168dSWilliam Breathitt Gray const unsigned char *const clump_exp,
136e4aa168dSWilliam Breathitt Gray const unsigned long *const clump)
137e4aa168dSWilliam Breathitt Gray {
138e4aa168dSWilliam Breathitt Gray unsigned long exp;
139e4aa168dSWilliam Breathitt Gray
140e4aa168dSWilliam Breathitt Gray if (offset >= size) {
141e4aa168dSWilliam Breathitt Gray pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected less than %u, got %u\n",
142e4aa168dSWilliam Breathitt Gray srcfile, line, size, offset);
143e4aa168dSWilliam Breathitt Gray return false;
144e4aa168dSWilliam Breathitt Gray }
145e4aa168dSWilliam Breathitt Gray
146e4aa168dSWilliam Breathitt Gray exp = clump_exp[offset / 8];
147e4aa168dSWilliam Breathitt Gray if (!exp) {
148e4aa168dSWilliam Breathitt Gray pr_warn("[%s:%u] bit offset for zero clump: expected nonzero clump, got bit offset %u with clump value 0",
149e4aa168dSWilliam Breathitt Gray srcfile, line, offset);
150e4aa168dSWilliam Breathitt Gray return false;
151e4aa168dSWilliam Breathitt Gray }
152e4aa168dSWilliam Breathitt Gray
153e4aa168dSWilliam Breathitt Gray if (*clump != exp) {
154e4aa168dSWilliam Breathitt Gray pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value of 0x%lX",
155e4aa168dSWilliam Breathitt Gray srcfile, line, exp, *clump);
156e4aa168dSWilliam Breathitt Gray return false;
157e4aa168dSWilliam Breathitt Gray }
158e4aa168dSWilliam Breathitt Gray
159e4aa168dSWilliam Breathitt Gray return true;
160e4aa168dSWilliam Breathitt Gray }
161e4aa168dSWilliam Breathitt Gray
162291f93caSBarry Song static bool __init
__check_eq_str(const char * srcfile,unsigned int line,const char * exp_str,const char * str,unsigned int len)163291f93caSBarry Song __check_eq_str(const char *srcfile, unsigned int line,
164291f93caSBarry Song const char *exp_str, const char *str,
165291f93caSBarry Song unsigned int len)
166291f93caSBarry Song {
167291f93caSBarry Song bool eq;
168291f93caSBarry Song
169291f93caSBarry Song eq = strncmp(exp_str, str, len) == 0;
170291f93caSBarry Song if (!eq)
171291f93caSBarry Song pr_err("[%s:%u] expected %s, got %s\n", srcfile, line, exp_str, str);
172291f93caSBarry Song
173291f93caSBarry Song return eq;
174291f93caSBarry Song }
175291f93caSBarry Song
1765fd003f5SDavid Decotigny #define __expect_eq(suffix, ...) \
1775fd003f5SDavid Decotigny ({ \
1785fd003f5SDavid Decotigny int result = 0; \
1795fd003f5SDavid Decotigny total_tests++; \
1805fd003f5SDavid Decotigny if (!__check_eq_ ## suffix(__FILE__, __LINE__, \
1815fd003f5SDavid Decotigny ##__VA_ARGS__)) { \
1825fd003f5SDavid Decotigny failed_tests++; \
1835fd003f5SDavid Decotigny result = 1; \
1845fd003f5SDavid Decotigny } \
1855fd003f5SDavid Decotigny result; \
1865fd003f5SDavid Decotigny })
1875fd003f5SDavid Decotigny
1885fd003f5SDavid Decotigny #define expect_eq_uint(...) __expect_eq(uint, ##__VA_ARGS__)
1895fd003f5SDavid Decotigny #define expect_eq_bitmap(...) __expect_eq(bitmap, ##__VA_ARGS__)
1905fd003f5SDavid Decotigny #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
1915fd003f5SDavid Decotigny #define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__)
192e4aa168dSWilliam Breathitt Gray #define expect_eq_clump8(...) __expect_eq(clump8, ##__VA_ARGS__)
193291f93caSBarry Song #define expect_eq_str(...) __expect_eq(str, ##__VA_ARGS__)
1945fd003f5SDavid Decotigny
test_zero_clear(void)195ee3527bdSAndy Shevchenko static void __init test_zero_clear(void)
196ee3527bdSAndy Shevchenko {
197ee3527bdSAndy Shevchenko DECLARE_BITMAP(bmap, 1024);
198ee3527bdSAndy Shevchenko
199ee3527bdSAndy Shevchenko /* Known way to set all bits */
200ee3527bdSAndy Shevchenko memset(bmap, 0xff, 128);
201ee3527bdSAndy Shevchenko
202ee3527bdSAndy Shevchenko expect_eq_pbl("0-22", bmap, 23);
203ee3527bdSAndy Shevchenko expect_eq_pbl("0-1023", bmap, 1024);
204ee3527bdSAndy Shevchenko
205ee3527bdSAndy Shevchenko /* single-word bitmaps */
206ee3527bdSAndy Shevchenko bitmap_clear(bmap, 0, 9);
207ee3527bdSAndy Shevchenko expect_eq_pbl("9-1023", bmap, 1024);
208ee3527bdSAndy Shevchenko
209ee3527bdSAndy Shevchenko bitmap_zero(bmap, 35);
210ee3527bdSAndy Shevchenko expect_eq_pbl("64-1023", bmap, 1024);
211ee3527bdSAndy Shevchenko
212ee3527bdSAndy Shevchenko /* cross boundaries operations */
213ee3527bdSAndy Shevchenko bitmap_clear(bmap, 79, 19);
214ee3527bdSAndy Shevchenko expect_eq_pbl("64-78,98-1023", bmap, 1024);
215ee3527bdSAndy Shevchenko
216ee3527bdSAndy Shevchenko bitmap_zero(bmap, 115);
217ee3527bdSAndy Shevchenko expect_eq_pbl("128-1023", bmap, 1024);
218ee3527bdSAndy Shevchenko
219ee3527bdSAndy Shevchenko /* Zeroing entire area */
220ee3527bdSAndy Shevchenko bitmap_zero(bmap, 1024);
221ee3527bdSAndy Shevchenko expect_eq_pbl("", bmap, 1024);
222ee3527bdSAndy Shevchenko }
223ee3527bdSAndy Shevchenko
test_find_nth_bit(void)224e3783c80SYury Norov static void __init test_find_nth_bit(void)
225e3783c80SYury Norov {
226e3783c80SYury Norov unsigned long b, bit, cnt = 0;
227e3783c80SYury Norov DECLARE_BITMAP(bmap, 64 * 3);
228e3783c80SYury Norov
229e3783c80SYury Norov bitmap_zero(bmap, 64 * 3);
230e3783c80SYury Norov __set_bit(10, bmap);
231e3783c80SYury Norov __set_bit(20, bmap);
232e3783c80SYury Norov __set_bit(30, bmap);
233e3783c80SYury Norov __set_bit(40, bmap);
234e3783c80SYury Norov __set_bit(50, bmap);
235e3783c80SYury Norov __set_bit(60, bmap);
236e3783c80SYury Norov __set_bit(80, bmap);
237e3783c80SYury Norov __set_bit(123, bmap);
238e3783c80SYury Norov
239e3783c80SYury Norov expect_eq_uint(10, find_nth_bit(bmap, 64 * 3, 0));
240e3783c80SYury Norov expect_eq_uint(20, find_nth_bit(bmap, 64 * 3, 1));
241e3783c80SYury Norov expect_eq_uint(30, find_nth_bit(bmap, 64 * 3, 2));
242e3783c80SYury Norov expect_eq_uint(40, find_nth_bit(bmap, 64 * 3, 3));
243e3783c80SYury Norov expect_eq_uint(50, find_nth_bit(bmap, 64 * 3, 4));
244e3783c80SYury Norov expect_eq_uint(60, find_nth_bit(bmap, 64 * 3, 5));
245e3783c80SYury Norov expect_eq_uint(80, find_nth_bit(bmap, 64 * 3, 6));
246e3783c80SYury Norov expect_eq_uint(123, find_nth_bit(bmap, 64 * 3, 7));
247e3783c80SYury Norov expect_eq_uint(64 * 3, find_nth_bit(bmap, 64 * 3, 8));
248e3783c80SYury Norov
249e3783c80SYury Norov expect_eq_uint(10, find_nth_bit(bmap, 64 * 3 - 1, 0));
250e3783c80SYury Norov expect_eq_uint(20, find_nth_bit(bmap, 64 * 3 - 1, 1));
251e3783c80SYury Norov expect_eq_uint(30, find_nth_bit(bmap, 64 * 3 - 1, 2));
252e3783c80SYury Norov expect_eq_uint(40, find_nth_bit(bmap, 64 * 3 - 1, 3));
253e3783c80SYury Norov expect_eq_uint(50, find_nth_bit(bmap, 64 * 3 - 1, 4));
254e3783c80SYury Norov expect_eq_uint(60, find_nth_bit(bmap, 64 * 3 - 1, 5));
255e3783c80SYury Norov expect_eq_uint(80, find_nth_bit(bmap, 64 * 3 - 1, 6));
256e3783c80SYury Norov expect_eq_uint(123, find_nth_bit(bmap, 64 * 3 - 1, 7));
257e3783c80SYury Norov expect_eq_uint(64 * 3 - 1, find_nth_bit(bmap, 64 * 3 - 1, 8));
258e3783c80SYury Norov
259e3783c80SYury Norov for_each_set_bit(bit, exp1, EXP1_IN_BITS) {
260e3783c80SYury Norov b = find_nth_bit(exp1, EXP1_IN_BITS, cnt++);
261e3783c80SYury Norov expect_eq_uint(b, bit);
262e3783c80SYury Norov }
263e3783c80SYury Norov }
264e3783c80SYury Norov
test_fill_set(void)265978f369cSAndy Shevchenko static void __init test_fill_set(void)
266978f369cSAndy Shevchenko {
267978f369cSAndy Shevchenko DECLARE_BITMAP(bmap, 1024);
268978f369cSAndy Shevchenko
269978f369cSAndy Shevchenko /* Known way to clear all bits */
270978f369cSAndy Shevchenko memset(bmap, 0x00, 128);
271978f369cSAndy Shevchenko
272978f369cSAndy Shevchenko expect_eq_pbl("", bmap, 23);
273978f369cSAndy Shevchenko expect_eq_pbl("", bmap, 1024);
274978f369cSAndy Shevchenko
275978f369cSAndy Shevchenko /* single-word bitmaps */
276978f369cSAndy Shevchenko bitmap_set(bmap, 0, 9);
277978f369cSAndy Shevchenko expect_eq_pbl("0-8", bmap, 1024);
278978f369cSAndy Shevchenko
279978f369cSAndy Shevchenko bitmap_fill(bmap, 35);
280978f369cSAndy Shevchenko expect_eq_pbl("0-63", bmap, 1024);
281978f369cSAndy Shevchenko
282978f369cSAndy Shevchenko /* cross boundaries operations */
283978f369cSAndy Shevchenko bitmap_set(bmap, 79, 19);
284978f369cSAndy Shevchenko expect_eq_pbl("0-63,79-97", bmap, 1024);
285978f369cSAndy Shevchenko
286978f369cSAndy Shevchenko bitmap_fill(bmap, 115);
287978f369cSAndy Shevchenko expect_eq_pbl("0-127", bmap, 1024);
288978f369cSAndy Shevchenko
289978f369cSAndy Shevchenko /* Zeroing entire area */
290978f369cSAndy Shevchenko bitmap_fill(bmap, 1024);
291978f369cSAndy Shevchenko expect_eq_pbl("0-1023", bmap, 1024);
292978f369cSAndy Shevchenko }
293978f369cSAndy Shevchenko
test_copy(void)294fe81814cSAndy Shevchenko static void __init test_copy(void)
2955fd003f5SDavid Decotigny {
2965fd003f5SDavid Decotigny DECLARE_BITMAP(bmap1, 1024);
2975fd003f5SDavid Decotigny DECLARE_BITMAP(bmap2, 1024);
2985fd003f5SDavid Decotigny
2995fd003f5SDavid Decotigny bitmap_zero(bmap1, 1024);
3005fd003f5SDavid Decotigny bitmap_zero(bmap2, 1024);
3015fd003f5SDavid Decotigny
3025fd003f5SDavid Decotigny /* single-word bitmaps */
303fe81814cSAndy Shevchenko bitmap_set(bmap1, 0, 19);
3045fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 23);
3055fd003f5SDavid Decotigny expect_eq_pbl("0-18", bmap2, 1024);
3065fd003f5SDavid Decotigny
307fe81814cSAndy Shevchenko bitmap_set(bmap2, 0, 23);
3085fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 23);
3095fd003f5SDavid Decotigny expect_eq_pbl("0-18", bmap2, 1024);
3105fd003f5SDavid Decotigny
3115fd003f5SDavid Decotigny /* multi-word bitmaps */
312fe81814cSAndy Shevchenko bitmap_set(bmap1, 0, 109);
3135fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 1024);
3145fd003f5SDavid Decotigny expect_eq_pbl("0-108", bmap2, 1024);
3155fd003f5SDavid Decotigny
3165fd003f5SDavid Decotigny bitmap_fill(bmap2, 1024);
3175fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 1024);
3185fd003f5SDavid Decotigny expect_eq_pbl("0-108", bmap2, 1024);
3195fd003f5SDavid Decotigny
3205fd003f5SDavid Decotigny /* the following tests assume a 32- or 64-bit arch (even 128b
3215fd003f5SDavid Decotigny * if we care)
3225fd003f5SDavid Decotigny */
3235fd003f5SDavid Decotigny
3245fd003f5SDavid Decotigny bitmap_fill(bmap2, 1024);
3255fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 109); /* ... but 0-padded til word length */
3265fd003f5SDavid Decotigny expect_eq_pbl("0-108,128-1023", bmap2, 1024);
3275fd003f5SDavid Decotigny
3285fd003f5SDavid Decotigny bitmap_fill(bmap2, 1024);
3295fd003f5SDavid Decotigny bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */
3305fd003f5SDavid Decotigny expect_eq_pbl("0-108,128-1023", bmap2, 1024);
3315fd003f5SDavid Decotigny }
3325fd003f5SDavid Decotigny
33330544ed5SAndy Shevchenko #define EXP2_IN_BITS (sizeof(exp2) * 8)
33430544ed5SAndy Shevchenko
test_replace(void)33530544ed5SAndy Shevchenko static void __init test_replace(void)
33630544ed5SAndy Shevchenko {
33730544ed5SAndy Shevchenko unsigned int nbits = 64;
33869334ca5SAndy Shevchenko unsigned int nlongs = DIV_ROUND_UP(nbits, BITS_PER_LONG);
33930544ed5SAndy Shevchenko DECLARE_BITMAP(bmap, 1024);
34030544ed5SAndy Shevchenko
341caa7f776SAndy Shevchenko BUILD_BUG_ON(EXP2_IN_BITS < nbits * 2);
342caa7f776SAndy Shevchenko
34330544ed5SAndy Shevchenko bitmap_zero(bmap, 1024);
34469334ca5SAndy Shevchenko bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits);
34530544ed5SAndy Shevchenko expect_eq_bitmap(bmap, exp3_0_1, nbits);
34630544ed5SAndy Shevchenko
34730544ed5SAndy Shevchenko bitmap_zero(bmap, 1024);
34869334ca5SAndy Shevchenko bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits);
34930544ed5SAndy Shevchenko expect_eq_bitmap(bmap, exp3_1_0, nbits);
35030544ed5SAndy Shevchenko
35130544ed5SAndy Shevchenko bitmap_fill(bmap, 1024);
35269334ca5SAndy Shevchenko bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits);
35330544ed5SAndy Shevchenko expect_eq_bitmap(bmap, exp3_0_1, nbits);
35430544ed5SAndy Shevchenko
35530544ed5SAndy Shevchenko bitmap_fill(bmap, 1024);
35669334ca5SAndy Shevchenko bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits);
35730544ed5SAndy Shevchenko expect_eq_bitmap(bmap, exp3_1_0, nbits);
35830544ed5SAndy Shevchenko }
35930544ed5SAndy Shevchenko
3606df0d464SYury Norov #define PARSE_TIME 0x1
3617eb2e94eSYury Norov #define NO_LEN 0x2
3626df0d464SYury Norov
3636df0d464SYury Norov struct test_bitmap_parselist{
3646df0d464SYury Norov const int errno;
3656df0d464SYury Norov const char *in;
3666df0d464SYury Norov const unsigned long *expected;
3676df0d464SYury Norov const int nbits;
3686df0d464SYury Norov const int flags;
3696df0d464SYury Norov };
3706df0d464SYury Norov
3716df0d464SYury Norov static const struct test_bitmap_parselist parselist_tests[] __initconst = {
37260ef6900SYury Norov #define step (sizeof(u64) / sizeof(unsigned long))
37360ef6900SYury Norov
3740ee312e3SAndy Shevchenko {0, "0", &exp1[0], 8, 0},
3750ee312e3SAndy Shevchenko {0, "1", &exp1[1 * step], 8, 0},
3760ee312e3SAndy Shevchenko {0, "0-15", &exp1[2 * step], 32, 0},
3770ee312e3SAndy Shevchenko {0, "16-31", &exp1[3 * step], 32, 0},
3780ee312e3SAndy Shevchenko {0, "0-31:1/2", &exp1[4 * step], 32, 0},
3790ee312e3SAndy Shevchenko {0, "1-31:1/2", &exp1[5 * step], 32, 0},
3800ee312e3SAndy Shevchenko {0, "0-31:1/4", &exp1[6 * step], 32, 0},
3810ee312e3SAndy Shevchenko {0, "1-31:1/4", &exp1[7 * step], 32, 0},
3820ee312e3SAndy Shevchenko {0, "0-31:4/4", &exp1[8 * step], 32, 0},
3830ee312e3SAndy Shevchenko {0, "1-31:4/4", &exp1[9 * step], 32, 0},
3840ee312e3SAndy Shevchenko {0, "0-31:1/4,32-63:2/4", &exp1[10 * step], 64, 0},
3850ee312e3SAndy Shevchenko {0, "0-31:3/4,32-63:4/4", &exp1[11 * step], 64, 0},
3860ee312e3SAndy Shevchenko {0, " ,, 0-31:3/4 ,, 32-63:4/4 ,, ", &exp1[11 * step], 64, 0},
3876df0d464SYury Norov
3886df0d464SYury Norov {0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4", exp2, 128, 0},
3896df0d464SYury Norov
3906df0d464SYury Norov {0, "0-2047:128/256", NULL, 2048, PARSE_TIME},
3916df0d464SYury Norov
3920ee312e3SAndy Shevchenko {0, "", &exp1[12 * step], 8, 0},
3930ee312e3SAndy Shevchenko {0, "\n", &exp1[12 * step], 8, 0},
3940ee312e3SAndy Shevchenko {0, ",, ,, , , ,", &exp1[12 * step], 8, 0},
3950ee312e3SAndy Shevchenko {0, " , ,, , , ", &exp1[12 * step], 8, 0},
3960ee312e3SAndy Shevchenko {0, " , ,, , , \n", &exp1[12 * step], 8, 0},
397a4ab5050SYury Norov
39897330db3SPaul Gortmaker {0, "0-0", &exp1[0], 32, 0},
39997330db3SPaul Gortmaker {0, "1-1", &exp1[1 * step], 32, 0},
40097330db3SPaul Gortmaker {0, "15-15", &exp1[13 * step], 32, 0},
40197330db3SPaul Gortmaker {0, "31-31", &exp1[14 * step], 32, 0},
40297330db3SPaul Gortmaker
40397330db3SPaul Gortmaker {0, "0-0:0/1", &exp1[12 * step], 32, 0},
40497330db3SPaul Gortmaker {0, "0-0:1/1", &exp1[0], 32, 0},
40597330db3SPaul Gortmaker {0, "0-0:1/31", &exp1[0], 32, 0},
40697330db3SPaul Gortmaker {0, "0-0:31/31", &exp1[0], 32, 0},
40797330db3SPaul Gortmaker {0, "1-1:1/1", &exp1[1 * step], 32, 0},
40897330db3SPaul Gortmaker {0, "0-15:16/31", &exp1[2 * step], 32, 0},
40997330db3SPaul Gortmaker {0, "15-15:1/2", &exp1[13 * step], 32, 0},
41097330db3SPaul Gortmaker {0, "15-15:31/31", &exp1[13 * step], 32, 0},
41197330db3SPaul Gortmaker {0, "15-31:1/31", &exp1[13 * step], 32, 0},
41297330db3SPaul Gortmaker {0, "16-31:16/31", &exp1[3 * step], 32, 0},
41397330db3SPaul Gortmaker {0, "31-31:31/31", &exp1[14 * step], 32, 0},
41497330db3SPaul Gortmaker
41599c58d1aSPaul Gortmaker {0, "N-N", &exp1[14 * step], 32, 0},
41699c58d1aSPaul Gortmaker {0, "0-0:1/N", &exp1[0], 32, 0},
41799c58d1aSPaul Gortmaker {0, "0-0:N/N", &exp1[0], 32, 0},
41899c58d1aSPaul Gortmaker {0, "0-15:16/N", &exp1[2 * step], 32, 0},
41999c58d1aSPaul Gortmaker {0, "15-15:N/N", &exp1[13 * step], 32, 0},
42099c58d1aSPaul Gortmaker {0, "15-N:1/N", &exp1[13 * step], 32, 0},
42199c58d1aSPaul Gortmaker {0, "16-N:16/N", &exp1[3 * step], 32, 0},
42299c58d1aSPaul Gortmaker {0, "N-N:N/N", &exp1[14 * step], 32, 0},
42399c58d1aSPaul Gortmaker
42499c58d1aSPaul Gortmaker {0, "0-N:1/3,1-N:1/3,2-N:1/3", &exp1[8 * step], 32, 0},
42597330db3SPaul Gortmaker {0, "0-31:1/3,1-31:1/3,2-31:1/3", &exp1[8 * step], 32, 0},
42697330db3SPaul Gortmaker {0, "1-10:8/12,8-31:24/29,0-31:0/3", &exp1[9 * step], 32, 0},
42797330db3SPaul Gortmaker
428b18def12SYury Norov {0, "all", &exp1[8 * step], 32, 0},
429b18def12SYury Norov {0, "0, 1, all, ", &exp1[8 * step], 32, 0},
430b18def12SYury Norov {0, "all:1/2", &exp1[4 * step], 32, 0},
431b18def12SYury Norov {0, "ALL:1/2", &exp1[4 * step], 32, 0},
432b18def12SYury Norov {-EINVAL, "al", NULL, 8, 0},
433b18def12SYury Norov {-EINVAL, "alll", NULL, 8, 0},
434b18def12SYury Norov
4356df0d464SYury Norov {-EINVAL, "-1", NULL, 8, 0},
4366df0d464SYury Norov {-EINVAL, "-0", NULL, 8, 0},
4376df0d464SYury Norov {-EINVAL, "10-1", NULL, 8, 0},
4386fef5905SPaul Gortmaker {-ERANGE, "8-8", NULL, 8, 0},
4396fef5905SPaul Gortmaker {-ERANGE, "0-31", NULL, 8, 0},
440494215fbSPaul Gortmaker {-EINVAL, "0-31:", NULL, 32, 0},
441494215fbSPaul Gortmaker {-EINVAL, "0-31:0", NULL, 32, 0},
442494215fbSPaul Gortmaker {-EINVAL, "0-31:0/", NULL, 32, 0},
443494215fbSPaul Gortmaker {-EINVAL, "0-31:0/0", NULL, 32, 0},
444494215fbSPaul Gortmaker {-EINVAL, "0-31:1/0", NULL, 32, 0},
445494215fbSPaul Gortmaker {-EINVAL, "0-31:10/1", NULL, 32, 0},
446a4ab5050SYury Norov {-EOVERFLOW, "0-98765432123456789:10/1", NULL, 8, 0},
447a4ab5050SYury Norov
448a4ab5050SYury Norov {-EINVAL, "a-31", NULL, 8, 0},
449a4ab5050SYury Norov {-EINVAL, "0-a1", NULL, 8, 0},
450a4ab5050SYury Norov {-EINVAL, "a-31:10/1", NULL, 8, 0},
451a4ab5050SYury Norov {-EINVAL, "0-31:a/1", NULL, 8, 0},
452a4ab5050SYury Norov {-EINVAL, "0-\n", NULL, 8, 0},
45354224044SAndy Shevchenko
4546df0d464SYury Norov };
4556df0d464SYury Norov
test_bitmap_parselist(void)45681b1e242SChristoph Hellwig static void __init test_bitmap_parselist(void)
4576df0d464SYury Norov {
4586df0d464SYury Norov int i;
4596df0d464SYury Norov int err;
4600c2111a5SYury Norov ktime_t time;
4616df0d464SYury Norov DECLARE_BITMAP(bmap, 2048);
4626df0d464SYury Norov
4636df0d464SYury Norov for (i = 0; i < ARRAY_SIZE(parselist_tests); i++) {
4646df0d464SYury Norov #define ptest parselist_tests[i]
4656df0d464SYury Norov
4660c2111a5SYury Norov time = ktime_get();
4676df0d464SYury Norov err = bitmap_parselist(ptest.in, bmap, ptest.nbits);
4680c2111a5SYury Norov time = ktime_get() - time;
4696df0d464SYury Norov
4706df0d464SYury Norov if (err != ptest.errno) {
47181b1e242SChristoph Hellwig pr_err("parselist: %d: input is %s, errno is %d, expected %d\n",
47281b1e242SChristoph Hellwig i, ptest.in, err, ptest.errno);
473c4c14c29SYury Norov failed_tests++;
4746df0d464SYury Norov continue;
4756df0d464SYury Norov }
4766df0d464SYury Norov
4776df0d464SYury Norov if (!err && ptest.expected
4786df0d464SYury Norov && !__bitmap_equal(bmap, ptest.expected, ptest.nbits)) {
47981b1e242SChristoph Hellwig pr_err("parselist: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
48081b1e242SChristoph Hellwig i, ptest.in, bmap[0],
4816ea86bdfSYury Norov *ptest.expected);
482c4c14c29SYury Norov failed_tests++;
4836df0d464SYury Norov continue;
4846df0d464SYury Norov }
4856df0d464SYury Norov
4866df0d464SYury Norov if (ptest.flags & PARSE_TIME)
48781b1e242SChristoph Hellwig pr_err("parselist: %d: input is '%s' OK, Time: %llu\n",
48881b1e242SChristoph Hellwig i, ptest.in, time);
48954224044SAndy Shevchenko
49054224044SAndy Shevchenko #undef ptest
4916df0d464SYury Norov }
4926df0d464SYury Norov }
4936df0d464SYury Norov
test_bitmap_printlist(void)494db731300SYury Norov static void __init test_bitmap_printlist(void)
495db731300SYury Norov {
496db731300SYury Norov unsigned long *bmap = kmalloc(PAGE_SIZE, GFP_KERNEL);
497db731300SYury Norov char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
498db731300SYury Norov char expected[256];
499db731300SYury Norov int ret, slen;
500db731300SYury Norov ktime_t time;
501db731300SYury Norov
502db731300SYury Norov if (!buf || !bmap)
503db731300SYury Norov goto out;
504db731300SYury Norov
505db731300SYury Norov memset(bmap, -1, PAGE_SIZE);
506db731300SYury Norov slen = snprintf(expected, 256, "0-%ld", PAGE_SIZE * 8 - 1);
507db731300SYury Norov if (slen < 0)
508db731300SYury Norov goto out;
509db731300SYury Norov
510db731300SYury Norov time = ktime_get();
511db731300SYury Norov ret = bitmap_print_to_pagebuf(true, buf, bmap, PAGE_SIZE * 8);
512db731300SYury Norov time = ktime_get() - time;
513db731300SYury Norov
514db731300SYury Norov if (ret != slen + 1) {
515db731300SYury Norov pr_err("bitmap_print_to_pagebuf: result is %d, expected %d\n", ret, slen);
516c4c14c29SYury Norov failed_tests++;
517db731300SYury Norov goto out;
518db731300SYury Norov }
519db731300SYury Norov
520db731300SYury Norov if (strncmp(buf, expected, slen)) {
521db731300SYury Norov pr_err("bitmap_print_to_pagebuf: result is %s, expected %s\n", buf, expected);
522c4c14c29SYury Norov failed_tests++;
523db731300SYury Norov goto out;
524db731300SYury Norov }
525db731300SYury Norov
526db731300SYury Norov pr_err("bitmap_print_to_pagebuf: input is '%s', Time: %llu\n", buf, time);
527db731300SYury Norov out:
528db731300SYury Norov kfree(buf);
529db731300SYury Norov kfree(bmap);
530db731300SYury Norov }
531db731300SYury Norov
5327eb2e94eSYury Norov static const unsigned long parse_test[] __initconst = {
5337eb2e94eSYury Norov BITMAP_FROM_U64(0),
5347eb2e94eSYury Norov BITMAP_FROM_U64(1),
5357eb2e94eSYury Norov BITMAP_FROM_U64(0xdeadbeef),
5367eb2e94eSYury Norov BITMAP_FROM_U64(0x100000000ULL),
5377eb2e94eSYury Norov };
5387eb2e94eSYury Norov
5397eb2e94eSYury Norov static const unsigned long parse_test2[] __initconst = {
5407eb2e94eSYury Norov BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xdeadbeef),
5417eb2e94eSYury Norov BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xbaadf00ddeadbeef),
5427eb2e94eSYury Norov BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0x0badf00ddeadbeef),
5437eb2e94eSYury Norov };
5447eb2e94eSYury Norov
5457eb2e94eSYury Norov static const struct test_bitmap_parselist parse_tests[] __initconst = {
546809e308fSYury Norov {0, "", &parse_test[0 * step], 32, 0},
547809e308fSYury Norov {0, " ", &parse_test[0 * step], 32, 0},
5487eb2e94eSYury Norov {0, "0", &parse_test[0 * step], 32, 0},
549809e308fSYury Norov {0, "0\n", &parse_test[0 * step], 32, 0},
5507eb2e94eSYury Norov {0, "1", &parse_test[1 * step], 32, 0},
5517eb2e94eSYury Norov {0, "deadbeef", &parse_test[2 * step], 32, 0},
5527eb2e94eSYury Norov {0, "1,0", &parse_test[3 * step], 33, 0},
553809e308fSYury Norov {0, "deadbeef,\n,0,1", &parse_test[2 * step], 96, 0},
5547eb2e94eSYury Norov
5557eb2e94eSYury Norov {0, "deadbeef,1,0", &parse_test2[0 * 2 * step], 96, 0},
5567eb2e94eSYury Norov {0, "baadf00d,deadbeef,1,0", &parse_test2[1 * 2 * step], 128, 0},
5577eb2e94eSYury Norov {0, "badf00d,deadbeef,1,0", &parse_test2[2 * 2 * step], 124, 0},
558809e308fSYury Norov {0, "badf00d,deadbeef,1,0", &parse_test2[2 * 2 * step], 124, NO_LEN},
559809e308fSYury Norov {0, " badf00d,deadbeef,1,0 ", &parse_test2[2 * 2 * step], 124, 0},
560809e308fSYury Norov {0, " , badf00d,deadbeef,1,0 , ", &parse_test2[2 * 2 * step], 124, 0},
561809e308fSYury Norov {0, " , badf00d, ,, ,,deadbeef,1,0 , ", &parse_test2[2 * 2 * step], 124, 0},
5627eb2e94eSYury Norov
5637eb2e94eSYury Norov {-EINVAL, "goodfood,deadbeef,1,0", NULL, 128, 0},
5647eb2e94eSYury Norov {-EOVERFLOW, "3,0", NULL, 33, 0},
5657eb2e94eSYury Norov {-EOVERFLOW, "123badf00d,deadbeef,1,0", NULL, 128, 0},
5667eb2e94eSYury Norov {-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 90, 0},
5677eb2e94eSYury Norov {-EOVERFLOW, "fbadf00d,deadbeef,1,0", NULL, 95, 0},
5687eb2e94eSYury Norov {-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 100, 0},
5697eb2e94eSYury Norov #undef step
5707eb2e94eSYury Norov };
5717eb2e94eSYury Norov
test_bitmap_parse(void)57281b1e242SChristoph Hellwig static void __init test_bitmap_parse(void)
5737eb2e94eSYury Norov {
5747eb2e94eSYury Norov int i;
5757eb2e94eSYury Norov int err;
5767eb2e94eSYury Norov ktime_t time;
5777eb2e94eSYury Norov DECLARE_BITMAP(bmap, 2048);
5787eb2e94eSYury Norov
5797eb2e94eSYury Norov for (i = 0; i < ARRAY_SIZE(parse_tests); i++) {
5807eb2e94eSYury Norov struct test_bitmap_parselist test = parse_tests[i];
58181b1e242SChristoph Hellwig size_t len = test.flags & NO_LEN ? UINT_MAX : strlen(test.in);
5827eb2e94eSYury Norov
5837eb2e94eSYury Norov time = ktime_get();
5847eb2e94eSYury Norov err = bitmap_parse(test.in, len, bmap, test.nbits);
5857eb2e94eSYury Norov time = ktime_get() - time;
5867eb2e94eSYury Norov
5877eb2e94eSYury Norov if (err != test.errno) {
58881b1e242SChristoph Hellwig pr_err("parse: %d: input is %s, errno is %d, expected %d\n",
58981b1e242SChristoph Hellwig i, test.in, err, test.errno);
590c4c14c29SYury Norov failed_tests++;
5917eb2e94eSYury Norov continue;
5927eb2e94eSYury Norov }
5937eb2e94eSYury Norov
5947eb2e94eSYury Norov if (!err && test.expected
5957eb2e94eSYury Norov && !__bitmap_equal(bmap, test.expected, test.nbits)) {
59681b1e242SChristoph Hellwig pr_err("parse: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
59781b1e242SChristoph Hellwig i, test.in, bmap[0],
5987eb2e94eSYury Norov *test.expected);
599c4c14c29SYury Norov failed_tests++;
6007eb2e94eSYury Norov continue;
6017eb2e94eSYury Norov }
6027eb2e94eSYury Norov
6037eb2e94eSYury Norov if (test.flags & PARSE_TIME)
60481b1e242SChristoph Hellwig pr_err("parse: %d: input is '%s' OK, Time: %llu\n",
60581b1e242SChristoph Hellwig i, test.in, time);
6067eb2e94eSYury Norov }
6077eb2e94eSYury Norov }
6087eb2e94eSYury Norov
test_bitmap_arr32(void)6093aa56885SYury Norov static void __init test_bitmap_arr32(void)
6105fd003f5SDavid Decotigny {
611f6f66c1bSKees Cook unsigned int nbits, next_bit;
612a4881d1cSAndy Shevchenko u32 arr[EXP1_IN_BITS / 32];
613a4881d1cSAndy Shevchenko DECLARE_BITMAP(bmap2, EXP1_IN_BITS);
6145fd003f5SDavid Decotigny
6153aa56885SYury Norov memset(arr, 0xa5, sizeof(arr));
6165fd003f5SDavid Decotigny
617a4881d1cSAndy Shevchenko for (nbits = 0; nbits < EXP1_IN_BITS; ++nbits) {
6180ee312e3SAndy Shevchenko bitmap_to_arr32(arr, exp1, nbits);
6193aa56885SYury Norov bitmap_from_arr32(bmap2, arr, nbits);
6200ee312e3SAndy Shevchenko expect_eq_bitmap(bmap2, exp1, nbits);
6215fd003f5SDavid Decotigny
6223aa56885SYury Norov next_bit = find_next_bit(bmap2,
6233aa56885SYury Norov round_up(nbits, BITS_PER_LONG), nbits);
624c4c14c29SYury Norov if (next_bit < round_up(nbits, BITS_PER_LONG)) {
6253aa56885SYury Norov pr_err("bitmap_copy_arr32(nbits == %d:"
6263aa56885SYury Norov " tail is not safely cleared: %d\n",
6273aa56885SYury Norov nbits, next_bit);
628c4c14c29SYury Norov failed_tests++;
629c4c14c29SYury Norov }
6305fd003f5SDavid Decotigny
631a4881d1cSAndy Shevchenko if (nbits < EXP1_IN_BITS - 32)
6323aa56885SYury Norov expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)],
6333aa56885SYury Norov 0xa5a5a5a5);
6345fd003f5SDavid Decotigny }
6355fd003f5SDavid Decotigny }
6365fd003f5SDavid Decotigny
test_bitmap_arr64(void)6372c523550SYury Norov static void __init test_bitmap_arr64(void)
6382c523550SYury Norov {
6392c523550SYury Norov unsigned int nbits, next_bit;
6402c523550SYury Norov u64 arr[EXP1_IN_BITS / 64];
6412c523550SYury Norov DECLARE_BITMAP(bmap2, EXP1_IN_BITS);
6422c523550SYury Norov
6432c523550SYury Norov memset(arr, 0xa5, sizeof(arr));
6442c523550SYury Norov
6452c523550SYury Norov for (nbits = 0; nbits < EXP1_IN_BITS; ++nbits) {
6462c523550SYury Norov memset(bmap2, 0xff, sizeof(arr));
6472c523550SYury Norov bitmap_to_arr64(arr, exp1, nbits);
6482c523550SYury Norov bitmap_from_arr64(bmap2, arr, nbits);
6492c523550SYury Norov expect_eq_bitmap(bmap2, exp1, nbits);
6502c523550SYury Norov
6512c523550SYury Norov next_bit = find_next_bit(bmap2, round_up(nbits, BITS_PER_LONG), nbits);
652c4c14c29SYury Norov if (next_bit < round_up(nbits, BITS_PER_LONG)) {
6532c523550SYury Norov pr_err("bitmap_copy_arr64(nbits == %d:"
6542c523550SYury Norov " tail is not safely cleared: %d\n", nbits, next_bit);
655c4c14c29SYury Norov failed_tests++;
656c4c14c29SYury Norov }
6572c523550SYury Norov
65830fd8cdfSAlexander Lobakin if ((nbits % 64) &&
659c4c14c29SYury Norov (arr[(nbits - 1) / 64] & ~GENMASK_ULL((nbits - 1) % 64, 0))) {
66030fd8cdfSAlexander Lobakin pr_err("bitmap_to_arr64(nbits == %d): tail is not safely cleared: 0x%016llx (must be 0x%016llx)\n",
66130fd8cdfSAlexander Lobakin nbits, arr[(nbits - 1) / 64],
66230fd8cdfSAlexander Lobakin GENMASK_ULL((nbits - 1) % 64, 0));
663c4c14c29SYury Norov failed_tests++;
664c4c14c29SYury Norov }
66530fd8cdfSAlexander Lobakin
6662c523550SYury Norov if (nbits < EXP1_IN_BITS - 64)
6672c523550SYury Norov expect_eq_uint(arr[DIV_ROUND_UP(nbits, 64)], 0xa5a5a5a5);
6682c523550SYury Norov }
6692c523550SYury Norov }
6702c523550SYury Norov
test_mem_optimisations(void)6713cc78125SMatthew Wilcox static void noinline __init test_mem_optimisations(void)
6723cc78125SMatthew Wilcox {
6733cc78125SMatthew Wilcox DECLARE_BITMAP(bmap1, 1024);
6743cc78125SMatthew Wilcox DECLARE_BITMAP(bmap2, 1024);
6753cc78125SMatthew Wilcox unsigned int start, nbits;
6763cc78125SMatthew Wilcox
6773cc78125SMatthew Wilcox for (start = 0; start < 1024; start += 8) {
6781e3054b9SMatthew Wilcox for (nbits = 0; nbits < 1024 - start; nbits += 8) {
6793cc78125SMatthew Wilcox memset(bmap1, 0x5a, sizeof(bmap1));
6803cc78125SMatthew Wilcox memset(bmap2, 0x5a, sizeof(bmap2));
6811e3054b9SMatthew Wilcox
6823cc78125SMatthew Wilcox bitmap_set(bmap1, start, nbits);
6833cc78125SMatthew Wilcox __bitmap_set(bmap2, start, nbits);
6841e3054b9SMatthew Wilcox if (!bitmap_equal(bmap1, bmap2, 1024)) {
6853cc78125SMatthew Wilcox printk("set not equal %d %d\n", start, nbits);
6861e3054b9SMatthew Wilcox failed_tests++;
6871e3054b9SMatthew Wilcox }
6881e3054b9SMatthew Wilcox if (!__bitmap_equal(bmap1, bmap2, 1024)) {
6893cc78125SMatthew Wilcox printk("set not __equal %d %d\n", start, nbits);
6901e3054b9SMatthew Wilcox failed_tests++;
6911e3054b9SMatthew Wilcox }
6923cc78125SMatthew Wilcox
6933cc78125SMatthew Wilcox bitmap_clear(bmap1, start, nbits);
6943cc78125SMatthew Wilcox __bitmap_clear(bmap2, start, nbits);
6951e3054b9SMatthew Wilcox if (!bitmap_equal(bmap1, bmap2, 1024)) {
6963cc78125SMatthew Wilcox printk("clear not equal %d %d\n", start, nbits);
6971e3054b9SMatthew Wilcox failed_tests++;
6981e3054b9SMatthew Wilcox }
6991e3054b9SMatthew Wilcox if (!__bitmap_equal(bmap1, bmap2, 1024)) {
7003cc78125SMatthew Wilcox printk("clear not __equal %d %d\n", start,
7013cc78125SMatthew Wilcox nbits);
7021e3054b9SMatthew Wilcox failed_tests++;
7031e3054b9SMatthew Wilcox }
7043cc78125SMatthew Wilcox }
7053cc78125SMatthew Wilcox }
7063cc78125SMatthew Wilcox }
7073cc78125SMatthew Wilcox
708e4aa168dSWilliam Breathitt Gray static const unsigned char clump_exp[] __initconst = {
709e4aa168dSWilliam Breathitt Gray 0x01, /* 1 bit set */
710e4aa168dSWilliam Breathitt Gray 0x02, /* non-edge 1 bit set */
711e4aa168dSWilliam Breathitt Gray 0x00, /* zero bits set */
712e4aa168dSWilliam Breathitt Gray 0x38, /* 3 bits set across 4-bit boundary */
713e4aa168dSWilliam Breathitt Gray 0x38, /* Repeated clump */
714e4aa168dSWilliam Breathitt Gray 0x0F, /* 4 bits set */
715e4aa168dSWilliam Breathitt Gray 0xFF, /* all bits set */
716e4aa168dSWilliam Breathitt Gray 0x05, /* non-adjacent 2 bits set */
717e4aa168dSWilliam Breathitt Gray };
718e4aa168dSWilliam Breathitt Gray
test_for_each_set_clump8(void)719e4aa168dSWilliam Breathitt Gray static void __init test_for_each_set_clump8(void)
720e4aa168dSWilliam Breathitt Gray {
721e4aa168dSWilliam Breathitt Gray #define CLUMP_EXP_NUMBITS 64
722e4aa168dSWilliam Breathitt Gray DECLARE_BITMAP(bits, CLUMP_EXP_NUMBITS);
723e4aa168dSWilliam Breathitt Gray unsigned int start;
724e4aa168dSWilliam Breathitt Gray unsigned long clump;
725e4aa168dSWilliam Breathitt Gray
726e4aa168dSWilliam Breathitt Gray /* set bitmap to test case */
727e4aa168dSWilliam Breathitt Gray bitmap_zero(bits, CLUMP_EXP_NUMBITS);
728e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 0, 1); /* 0x01 */
729e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 9, 1); /* 0x02 */
730e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 27, 3); /* 0x28 */
731e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 35, 3); /* 0x28 */
732e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 40, 4); /* 0x0F */
733e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 48, 8); /* 0xFF */
734e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 56, 1); /* 0x05 - part 1 */
735e4aa168dSWilliam Breathitt Gray bitmap_set(bits, 58, 1); /* 0x05 - part 2 */
736e4aa168dSWilliam Breathitt Gray
737e4aa168dSWilliam Breathitt Gray for_each_set_clump8(start, clump, bits, CLUMP_EXP_NUMBITS)
738e4aa168dSWilliam Breathitt Gray expect_eq_clump8(start, CLUMP_EXP_NUMBITS, clump_exp, &clump);
739e4aa168dSWilliam Breathitt Gray }
740e4aa168dSWilliam Breathitt Gray
test_for_each_set_bit_wrap(void)7418173aa26SYury Norov static void __init test_for_each_set_bit_wrap(void)
7428173aa26SYury Norov {
7438173aa26SYury Norov DECLARE_BITMAP(orig, 500);
7448173aa26SYury Norov DECLARE_BITMAP(copy, 500);
7458173aa26SYury Norov unsigned int wr, bit;
7468173aa26SYury Norov
7478173aa26SYury Norov bitmap_zero(orig, 500);
7488173aa26SYury Norov
7498173aa26SYury Norov /* Set individual bits */
7508173aa26SYury Norov for (bit = 0; bit < 500; bit += 10)
7518173aa26SYury Norov bitmap_set(orig, bit, 1);
7528173aa26SYury Norov
7538173aa26SYury Norov /* Set range of bits */
7548173aa26SYury Norov bitmap_set(orig, 100, 50);
7558173aa26SYury Norov
7568173aa26SYury Norov for (wr = 0; wr < 500; wr++) {
7578173aa26SYury Norov bitmap_zero(copy, 500);
7588173aa26SYury Norov
7598173aa26SYury Norov for_each_set_bit_wrap(bit, orig, 500, wr)
7608173aa26SYury Norov bitmap_set(copy, bit, 1);
7618173aa26SYury Norov
7628173aa26SYury Norov expect_eq_bitmap(orig, copy, 500);
7638173aa26SYury Norov }
7648173aa26SYury Norov }
7658173aa26SYury Norov
test_for_each_set_bit(void)7668173aa26SYury Norov static void __init test_for_each_set_bit(void)
7678173aa26SYury Norov {
7688173aa26SYury Norov DECLARE_BITMAP(orig, 500);
7698173aa26SYury Norov DECLARE_BITMAP(copy, 500);
7708173aa26SYury Norov unsigned int bit;
7718173aa26SYury Norov
7728173aa26SYury Norov bitmap_zero(orig, 500);
7738173aa26SYury Norov bitmap_zero(copy, 500);
7748173aa26SYury Norov
7758173aa26SYury Norov /* Set individual bits */
7768173aa26SYury Norov for (bit = 0; bit < 500; bit += 10)
7778173aa26SYury Norov bitmap_set(orig, bit, 1);
7788173aa26SYury Norov
7798173aa26SYury Norov /* Set range of bits */
7808173aa26SYury Norov bitmap_set(orig, 100, 50);
7818173aa26SYury Norov
7828173aa26SYury Norov for_each_set_bit(bit, orig, 500)
7838173aa26SYury Norov bitmap_set(copy, bit, 1);
7848173aa26SYury Norov
7858173aa26SYury Norov expect_eq_bitmap(orig, copy, 500);
7868173aa26SYury Norov }
7878173aa26SYury Norov
test_for_each_set_bit_from(void)7888173aa26SYury Norov static void __init test_for_each_set_bit_from(void)
7898173aa26SYury Norov {
7908173aa26SYury Norov DECLARE_BITMAP(orig, 500);
7918173aa26SYury Norov DECLARE_BITMAP(copy, 500);
7928173aa26SYury Norov unsigned int wr, bit;
7938173aa26SYury Norov
7948173aa26SYury Norov bitmap_zero(orig, 500);
7958173aa26SYury Norov
7968173aa26SYury Norov /* Set individual bits */
7978173aa26SYury Norov for (bit = 0; bit < 500; bit += 10)
7988173aa26SYury Norov bitmap_set(orig, bit, 1);
7998173aa26SYury Norov
8008173aa26SYury Norov /* Set range of bits */
8018173aa26SYury Norov bitmap_set(orig, 100, 50);
8028173aa26SYury Norov
8038173aa26SYury Norov for (wr = 0; wr < 500; wr++) {
8048173aa26SYury Norov DECLARE_BITMAP(tmp, 500);
8058173aa26SYury Norov
8068173aa26SYury Norov bitmap_zero(copy, 500);
8078173aa26SYury Norov bit = wr;
8088173aa26SYury Norov
8098173aa26SYury Norov for_each_set_bit_from(bit, orig, 500)
8108173aa26SYury Norov bitmap_set(copy, bit, 1);
8118173aa26SYury Norov
8128173aa26SYury Norov bitmap_copy(tmp, orig, 500);
8138173aa26SYury Norov bitmap_clear(tmp, 0, wr);
8148173aa26SYury Norov expect_eq_bitmap(tmp, copy, 500);
8158173aa26SYury Norov }
8168173aa26SYury Norov }
8178173aa26SYury Norov
test_for_each_clear_bit(void)8188173aa26SYury Norov static void __init test_for_each_clear_bit(void)
8198173aa26SYury Norov {
8208173aa26SYury Norov DECLARE_BITMAP(orig, 500);
8218173aa26SYury Norov DECLARE_BITMAP(copy, 500);
8228173aa26SYury Norov unsigned int bit;
8238173aa26SYury Norov
8248173aa26SYury Norov bitmap_fill(orig, 500);
8258173aa26SYury Norov bitmap_fill(copy, 500);
8268173aa26SYury Norov
8278173aa26SYury Norov /* Set individual bits */
8288173aa26SYury Norov for (bit = 0; bit < 500; bit += 10)
8298173aa26SYury Norov bitmap_clear(orig, bit, 1);
8308173aa26SYury Norov
8318173aa26SYury Norov /* Set range of bits */
8328173aa26SYury Norov bitmap_clear(orig, 100, 50);
8338173aa26SYury Norov
8348173aa26SYury Norov for_each_clear_bit(bit, orig, 500)
8358173aa26SYury Norov bitmap_clear(copy, bit, 1);
8368173aa26SYury Norov
8378173aa26SYury Norov expect_eq_bitmap(orig, copy, 500);
8388173aa26SYury Norov }
8398173aa26SYury Norov
test_for_each_clear_bit_from(void)8408173aa26SYury Norov static void __init test_for_each_clear_bit_from(void)
8418173aa26SYury Norov {
8428173aa26SYury Norov DECLARE_BITMAP(orig, 500);
8438173aa26SYury Norov DECLARE_BITMAP(copy, 500);
8448173aa26SYury Norov unsigned int wr, bit;
8458173aa26SYury Norov
8468173aa26SYury Norov bitmap_fill(orig, 500);
8478173aa26SYury Norov
8488173aa26SYury Norov /* Set individual bits */
8498173aa26SYury Norov for (bit = 0; bit < 500; bit += 10)
8508173aa26SYury Norov bitmap_clear(orig, bit, 1);
8518173aa26SYury Norov
8528173aa26SYury Norov /* Set range of bits */
8538173aa26SYury Norov bitmap_clear(orig, 100, 50);
8548173aa26SYury Norov
8558173aa26SYury Norov for (wr = 0; wr < 500; wr++) {
8568173aa26SYury Norov DECLARE_BITMAP(tmp, 500);
8578173aa26SYury Norov
8588173aa26SYury Norov bitmap_fill(copy, 500);
8598173aa26SYury Norov bit = wr;
8608173aa26SYury Norov
8618173aa26SYury Norov for_each_clear_bit_from(bit, orig, 500)
8628173aa26SYury Norov bitmap_clear(copy, bit, 1);
8638173aa26SYury Norov
8648173aa26SYury Norov bitmap_copy(tmp, orig, 500);
8658173aa26SYury Norov bitmap_set(tmp, 0, wr);
8668173aa26SYury Norov expect_eq_bitmap(tmp, copy, 500);
8678173aa26SYury Norov }
8688173aa26SYury Norov }
8698173aa26SYury Norov
test_for_each_set_bitrange(void)8708173aa26SYury Norov static void __init test_for_each_set_bitrange(void)
8718173aa26SYury Norov {
8728173aa26SYury Norov DECLARE_BITMAP(orig, 500);
8738173aa26SYury Norov DECLARE_BITMAP(copy, 500);
8748173aa26SYury Norov unsigned int s, e;
8758173aa26SYury Norov
8768173aa26SYury Norov bitmap_zero(orig, 500);
8778173aa26SYury Norov bitmap_zero(copy, 500);
8788173aa26SYury Norov
8798173aa26SYury Norov /* Set individual bits */
8808173aa26SYury Norov for (s = 0; s < 500; s += 10)
8818173aa26SYury Norov bitmap_set(orig, s, 1);
8828173aa26SYury Norov
8838173aa26SYury Norov /* Set range of bits */
8848173aa26SYury Norov bitmap_set(orig, 100, 50);
8858173aa26SYury Norov
8868173aa26SYury Norov for_each_set_bitrange(s, e, orig, 500)
8878173aa26SYury Norov bitmap_set(copy, s, e-s);
8888173aa26SYury Norov
8898173aa26SYury Norov expect_eq_bitmap(orig, copy, 500);
8908173aa26SYury Norov }
8918173aa26SYury Norov
test_for_each_clear_bitrange(void)8928173aa26SYury Norov static void __init test_for_each_clear_bitrange(void)
8938173aa26SYury Norov {
8948173aa26SYury Norov DECLARE_BITMAP(orig, 500);
8958173aa26SYury Norov DECLARE_BITMAP(copy, 500);
8968173aa26SYury Norov unsigned int s, e;
8978173aa26SYury Norov
8988173aa26SYury Norov bitmap_fill(orig, 500);
8998173aa26SYury Norov bitmap_fill(copy, 500);
9008173aa26SYury Norov
9018173aa26SYury Norov /* Set individual bits */
9028173aa26SYury Norov for (s = 0; s < 500; s += 10)
9038173aa26SYury Norov bitmap_clear(orig, s, 1);
9048173aa26SYury Norov
9058173aa26SYury Norov /* Set range of bits */
9068173aa26SYury Norov bitmap_clear(orig, 100, 50);
9078173aa26SYury Norov
9088173aa26SYury Norov for_each_clear_bitrange(s, e, orig, 500)
9098173aa26SYury Norov bitmap_clear(copy, s, e-s);
9108173aa26SYury Norov
9118173aa26SYury Norov expect_eq_bitmap(orig, copy, 500);
9128173aa26SYury Norov }
9138173aa26SYury Norov
test_for_each_set_bitrange_from(void)9148173aa26SYury Norov static void __init test_for_each_set_bitrange_from(void)
9158173aa26SYury Norov {
9168173aa26SYury Norov DECLARE_BITMAP(orig, 500);
9178173aa26SYury Norov DECLARE_BITMAP(copy, 500);
9188173aa26SYury Norov unsigned int wr, s, e;
9198173aa26SYury Norov
9208173aa26SYury Norov bitmap_zero(orig, 500);
9218173aa26SYury Norov
9228173aa26SYury Norov /* Set individual bits */
9238173aa26SYury Norov for (s = 0; s < 500; s += 10)
9248173aa26SYury Norov bitmap_set(orig, s, 1);
9258173aa26SYury Norov
9268173aa26SYury Norov /* Set range of bits */
9278173aa26SYury Norov bitmap_set(orig, 100, 50);
9288173aa26SYury Norov
9298173aa26SYury Norov for (wr = 0; wr < 500; wr++) {
9308173aa26SYury Norov DECLARE_BITMAP(tmp, 500);
9318173aa26SYury Norov
9328173aa26SYury Norov bitmap_zero(copy, 500);
9338173aa26SYury Norov s = wr;
9348173aa26SYury Norov
9358173aa26SYury Norov for_each_set_bitrange_from(s, e, orig, 500)
9368173aa26SYury Norov bitmap_set(copy, s, e - s);
9378173aa26SYury Norov
9388173aa26SYury Norov bitmap_copy(tmp, orig, 500);
9398173aa26SYury Norov bitmap_clear(tmp, 0, wr);
9408173aa26SYury Norov expect_eq_bitmap(tmp, copy, 500);
9418173aa26SYury Norov }
9428173aa26SYury Norov }
9438173aa26SYury Norov
test_for_each_clear_bitrange_from(void)9448173aa26SYury Norov static void __init test_for_each_clear_bitrange_from(void)
9458173aa26SYury Norov {
9468173aa26SYury Norov DECLARE_BITMAP(orig, 500);
9478173aa26SYury Norov DECLARE_BITMAP(copy, 500);
9488173aa26SYury Norov unsigned int wr, s, e;
9498173aa26SYury Norov
9508173aa26SYury Norov bitmap_fill(orig, 500);
9518173aa26SYury Norov
9528173aa26SYury Norov /* Set individual bits */
9538173aa26SYury Norov for (s = 0; s < 500; s += 10)
9548173aa26SYury Norov bitmap_clear(orig, s, 1);
9558173aa26SYury Norov
9568173aa26SYury Norov /* Set range of bits */
9578173aa26SYury Norov bitmap_set(orig, 100, 50);
9588173aa26SYury Norov
9598173aa26SYury Norov for (wr = 0; wr < 500; wr++) {
9608173aa26SYury Norov DECLARE_BITMAP(tmp, 500);
9618173aa26SYury Norov
9628173aa26SYury Norov bitmap_fill(copy, 500);
9638173aa26SYury Norov s = wr;
9648173aa26SYury Norov
9658173aa26SYury Norov for_each_clear_bitrange_from(s, e, orig, 500)
9668173aa26SYury Norov bitmap_clear(copy, s, e - s);
9678173aa26SYury Norov
9688173aa26SYury Norov bitmap_copy(tmp, orig, 500);
9698173aa26SYury Norov bitmap_set(tmp, 0, wr);
9708173aa26SYury Norov expect_eq_bitmap(tmp, copy, 500);
9718173aa26SYury Norov }
9728173aa26SYury Norov }
9738173aa26SYury Norov
974bcb32a1dSStefano Brivio struct test_bitmap_cut {
975bcb32a1dSStefano Brivio unsigned int first;
976bcb32a1dSStefano Brivio unsigned int cut;
977bcb32a1dSStefano Brivio unsigned int nbits;
978bcb32a1dSStefano Brivio unsigned long in[4];
979bcb32a1dSStefano Brivio unsigned long expected[4];
980bcb32a1dSStefano Brivio };
981bcb32a1dSStefano Brivio
982bcb32a1dSStefano Brivio static struct test_bitmap_cut test_cut[] = {
983bcb32a1dSStefano Brivio { 0, 0, 8, { 0x0000000aUL, }, { 0x0000000aUL, }, },
984bcb32a1dSStefano Brivio { 0, 0, 32, { 0xdadadeadUL, }, { 0xdadadeadUL, }, },
985bcb32a1dSStefano Brivio { 0, 3, 8, { 0x000000aaUL, }, { 0x00000015UL, }, },
986bcb32a1dSStefano Brivio { 3, 3, 8, { 0x000000aaUL, }, { 0x00000012UL, }, },
987bcb32a1dSStefano Brivio { 0, 1, 32, { 0xa5a5a5a5UL, }, { 0x52d2d2d2UL, }, },
988bcb32a1dSStefano Brivio { 0, 8, 32, { 0xdeadc0deUL, }, { 0x00deadc0UL, }, },
989bcb32a1dSStefano Brivio { 1, 1, 32, { 0x5a5a5a5aUL, }, { 0x2d2d2d2cUL, }, },
990bcb32a1dSStefano Brivio { 0, 15, 32, { 0xa5a5a5a5UL, }, { 0x00014b4bUL, }, },
991bcb32a1dSStefano Brivio { 0, 16, 32, { 0xa5a5a5a5UL, }, { 0x0000a5a5UL, }, },
992bcb32a1dSStefano Brivio { 15, 15, 32, { 0xa5a5a5a5UL, }, { 0x000125a5UL, }, },
993bcb32a1dSStefano Brivio { 15, 16, 32, { 0xa5a5a5a5UL, }, { 0x0000a5a5UL, }, },
994bcb32a1dSStefano Brivio { 16, 15, 32, { 0xa5a5a5a5UL, }, { 0x0001a5a5UL, }, },
995bcb32a1dSStefano Brivio
996bcb32a1dSStefano Brivio { BITS_PER_LONG, BITS_PER_LONG, BITS_PER_LONG,
997bcb32a1dSStefano Brivio { 0xa5a5a5a5UL, 0xa5a5a5a5UL, },
998bcb32a1dSStefano Brivio { 0xa5a5a5a5UL, 0xa5a5a5a5UL, },
999bcb32a1dSStefano Brivio },
1000bcb32a1dSStefano Brivio { 1, BITS_PER_LONG - 1, BITS_PER_LONG,
1001bcb32a1dSStefano Brivio { 0xa5a5a5a5UL, 0xa5a5a5a5UL, },
1002bcb32a1dSStefano Brivio { 0x00000001UL, 0x00000001UL, },
1003bcb32a1dSStefano Brivio },
1004bcb32a1dSStefano Brivio
1005bcb32a1dSStefano Brivio { 0, BITS_PER_LONG * 2, BITS_PER_LONG * 2 + 1,
1006bcb32a1dSStefano Brivio { 0xa5a5a5a5UL, 0x00000001UL, 0x00000001UL, 0x00000001UL },
1007bcb32a1dSStefano Brivio { 0x00000001UL, },
1008bcb32a1dSStefano Brivio },
1009bcb32a1dSStefano Brivio { 16, BITS_PER_LONG * 2 + 1, BITS_PER_LONG * 2 + 1 + 16,
1010bcb32a1dSStefano Brivio { 0x0000ffffUL, 0x5a5a5a5aUL, 0x5a5a5a5aUL, 0x5a5a5a5aUL },
1011bcb32a1dSStefano Brivio { 0x2d2dffffUL, },
1012bcb32a1dSStefano Brivio },
1013bcb32a1dSStefano Brivio };
1014bcb32a1dSStefano Brivio
test_bitmap_cut(void)1015bcb32a1dSStefano Brivio static void __init test_bitmap_cut(void)
1016bcb32a1dSStefano Brivio {
1017bcb32a1dSStefano Brivio unsigned long b[5], *in = &b[1], *out = &b[0]; /* Partial overlap */
1018bcb32a1dSStefano Brivio int i;
1019bcb32a1dSStefano Brivio
1020bcb32a1dSStefano Brivio for (i = 0; i < ARRAY_SIZE(test_cut); i++) {
1021bcb32a1dSStefano Brivio struct test_bitmap_cut *t = &test_cut[i];
1022bcb32a1dSStefano Brivio
1023bcb32a1dSStefano Brivio memcpy(in, t->in, sizeof(t->in));
1024bcb32a1dSStefano Brivio
1025bcb32a1dSStefano Brivio bitmap_cut(out, in, t->first, t->cut, t->nbits);
1026bcb32a1dSStefano Brivio
1027bcb32a1dSStefano Brivio expect_eq_bitmap(t->expected, out, t->nbits);
1028bcb32a1dSStefano Brivio }
1029bcb32a1dSStefano Brivio }
1030bcb32a1dSStefano Brivio
1031291f93caSBarry Song struct test_bitmap_print {
1032291f93caSBarry Song const unsigned long *bitmap;
1033291f93caSBarry Song unsigned long nbits;
1034291f93caSBarry Song const char *mask;
1035291f93caSBarry Song const char *list;
1036291f93caSBarry Song };
1037291f93caSBarry Song
1038291f93caSBarry Song static const unsigned long small_bitmap[] __initconst = {
1039291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL),
1040291f93caSBarry Song };
1041291f93caSBarry Song
1042291f93caSBarry Song static const char small_mask[] __initconst = "33333333,11111111\n";
1043291f93caSBarry Song static const char small_list[] __initconst = "0,4,8,12,16,20,24,28,32-33,36-37,40-41,44-45,48-49,52-53,56-57,60-61\n";
1044291f93caSBarry Song
1045291f93caSBarry Song static const unsigned long large_bitmap[] __initconst = {
1046291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1047291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1048291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1049291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1050291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1051291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1052291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1053291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1054291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1055291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1056291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1057291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1058291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1059291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1060291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1061291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1062291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1063291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1064291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1065291f93caSBarry Song BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
1066291f93caSBarry Song };
1067291f93caSBarry Song
1068291f93caSBarry Song static const char large_mask[] __initconst = "33333333,11111111,33333333,11111111,"
1069291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1070291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1071291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1072291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1073291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1074291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1075291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1076291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1077291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1078291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1079291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1080291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1081291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1082291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1083291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1084291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1085291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1086291f93caSBarry Song "33333333,11111111,33333333,11111111,"
1087291f93caSBarry Song "33333333,11111111,33333333,11111111\n";
1088291f93caSBarry Song
1089291f93caSBarry Song static const char large_list[] __initconst = /* more than 4KB */
1090291f93caSBarry Song "0,4,8,12,16,20,24,28,32-33,36-37,40-41,44-45,48-49,52-53,56-57,60-61,64,68,72,76,80,84,88,92,96-97,100-101,104-1"
1091291f93caSBarry Song "05,108-109,112-113,116-117,120-121,124-125,128,132,136,140,144,148,152,156,160-161,164-165,168-169,172-173,176-1"
1092291f93caSBarry Song "77,180-181,184-185,188-189,192,196,200,204,208,212,216,220,224-225,228-229,232-233,236-237,240-241,244-245,248-2"
1093291f93caSBarry Song "49,252-253,256,260,264,268,272,276,280,284,288-289,292-293,296-297,300-301,304-305,308-309,312-313,316-317,320,3"
1094291f93caSBarry Song "24,328,332,336,340,344,348,352-353,356-357,360-361,364-365,368-369,372-373,376-377,380-381,384,388,392,396,400,4"
1095291f93caSBarry Song "04,408,412,416-417,420-421,424-425,428-429,432-433,436-437,440-441,444-445,448,452,456,460,464,468,472,476,480-4"
1096291f93caSBarry Song "81,484-485,488-489,492-493,496-497,500-501,504-505,508-509,512,516,520,524,528,532,536,540,544-545,548-549,552-5"
1097291f93caSBarry Song "53,556-557,560-561,564-565,568-569,572-573,576,580,584,588,592,596,600,604,608-609,612-613,616-617,620-621,624-6"
1098291f93caSBarry Song "25,628-629,632-633,636-637,640,644,648,652,656,660,664,668,672-673,676-677,680-681,684-685,688-689,692-693,696-6"
1099291f93caSBarry Song "97,700-701,704,708,712,716,720,724,728,732,736-737,740-741,744-745,748-749,752-753,756-757,760-761,764-765,768,7"
1100291f93caSBarry Song "72,776,780,784,788,792,796,800-801,804-805,808-809,812-813,816-817,820-821,824-825,828-829,832,836,840,844,848,8"
1101291f93caSBarry Song "52,856,860,864-865,868-869,872-873,876-877,880-881,884-885,888-889,892-893,896,900,904,908,912,916,920,924,928-9"
1102291f93caSBarry Song "29,932-933,936-937,940-941,944-945,948-949,952-953,956-957,960,964,968,972,976,980,984,988,992-993,996-997,1000-"
1103291f93caSBarry Song "1001,1004-1005,1008-1009,1012-1013,1016-1017,1020-1021,1024,1028,1032,1036,1040,1044,1048,1052,1056-1057,1060-10"
1104291f93caSBarry Song "61,1064-1065,1068-1069,1072-1073,1076-1077,1080-1081,1084-1085,1088,1092,1096,1100,1104,1108,1112,1116,1120-1121"
1105291f93caSBarry Song ",1124-1125,1128-1129,1132-1133,1136-1137,1140-1141,1144-1145,1148-1149,1152,1156,1160,1164,1168,1172,1176,1180,1"
1106291f93caSBarry Song "184-1185,1188-1189,1192-1193,1196-1197,1200-1201,1204-1205,1208-1209,1212-1213,1216,1220,1224,1228,1232,1236,124"
1107291f93caSBarry Song "0,1244,1248-1249,1252-1253,1256-1257,1260-1261,1264-1265,1268-1269,1272-1273,1276-1277,1280,1284,1288,1292,1296,"
1108291f93caSBarry Song "1300,1304,1308,1312-1313,1316-1317,1320-1321,1324-1325,1328-1329,1332-1333,1336-1337,1340-1341,1344,1348,1352,13"
1109291f93caSBarry Song "56,1360,1364,1368,1372,1376-1377,1380-1381,1384-1385,1388-1389,1392-1393,1396-1397,1400-1401,1404-1405,1408,1412"
1110291f93caSBarry Song ",1416,1420,1424,1428,1432,1436,1440-1441,1444-1445,1448-1449,1452-1453,1456-1457,1460-1461,1464-1465,1468-1469,1"
1111291f93caSBarry Song "472,1476,1480,1484,1488,1492,1496,1500,1504-1505,1508-1509,1512-1513,1516-1517,1520-1521,1524-1525,1528-1529,153"
1112291f93caSBarry Song "2-1533,1536,1540,1544,1548,1552,1556,1560,1564,1568-1569,1572-1573,1576-1577,1580-1581,1584-1585,1588-1589,1592-"
1113291f93caSBarry Song "1593,1596-1597,1600,1604,1608,1612,1616,1620,1624,1628,1632-1633,1636-1637,1640-1641,1644-1645,1648-1649,1652-16"
1114291f93caSBarry Song "53,1656-1657,1660-1661,1664,1668,1672,1676,1680,1684,1688,1692,1696-1697,1700-1701,1704-1705,1708-1709,1712-1713"
1115291f93caSBarry Song ",1716-1717,1720-1721,1724-1725,1728,1732,1736,1740,1744,1748,1752,1756,1760-1761,1764-1765,1768-1769,1772-1773,1"
1116291f93caSBarry Song "776-1777,1780-1781,1784-1785,1788-1789,1792,1796,1800,1804,1808,1812,1816,1820,1824-1825,1828-1829,1832-1833,183"
1117291f93caSBarry Song "6-1837,1840-1841,1844-1845,1848-1849,1852-1853,1856,1860,1864,1868,1872,1876,1880,1884,1888-1889,1892-1893,1896-"
1118291f93caSBarry Song "1897,1900-1901,1904-1905,1908-1909,1912-1913,1916-1917,1920,1924,1928,1932,1936,1940,1944,1948,1952-1953,1956-19"
1119291f93caSBarry Song "57,1960-1961,1964-1965,1968-1969,1972-1973,1976-1977,1980-1981,1984,1988,1992,1996,2000,2004,2008,2012,2016-2017"
1120291f93caSBarry Song ",2020-2021,2024-2025,2028-2029,2032-2033,2036-2037,2040-2041,2044-2045,2048,2052,2056,2060,2064,2068,2072,2076,2"
1121291f93caSBarry Song "080-2081,2084-2085,2088-2089,2092-2093,2096-2097,2100-2101,2104-2105,2108-2109,2112,2116,2120,2124,2128,2132,213"
1122291f93caSBarry Song "6,2140,2144-2145,2148-2149,2152-2153,2156-2157,2160-2161,2164-2165,2168-2169,2172-2173,2176,2180,2184,2188,2192,"
1123291f93caSBarry Song "2196,2200,2204,2208-2209,2212-2213,2216-2217,2220-2221,2224-2225,2228-2229,2232-2233,2236-2237,2240,2244,2248,22"
1124291f93caSBarry Song "52,2256,2260,2264,2268,2272-2273,2276-2277,2280-2281,2284-2285,2288-2289,2292-2293,2296-2297,2300-2301,2304,2308"
1125291f93caSBarry Song ",2312,2316,2320,2324,2328,2332,2336-2337,2340-2341,2344-2345,2348-2349,2352-2353,2356-2357,2360-2361,2364-2365,2"
1126291f93caSBarry Song "368,2372,2376,2380,2384,2388,2392,2396,2400-2401,2404-2405,2408-2409,2412-2413,2416-2417,2420-2421,2424-2425,242"
1127291f93caSBarry Song "8-2429,2432,2436,2440,2444,2448,2452,2456,2460,2464-2465,2468-2469,2472-2473,2476-2477,2480-2481,2484-2485,2488-"
1128291f93caSBarry Song "2489,2492-2493,2496,2500,2504,2508,2512,2516,2520,2524,2528-2529,2532-2533,2536-2537,2540-2541,2544-2545,2548-25"
1129291f93caSBarry Song "49,2552-2553,2556-2557\n";
1130291f93caSBarry Song
1131291f93caSBarry Song static const struct test_bitmap_print test_print[] __initconst = {
1132291f93caSBarry Song { small_bitmap, sizeof(small_bitmap) * BITS_PER_BYTE, small_mask, small_list },
1133291f93caSBarry Song { large_bitmap, sizeof(large_bitmap) * BITS_PER_BYTE, large_mask, large_list },
1134291f93caSBarry Song };
1135291f93caSBarry Song
test_bitmap_print_buf(void)1136291f93caSBarry Song static void __init test_bitmap_print_buf(void)
1137291f93caSBarry Song {
1138291f93caSBarry Song int i;
1139291f93caSBarry Song
1140291f93caSBarry Song for (i = 0; i < ARRAY_SIZE(test_print); i++) {
1141291f93caSBarry Song const struct test_bitmap_print *t = &test_print[i];
1142291f93caSBarry Song int n;
1143291f93caSBarry Song
1144291f93caSBarry Song n = bitmap_print_bitmask_to_buf(print_buf, t->bitmap, t->nbits,
1145291f93caSBarry Song 0, 2 * PAGE_SIZE);
1146291f93caSBarry Song expect_eq_uint(strlen(t->mask) + 1, n);
1147291f93caSBarry Song expect_eq_str(t->mask, print_buf, n);
1148291f93caSBarry Song
1149291f93caSBarry Song n = bitmap_print_list_to_buf(print_buf, t->bitmap, t->nbits,
1150291f93caSBarry Song 0, 2 * PAGE_SIZE);
1151291f93caSBarry Song expect_eq_uint(strlen(t->list) + 1, n);
1152291f93caSBarry Song expect_eq_str(t->list, print_buf, n);
1153291f93caSBarry Song
1154291f93caSBarry Song /* test by non-zero offset */
1155291f93caSBarry Song if (strlen(t->list) > PAGE_SIZE) {
1156291f93caSBarry Song n = bitmap_print_list_to_buf(print_buf, t->bitmap, t->nbits,
1157291f93caSBarry Song PAGE_SIZE, PAGE_SIZE);
1158291f93caSBarry Song expect_eq_uint(strlen(t->list) + 1 - PAGE_SIZE, n);
1159291f93caSBarry Song expect_eq_str(t->list + PAGE_SIZE, print_buf, n);
1160291f93caSBarry Song }
1161291f93caSBarry Song }
1162291f93caSBarry Song }
1163291f93caSBarry Song
1164*2356d198SYury Norov /*
1165*2356d198SYury Norov * FIXME: Clang breaks compile-time evaluations when KASAN and GCOV are enabled.
1166*2356d198SYury Norov * To workaround it, GCOV is force-disabled in Makefile for this configuration.
1167*2356d198SYury Norov */
test_bitmap_const_eval(void)1168dc34d503SAlexander Lobakin static void __init test_bitmap_const_eval(void)
1169dc34d503SAlexander Lobakin {
1170dc34d503SAlexander Lobakin DECLARE_BITMAP(bitmap, BITS_PER_LONG);
1171dc34d503SAlexander Lobakin unsigned long initvar = BIT(2);
1172dc34d503SAlexander Lobakin unsigned long bitopvar = 0;
1173dc34d503SAlexander Lobakin unsigned long var = 0;
1174dc34d503SAlexander Lobakin int res;
1175dc34d503SAlexander Lobakin
1176dc34d503SAlexander Lobakin /*
1177dc34d503SAlexander Lobakin * Compilers must be able to optimize all of those to compile-time
1178dc34d503SAlexander Lobakin * constants on any supported optimization level (-O2, -Os) and any
1179dc34d503SAlexander Lobakin * architecture. Otherwise, trigger a build bug.
1180dc34d503SAlexander Lobakin * The whole function gets optimized out then, there's nothing to do
1181dc34d503SAlexander Lobakin * in runtime.
1182dc34d503SAlexander Lobakin */
1183dc34d503SAlexander Lobakin
1184dc34d503SAlexander Lobakin /*
1185dc34d503SAlexander Lobakin * Equals to `unsigned long bitmap[1] = { GENMASK(6, 5), }`.
1186dc34d503SAlexander Lobakin * Clang on s390 optimizes bitops at compile-time as intended, but at
1187dc34d503SAlexander Lobakin * the same time stops treating @bitmap and @bitopvar as compile-time
1188dc34d503SAlexander Lobakin * constants after regular test_bit() is executed, thus triggering the
1189dc34d503SAlexander Lobakin * build bugs below. So, call const_test_bit() there directly until
1190dc34d503SAlexander Lobakin * the compiler is fixed.
1191dc34d503SAlexander Lobakin */
1192dc34d503SAlexander Lobakin bitmap_clear(bitmap, 0, BITS_PER_LONG);
1193dc34d503SAlexander Lobakin if (!test_bit(7, bitmap))
1194dc34d503SAlexander Lobakin bitmap_set(bitmap, 5, 2);
1195dc34d503SAlexander Lobakin
1196dc34d503SAlexander Lobakin /* Equals to `unsigned long bitopvar = BIT(20)` */
1197dc34d503SAlexander Lobakin __change_bit(31, &bitopvar);
1198dc34d503SAlexander Lobakin bitmap_shift_right(&bitopvar, &bitopvar, 11, BITS_PER_LONG);
1199dc34d503SAlexander Lobakin
1200dc34d503SAlexander Lobakin /* Equals to `unsigned long var = BIT(25)` */
1201dc34d503SAlexander Lobakin var |= BIT(25);
1202dc34d503SAlexander Lobakin if (var & BIT(0))
1203dc34d503SAlexander Lobakin var ^= GENMASK(9, 6);
1204dc34d503SAlexander Lobakin
1205dc34d503SAlexander Lobakin /* __const_hweight<32|64>(GENMASK(6, 5)) == 2 */
1206dc34d503SAlexander Lobakin res = bitmap_weight(bitmap, 20);
1207dc34d503SAlexander Lobakin BUILD_BUG_ON(!__builtin_constant_p(res));
1208dc34d503SAlexander Lobakin BUILD_BUG_ON(res != 2);
1209dc34d503SAlexander Lobakin
1210dc34d503SAlexander Lobakin /* !(BIT(31) & BIT(18)) == 1 */
1211dc34d503SAlexander Lobakin res = !test_bit(18, &bitopvar);
1212dc34d503SAlexander Lobakin BUILD_BUG_ON(!__builtin_constant_p(res));
1213dc34d503SAlexander Lobakin BUILD_BUG_ON(!res);
1214dc34d503SAlexander Lobakin
1215dc34d503SAlexander Lobakin /* BIT(2) & GENMASK(14, 8) == 0 */
1216dc34d503SAlexander Lobakin res = initvar & GENMASK(14, 8);
1217dc34d503SAlexander Lobakin BUILD_BUG_ON(!__builtin_constant_p(res));
1218dc34d503SAlexander Lobakin BUILD_BUG_ON(res);
1219dc34d503SAlexander Lobakin
1220dc34d503SAlexander Lobakin /* ~BIT(25) */
1221dc34d503SAlexander Lobakin BUILD_BUG_ON(!__builtin_constant_p(~var));
1222dc34d503SAlexander Lobakin BUILD_BUG_ON(~var != ~BIT(25));
1223dc34d503SAlexander Lobakin }
1224dc34d503SAlexander Lobakin
selftest(void)12256b1a4d5bSTobin C. Harding static void __init selftest(void)
12265fd003f5SDavid Decotigny {
1227ee3527bdSAndy Shevchenko test_zero_clear();
1228978f369cSAndy Shevchenko test_fill_set();
1229fe81814cSAndy Shevchenko test_copy();
123030544ed5SAndy Shevchenko test_replace();
12313aa56885SYury Norov test_bitmap_arr32();
12322c523550SYury Norov test_bitmap_arr64();
12337eb2e94eSYury Norov test_bitmap_parse();
12346df0d464SYury Norov test_bitmap_parselist();
1235db731300SYury Norov test_bitmap_printlist();
12363cc78125SMatthew Wilcox test_mem_optimisations();
1237bcb32a1dSStefano Brivio test_bitmap_cut();
1238291f93caSBarry Song test_bitmap_print_buf();
1239dc34d503SAlexander Lobakin test_bitmap_const_eval();
1240e3783c80SYury Norov
1241e3783c80SYury Norov test_find_nth_bit();
12428173aa26SYury Norov test_for_each_set_bit();
12438173aa26SYury Norov test_for_each_set_bit_from();
12448173aa26SYury Norov test_for_each_clear_bit();
12458173aa26SYury Norov test_for_each_clear_bit_from();
12468173aa26SYury Norov test_for_each_set_bitrange();
12478173aa26SYury Norov test_for_each_clear_bitrange();
12488173aa26SYury Norov test_for_each_set_bitrange_from();
12498173aa26SYury Norov test_for_each_clear_bitrange_from();
12508173aa26SYury Norov test_for_each_set_clump8();
12518173aa26SYury Norov test_for_each_set_bit_wrap();
12525fd003f5SDavid Decotigny }
12535fd003f5SDavid Decotigny
12546b1a4d5bSTobin C. Harding KSTM_MODULE_LOADERS(test_bitmap);
12555fd003f5SDavid Decotigny MODULE_AUTHOR("david decotigny <david.decotigny@googlers.com>");
12565fd003f5SDavid Decotigny MODULE_LICENSE("GPL");
1257