diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 8 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/ioremap.c | 11 | ||||
-rw-r--r-- | lib/mpi/longlong.h | 16 | ||||
-rw-r--r-- | lib/rbtree.c | 40 | ||||
-rw-r--r-- | lib/string.c | 11 | ||||
-rw-r--r-- | lib/string_helpers.c | 77 | ||||
-rw-r--r-- | lib/test_meminit.c | 364 | ||||
-rw-r--r-- | lib/test_overflow.c | 11 | ||||
-rw-r--r-- | lib/test_string.c | 83 |
10 files changed, 531 insertions, 91 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a858b55e8ac7..bc6673ab3a08 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -2076,6 +2076,14 @@ config TEST_STACKINIT | |||
2076 | 2076 | ||
2077 | If unsure, say N. | 2077 | If unsure, say N. |
2078 | 2078 | ||
2079 | config TEST_MEMINIT | ||
2080 | tristate "Test heap/page initialization" | ||
2081 | help | ||
2082 | Test if the kernel is zero-initializing heap and page allocations. | ||
2083 | This can be useful to test init_on_alloc and init_on_free features. | ||
2084 | |||
2085 | If unsure, say N. | ||
2086 | |||
2079 | endif # RUNTIME_TESTING_MENU | 2087 | endif # RUNTIME_TESTING_MENU |
2080 | 2088 | ||
2081 | config MEMTEST | 2089 | config MEMTEST |
diff --git a/lib/Makefile b/lib/Makefile index fdd56bc219b8..59067f51f3ab 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -92,6 +92,7 @@ obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o | |||
92 | obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o | 92 | obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o |
93 | obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o | 93 | obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o |
94 | obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o | 94 | obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o |
95 | obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o | ||
95 | 96 | ||
96 | obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/ | 97 | obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/ |
97 | 98 | ||
diff --git a/lib/ioremap.c b/lib/ioremap.c index 063213685563..0a2ffadc6d71 100644 --- a/lib/ioremap.c +++ b/lib/ioremap.c | |||
@@ -30,6 +30,8 @@ early_param("nohugeiomap", set_nohugeiomap); | |||
30 | void __init ioremap_huge_init(void) | 30 | void __init ioremap_huge_init(void) |
31 | { | 31 | { |
32 | if (!ioremap_huge_disabled) { | 32 | if (!ioremap_huge_disabled) { |
33 | if (arch_ioremap_p4d_supported()) | ||
34 | ioremap_p4d_capable = 1; | ||
33 | if (arch_ioremap_pud_supported()) | 35 | if (arch_ioremap_pud_supported()) |
34 | ioremap_pud_capable = 1; | 36 | ioremap_pud_capable = 1; |
35 | if (arch_ioremap_pmd_supported()) | 37 | if (arch_ioremap_pmd_supported()) |
@@ -86,6 +88,9 @@ static int ioremap_try_huge_pmd(pmd_t *pmd, unsigned long addr, | |||
86 | if ((end - addr) != PMD_SIZE) | 88 | if ((end - addr) != PMD_SIZE) |
87 | return 0; | 89 | return 0; |
88 | 90 | ||
91 | if (!IS_ALIGNED(addr, PMD_SIZE)) | ||
92 | return 0; | ||
93 | |||
89 | if (!IS_ALIGNED(phys_addr, PMD_SIZE)) | 94 | if (!IS_ALIGNED(phys_addr, PMD_SIZE)) |
90 | return 0; | 95 | return 0; |
91 | 96 | ||
@@ -126,6 +131,9 @@ static int ioremap_try_huge_pud(pud_t *pud, unsigned long addr, | |||
126 | if ((end - addr) != PUD_SIZE) | 131 | if ((end - addr) != PUD_SIZE) |
127 | return 0; | 132 | return 0; |
128 | 133 | ||
134 | if (!IS_ALIGNED(addr, PUD_SIZE)) | ||
135 | return 0; | ||
136 | |||
129 | if (!IS_ALIGNED(phys_addr, PUD_SIZE)) | 137 | if (!IS_ALIGNED(phys_addr, PUD_SIZE)) |
130 | return 0; | 138 | return 0; |
131 | 139 | ||
@@ -166,6 +174,9 @@ static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr, | |||
166 | if ((end - addr) != P4D_SIZE) | 174 | if ((end - addr) != P4D_SIZE) |
167 | return 0; | 175 | return 0; |
168 | 176 | ||
177 | if (!IS_ALIGNED(addr, P4D_SIZE)) | ||
178 | return 0; | ||
179 | |||
169 | if (!IS_ALIGNED(phys_addr, P4D_SIZE)) | 180 | if (!IS_ALIGNED(phys_addr, P4D_SIZE)) |
170 | return 0; | 181 | return 0; |
171 | 182 | ||
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 08c60d10747f..3bb6260d8f42 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h | |||
@@ -397,8 +397,8 @@ do { \ | |||
397 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ | 397 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ |
398 | __asm__ ("addl %5,%1\n" \ | 398 | __asm__ ("addl %5,%1\n" \ |
399 | "adcl %3,%0" \ | 399 | "adcl %3,%0" \ |
400 | : "=r" ((USItype)(sh)), \ | 400 | : "=r" (sh), \ |
401 | "=&r" ((USItype)(sl)) \ | 401 | "=&r" (sl) \ |
402 | : "%0" ((USItype)(ah)), \ | 402 | : "%0" ((USItype)(ah)), \ |
403 | "g" ((USItype)(bh)), \ | 403 | "g" ((USItype)(bh)), \ |
404 | "%1" ((USItype)(al)), \ | 404 | "%1" ((USItype)(al)), \ |
@@ -406,22 +406,22 @@ do { \ | |||
406 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ | 406 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ |
407 | __asm__ ("subl %5,%1\n" \ | 407 | __asm__ ("subl %5,%1\n" \ |
408 | "sbbl %3,%0" \ | 408 | "sbbl %3,%0" \ |
409 | : "=r" ((USItype)(sh)), \ | 409 | : "=r" (sh), \ |
410 | "=&r" ((USItype)(sl)) \ | 410 | "=&r" (sl) \ |
411 | : "0" ((USItype)(ah)), \ | 411 | : "0" ((USItype)(ah)), \ |
412 | "g" ((USItype)(bh)), \ | 412 | "g" ((USItype)(bh)), \ |
413 | "1" ((USItype)(al)), \ | 413 | "1" ((USItype)(al)), \ |
414 | "g" ((USItype)(bl))) | 414 | "g" ((USItype)(bl))) |
415 | #define umul_ppmm(w1, w0, u, v) \ | 415 | #define umul_ppmm(w1, w0, u, v) \ |
416 | __asm__ ("mull %3" \ | 416 | __asm__ ("mull %3" \ |
417 | : "=a" ((USItype)(w0)), \ | 417 | : "=a" (w0), \ |
418 | "=d" ((USItype)(w1)) \ | 418 | "=d" (w1) \ |
419 | : "%0" ((USItype)(u)), \ | 419 | : "%0" ((USItype)(u)), \ |
420 | "rm" ((USItype)(v))) | 420 | "rm" ((USItype)(v))) |
421 | #define udiv_qrnnd(q, r, n1, n0, d) \ | 421 | #define udiv_qrnnd(q, r, n1, n0, d) \ |
422 | __asm__ ("divl %4" \ | 422 | __asm__ ("divl %4" \ |
423 | : "=a" ((USItype)(q)), \ | 423 | : "=a" (q), \ |
424 | "=d" ((USItype)(r)) \ | 424 | "=d" (r) \ |
425 | : "0" ((USItype)(n0)), \ | 425 | : "0" ((USItype)(n0)), \ |
426 | "1" ((USItype)(n1)), \ | 426 | "1" ((USItype)(n1)), \ |
427 | "rm" ((USItype)(d))) | 427 | "rm" ((USItype)(d))) |
diff --git a/lib/rbtree.c b/lib/rbtree.c index 1ef6e25d031c..abc86c6a3177 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
@@ -83,14 +83,10 @@ __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, | |||
83 | 83 | ||
84 | static __always_inline void | 84 | static __always_inline void |
85 | __rb_insert(struct rb_node *node, struct rb_root *root, | 85 | __rb_insert(struct rb_node *node, struct rb_root *root, |
86 | bool newleft, struct rb_node **leftmost, | ||
87 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | 86 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) |
88 | { | 87 | { |
89 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; | 88 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; |
90 | 89 | ||
91 | if (newleft) | ||
92 | *leftmost = node; | ||
93 | |||
94 | while (true) { | 90 | while (true) { |
95 | /* | 91 | /* |
96 | * Loop invariant: node is red. | 92 | * Loop invariant: node is red. |
@@ -437,38 +433,19 @@ static const struct rb_augment_callbacks dummy_callbacks = { | |||
437 | 433 | ||
438 | void rb_insert_color(struct rb_node *node, struct rb_root *root) | 434 | void rb_insert_color(struct rb_node *node, struct rb_root *root) |
439 | { | 435 | { |
440 | __rb_insert(node, root, false, NULL, dummy_rotate); | 436 | __rb_insert(node, root, dummy_rotate); |
441 | } | 437 | } |
442 | EXPORT_SYMBOL(rb_insert_color); | 438 | EXPORT_SYMBOL(rb_insert_color); |
443 | 439 | ||
444 | void rb_erase(struct rb_node *node, struct rb_root *root) | 440 | void rb_erase(struct rb_node *node, struct rb_root *root) |
445 | { | 441 | { |
446 | struct rb_node *rebalance; | 442 | struct rb_node *rebalance; |
447 | rebalance = __rb_erase_augmented(node, root, | 443 | rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); |
448 | NULL, &dummy_callbacks); | ||
449 | if (rebalance) | 444 | if (rebalance) |
450 | ____rb_erase_color(rebalance, root, dummy_rotate); | 445 | ____rb_erase_color(rebalance, root, dummy_rotate); |
451 | } | 446 | } |
452 | EXPORT_SYMBOL(rb_erase); | 447 | EXPORT_SYMBOL(rb_erase); |
453 | 448 | ||
454 | void rb_insert_color_cached(struct rb_node *node, | ||
455 | struct rb_root_cached *root, bool leftmost) | ||
456 | { | ||
457 | __rb_insert(node, &root->rb_root, leftmost, | ||
458 | &root->rb_leftmost, dummy_rotate); | ||
459 | } | ||
460 | EXPORT_SYMBOL(rb_insert_color_cached); | ||
461 | |||
462 | void rb_erase_cached(struct rb_node *node, struct rb_root_cached *root) | ||
463 | { | ||
464 | struct rb_node *rebalance; | ||
465 | rebalance = __rb_erase_augmented(node, &root->rb_root, | ||
466 | &root->rb_leftmost, &dummy_callbacks); | ||
467 | if (rebalance) | ||
468 | ____rb_erase_color(rebalance, &root->rb_root, dummy_rotate); | ||
469 | } | ||
470 | EXPORT_SYMBOL(rb_erase_cached); | ||
471 | |||
472 | /* | 449 | /* |
473 | * Augmented rbtree manipulation functions. | 450 | * Augmented rbtree manipulation functions. |
474 | * | 451 | * |
@@ -477,10 +454,9 @@ EXPORT_SYMBOL(rb_erase_cached); | |||
477 | */ | 454 | */ |
478 | 455 | ||
479 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, | 456 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, |
480 | bool newleft, struct rb_node **leftmost, | ||
481 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | 457 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) |
482 | { | 458 | { |
483 | __rb_insert(node, root, newleft, leftmost, augment_rotate); | 459 | __rb_insert(node, root, augment_rotate); |
484 | } | 460 | } |
485 | EXPORT_SYMBOL(__rb_insert_augmented); | 461 | EXPORT_SYMBOL(__rb_insert_augmented); |
486 | 462 | ||
@@ -591,16 +567,6 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, | |||
591 | } | 567 | } |
592 | EXPORT_SYMBOL(rb_replace_node); | 568 | EXPORT_SYMBOL(rb_replace_node); |
593 | 569 | ||
594 | void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, | ||
595 | struct rb_root_cached *root) | ||
596 | { | ||
597 | rb_replace_node(victim, new, &root->rb_root); | ||
598 | |||
599 | if (root->rb_leftmost == victim) | ||
600 | root->rb_leftmost = new; | ||
601 | } | ||
602 | EXPORT_SYMBOL(rb_replace_node_cached); | ||
603 | |||
604 | void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, | 570 | void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, |
605 | struct rb_root *root) | 571 | struct rb_root *root) |
606 | { | 572 | { |
diff --git a/lib/string.c b/lib/string.c index 6016eb3ac73d..461fb620f85f 100644 --- a/lib/string.c +++ b/lib/string.c | |||
@@ -400,6 +400,9 @@ EXPORT_SYMBOL(strncmp); | |||
400 | * strchr - Find the first occurrence of a character in a string | 400 | * strchr - Find the first occurrence of a character in a string |
401 | * @s: The string to be searched | 401 | * @s: The string to be searched |
402 | * @c: The character to search for | 402 | * @c: The character to search for |
403 | * | ||
404 | * Note that the %NUL-terminator is considered part of the string, and can | ||
405 | * be searched for. | ||
403 | */ | 406 | */ |
404 | char *strchr(const char *s, int c) | 407 | char *strchr(const char *s, int c) |
405 | { | 408 | { |
@@ -453,12 +456,18 @@ EXPORT_SYMBOL(strrchr); | |||
453 | * @s: The string to be searched | 456 | * @s: The string to be searched |
454 | * @count: The number of characters to be searched | 457 | * @count: The number of characters to be searched |
455 | * @c: The character to search for | 458 | * @c: The character to search for |
459 | * | ||
460 | * Note that the %NUL-terminator is considered part of the string, and can | ||
461 | * be searched for. | ||
456 | */ | 462 | */ |
457 | char *strnchr(const char *s, size_t count, int c) | 463 | char *strnchr(const char *s, size_t count, int c) |
458 | { | 464 | { |
459 | for (; count-- && *s != '\0'; ++s) | 465 | while (count--) { |
460 | if (*s == (char)c) | 466 | if (*s == (char)c) |
461 | return (char *)s; | 467 | return (char *)s; |
468 | if (*s++ == '\0') | ||
469 | break; | ||
470 | } | ||
462 | return NULL; | 471 | return NULL; |
463 | } | 472 | } |
464 | EXPORT_SYMBOL(strnchr); | 473 | EXPORT_SYMBOL(strnchr); |
diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 3a90a9e2b94a..963050c0283e 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c | |||
@@ -231,35 +231,36 @@ static bool unescape_special(char **src, char **dst) | |||
231 | * @src: source buffer (escaped) | 231 | * @src: source buffer (escaped) |
232 | * @dst: destination buffer (unescaped) | 232 | * @dst: destination buffer (unescaped) |
233 | * @size: size of the destination buffer (0 to unlimit) | 233 | * @size: size of the destination buffer (0 to unlimit) |
234 | * @flags: combination of the flags (bitwise OR): | 234 | * @flags: combination of the flags. |
235 | * %UNESCAPE_SPACE: | 235 | * |
236 | * Description: | ||
237 | * The function unquotes characters in the given string. | ||
238 | * | ||
239 | * Because the size of the output will be the same as or less than the size of | ||
240 | * the input, the transformation may be performed in place. | ||
241 | * | ||
242 | * Caller must provide valid source and destination pointers. Be aware that | ||
243 | * destination buffer will always be NULL-terminated. Source string must be | ||
244 | * NULL-terminated as well. The supported flags are:: | ||
245 | * | ||
246 | * UNESCAPE_SPACE: | ||
236 | * '\f' - form feed | 247 | * '\f' - form feed |
237 | * '\n' - new line | 248 | * '\n' - new line |
238 | * '\r' - carriage return | 249 | * '\r' - carriage return |
239 | * '\t' - horizontal tab | 250 | * '\t' - horizontal tab |
240 | * '\v' - vertical tab | 251 | * '\v' - vertical tab |
241 | * %UNESCAPE_OCTAL: | 252 | * UNESCAPE_OCTAL: |
242 | * '\NNN' - byte with octal value NNN (1 to 3 digits) | 253 | * '\NNN' - byte with octal value NNN (1 to 3 digits) |
243 | * %UNESCAPE_HEX: | 254 | * UNESCAPE_HEX: |
244 | * '\xHH' - byte with hexadecimal value HH (1 to 2 digits) | 255 | * '\xHH' - byte with hexadecimal value HH (1 to 2 digits) |
245 | * %UNESCAPE_SPECIAL: | 256 | * UNESCAPE_SPECIAL: |
246 | * '\"' - double quote | 257 | * '\"' - double quote |
247 | * '\\' - backslash | 258 | * '\\' - backslash |
248 | * '\a' - alert (BEL) | 259 | * '\a' - alert (BEL) |
249 | * '\e' - escape | 260 | * '\e' - escape |
250 | * %UNESCAPE_ANY: | 261 | * UNESCAPE_ANY: |
251 | * all previous together | 262 | * all previous together |
252 | * | 263 | * |
253 | * Description: | ||
254 | * The function unquotes characters in the given string. | ||
255 | * | ||
256 | * Because the size of the output will be the same as or less than the size of | ||
257 | * the input, the transformation may be performed in place. | ||
258 | * | ||
259 | * Caller must provide valid source and destination pointers. Be aware that | ||
260 | * destination buffer will always be NULL-terminated. Source string must be | ||
261 | * NULL-terminated as well. | ||
262 | * | ||
263 | * Return: | 264 | * Return: |
264 | * The amount of the characters processed to the destination buffer excluding | 265 | * The amount of the characters processed to the destination buffer excluding |
265 | * trailing '\0' is returned. | 266 | * trailing '\0' is returned. |
@@ -441,7 +442,29 @@ static bool escape_hex(unsigned char c, char **dst, char *end) | |||
441 | * @isz: source buffer size | 442 | * @isz: source buffer size |
442 | * @dst: destination buffer (escaped) | 443 | * @dst: destination buffer (escaped) |
443 | * @osz: destination buffer size | 444 | * @osz: destination buffer size |
444 | * @flags: combination of the flags (bitwise OR): | 445 | * @flags: combination of the flags |
446 | * @only: NULL-terminated string containing characters used to limit | ||
447 | * the selected escape class. If characters are included in @only | ||
448 | * that would not normally be escaped by the classes selected | ||
449 | * in @flags, they will be copied to @dst unescaped. | ||
450 | * | ||
451 | * Description: | ||
452 | * The process of escaping byte buffer includes several parts. They are applied | ||
453 | * in the following sequence. | ||
454 | * | ||
455 | * 1. The character is matched to the printable class, if asked, and in | ||
456 | * case of match it passes through to the output. | ||
457 | * 2. The character is not matched to the one from @only string and thus | ||
458 | * must go as-is to the output. | ||
459 | * 3. The character is checked if it falls into the class given by @flags. | ||
460 | * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any | ||
461 | * character. Note that they actually can't go together, otherwise | ||
462 | * %ESCAPE_HEX will be ignored. | ||
463 | * | ||
464 | * Caller must provide valid source and destination pointers. Be aware that | ||
465 | * destination buffer will not be NULL-terminated, thus caller have to append | ||
466 | * it if needs. The supported flags are:: | ||
467 | * | ||
445 | * %ESCAPE_SPACE: (special white space, not space itself) | 468 | * %ESCAPE_SPACE: (special white space, not space itself) |
446 | * '\f' - form feed | 469 | * '\f' - form feed |
447 | * '\n' - new line | 470 | * '\n' - new line |
@@ -464,26 +487,6 @@ static bool escape_hex(unsigned char c, char **dst, char *end) | |||
464 | * all previous together | 487 | * all previous together |
465 | * %ESCAPE_HEX: | 488 | * %ESCAPE_HEX: |
466 | * '\xHH' - byte with hexadecimal value HH (2 digits) | 489 | * '\xHH' - byte with hexadecimal value HH (2 digits) |
467 | * @only: NULL-terminated string containing characters used to limit | ||
468 | * the selected escape class. If characters are included in @only | ||
469 | * that would not normally be escaped by the classes selected | ||
470 | * in @flags, they will be copied to @dst unescaped. | ||
471 | * | ||
472 | * Description: | ||
473 | * The process of escaping byte buffer includes several parts. They are applied | ||
474 | * in the following sequence. | ||
475 | * 1. The character is matched to the printable class, if asked, and in | ||
476 | * case of match it passes through to the output. | ||
477 | * 2. The character is not matched to the one from @only string and thus | ||
478 | * must go as-is to the output. | ||
479 | * 3. The character is checked if it falls into the class given by @flags. | ||
480 | * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any | ||
481 | * character. Note that they actually can't go together, otherwise | ||
482 | * %ESCAPE_HEX will be ignored. | ||
483 | * | ||
484 | * Caller must provide valid source and destination pointers. Be aware that | ||
485 | * destination buffer will not be NULL-terminated, thus caller have to append | ||
486 | * it if needs. | ||
487 | * | 490 | * |
488 | * Return: | 491 | * Return: |
489 | * The total size of the escaped output that would be generated for | 492 | * The total size of the escaped output that would be generated for |
diff --git a/lib/test_meminit.c b/lib/test_meminit.c new file mode 100644 index 000000000000..62d19f270cad --- /dev/null +++ b/lib/test_meminit.c | |||
@@ -0,0 +1,364 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Test cases for SL[AOU]B/page initialization at alloc/free time. | ||
4 | */ | ||
5 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
6 | |||
7 | #include <linux/init.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/vmalloc.h> | ||
14 | |||
15 | #define GARBAGE_INT (0x09A7BA9E) | ||
16 | #define GARBAGE_BYTE (0x9E) | ||
17 | |||
18 | #define REPORT_FAILURES_IN_FN() \ | ||
19 | do { \ | ||
20 | if (failures) \ | ||
21 | pr_info("%s failed %d out of %d times\n", \ | ||
22 | __func__, failures, num_tests); \ | ||
23 | else \ | ||
24 | pr_info("all %d tests in %s passed\n", \ | ||
25 | num_tests, __func__); \ | ||
26 | } while (0) | ||
27 | |||
28 | /* Calculate the number of uninitialized bytes in the buffer. */ | ||
29 | static int __init count_nonzero_bytes(void *ptr, size_t size) | ||
30 | { | ||
31 | int i, ret = 0; | ||
32 | unsigned char *p = (unsigned char *)ptr; | ||
33 | |||
34 | for (i = 0; i < size; i++) | ||
35 | if (p[i]) | ||
36 | ret++; | ||
37 | return ret; | ||
38 | } | ||
39 | |||
40 | /* Fill a buffer with garbage, skipping |skip| first bytes. */ | ||
41 | static void __init fill_with_garbage_skip(void *ptr, int size, size_t skip) | ||
42 | { | ||
43 | unsigned int *p = (unsigned int *)((char *)ptr + skip); | ||
44 | int i = 0; | ||
45 | |||
46 | WARN_ON(skip > size); | ||
47 | size -= skip; | ||
48 | |||
49 | while (size >= sizeof(*p)) { | ||
50 | p[i] = GARBAGE_INT; | ||
51 | i++; | ||
52 | size -= sizeof(*p); | ||
53 | } | ||
54 | if (size) | ||
55 | memset(&p[i], GARBAGE_BYTE, size); | ||
56 | } | ||
57 | |||
58 | static void __init fill_with_garbage(void *ptr, size_t size) | ||
59 | { | ||
60 | fill_with_garbage_skip(ptr, size, 0); | ||
61 | } | ||
62 | |||
63 | static int __init do_alloc_pages_order(int order, int *total_failures) | ||
64 | { | ||
65 | struct page *page; | ||
66 | void *buf; | ||
67 | size_t size = PAGE_SIZE << order; | ||
68 | |||
69 | page = alloc_pages(GFP_KERNEL, order); | ||
70 | buf = page_address(page); | ||
71 | fill_with_garbage(buf, size); | ||
72 | __free_pages(page, order); | ||
73 | |||
74 | page = alloc_pages(GFP_KERNEL, order); | ||
75 | buf = page_address(page); | ||
76 | if (count_nonzero_bytes(buf, size)) | ||
77 | (*total_failures)++; | ||
78 | fill_with_garbage(buf, size); | ||
79 | __free_pages(page, order); | ||
80 | return 1; | ||
81 | } | ||
82 | |||
83 | /* Test the page allocator by calling alloc_pages with different orders. */ | ||
84 | static int __init test_pages(int *total_failures) | ||
85 | { | ||
86 | int failures = 0, num_tests = 0; | ||
87 | int i; | ||
88 | |||
89 | for (i = 0; i < 10; i++) | ||
90 | num_tests += do_alloc_pages_order(i, &failures); | ||
91 | |||
92 | REPORT_FAILURES_IN_FN(); | ||
93 | *total_failures += failures; | ||
94 | return num_tests; | ||
95 | } | ||
96 | |||
97 | /* Test kmalloc() with given parameters. */ | ||
98 | static int __init do_kmalloc_size(size_t size, int *total_failures) | ||
99 | { | ||
100 | void *buf; | ||
101 | |||
102 | buf = kmalloc(size, GFP_KERNEL); | ||
103 | fill_with_garbage(buf, size); | ||
104 | kfree(buf); | ||
105 | |||
106 | buf = kmalloc(size, GFP_KERNEL); | ||
107 | if (count_nonzero_bytes(buf, size)) | ||
108 | (*total_failures)++; | ||
109 | fill_with_garbage(buf, size); | ||
110 | kfree(buf); | ||
111 | return 1; | ||
112 | } | ||
113 | |||
114 | /* Test vmalloc() with given parameters. */ | ||
115 | static int __init do_vmalloc_size(size_t size, int *total_failures) | ||
116 | { | ||
117 | void *buf; | ||
118 | |||
119 | buf = vmalloc(size); | ||
120 | fill_with_garbage(buf, size); | ||
121 | vfree(buf); | ||
122 | |||
123 | buf = vmalloc(size); | ||
124 | if (count_nonzero_bytes(buf, size)) | ||
125 | (*total_failures)++; | ||
126 | fill_with_garbage(buf, size); | ||
127 | vfree(buf); | ||
128 | return 1; | ||
129 | } | ||
130 | |||
131 | /* Test kmalloc()/vmalloc() by allocating objects of different sizes. */ | ||
132 | static int __init test_kvmalloc(int *total_failures) | ||
133 | { | ||
134 | int failures = 0, num_tests = 0; | ||
135 | int i, size; | ||
136 | |||
137 | for (i = 0; i < 20; i++) { | ||
138 | size = 1 << i; | ||
139 | num_tests += do_kmalloc_size(size, &failures); | ||
140 | num_tests += do_vmalloc_size(size, &failures); | ||
141 | } | ||
142 | |||
143 | REPORT_FAILURES_IN_FN(); | ||
144 | *total_failures += failures; | ||
145 | return num_tests; | ||
146 | } | ||
147 | |||
148 | #define CTOR_BYTES (sizeof(unsigned int)) | ||
149 | #define CTOR_PATTERN (0x41414141) | ||
150 | /* Initialize the first 4 bytes of the object. */ | ||
151 | static void test_ctor(void *obj) | ||
152 | { | ||
153 | *(unsigned int *)obj = CTOR_PATTERN; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Check the invariants for the buffer allocated from a slab cache. | ||
158 | * If the cache has a test constructor, the first 4 bytes of the object must | ||
159 | * always remain equal to CTOR_PATTERN. | ||
160 | * If the cache isn't an RCU-typesafe one, or if the allocation is done with | ||
161 | * __GFP_ZERO, then the object contents must be zeroed after allocation. | ||
162 | * If the cache is an RCU-typesafe one, the object contents must never be | ||
163 | * zeroed after the first use. This is checked by memcmp() in | ||
164 | * do_kmem_cache_size(). | ||
165 | */ | ||
166 | static bool __init check_buf(void *buf, int size, bool want_ctor, | ||
167 | bool want_rcu, bool want_zero) | ||
168 | { | ||
169 | int bytes; | ||
170 | bool fail = false; | ||
171 | |||
172 | bytes = count_nonzero_bytes(buf, size); | ||
173 | WARN_ON(want_ctor && want_zero); | ||
174 | if (want_zero) | ||
175 | return bytes; | ||
176 | if (want_ctor) { | ||
177 | if (*(unsigned int *)buf != CTOR_PATTERN) | ||
178 | fail = 1; | ||
179 | } else { | ||
180 | if (bytes) | ||
181 | fail = !want_rcu; | ||
182 | } | ||
183 | return fail; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Test kmem_cache with given parameters: | ||
188 | * want_ctor - use a constructor; | ||
189 | * want_rcu - use SLAB_TYPESAFE_BY_RCU; | ||
190 | * want_zero - use __GFP_ZERO. | ||
191 | */ | ||
192 | static int __init do_kmem_cache_size(size_t size, bool want_ctor, | ||
193 | bool want_rcu, bool want_zero, | ||
194 | int *total_failures) | ||
195 | { | ||
196 | struct kmem_cache *c; | ||
197 | int iter; | ||
198 | bool fail = false; | ||
199 | gfp_t alloc_mask = GFP_KERNEL | (want_zero ? __GFP_ZERO : 0); | ||
200 | void *buf, *buf_copy; | ||
201 | |||
202 | c = kmem_cache_create("test_cache", size, 1, | ||
203 | want_rcu ? SLAB_TYPESAFE_BY_RCU : 0, | ||
204 | want_ctor ? test_ctor : NULL); | ||
205 | for (iter = 0; iter < 10; iter++) { | ||
206 | buf = kmem_cache_alloc(c, alloc_mask); | ||
207 | /* Check that buf is zeroed, if it must be. */ | ||
208 | fail = check_buf(buf, size, want_ctor, want_rcu, want_zero); | ||
209 | fill_with_garbage_skip(buf, size, want_ctor ? CTOR_BYTES : 0); | ||
210 | |||
211 | if (!want_rcu) { | ||
212 | kmem_cache_free(c, buf); | ||
213 | continue; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * If this is an RCU cache, use a critical section to ensure we | ||
218 | * can touch objects after they're freed. | ||
219 | */ | ||
220 | rcu_read_lock(); | ||
221 | /* | ||
222 | * Copy the buffer to check that it's not wiped on | ||
223 | * free(). | ||
224 | */ | ||
225 | buf_copy = kmalloc(size, GFP_KERNEL); | ||
226 | if (buf_copy) | ||
227 | memcpy(buf_copy, buf, size); | ||
228 | |||
229 | kmem_cache_free(c, buf); | ||
230 | /* | ||
231 | * Check that |buf| is intact after kmem_cache_free(). | ||
232 | * |want_zero| is false, because we wrote garbage to | ||
233 | * the buffer already. | ||
234 | */ | ||
235 | fail |= check_buf(buf, size, want_ctor, want_rcu, | ||
236 | false); | ||
237 | if (buf_copy) { | ||
238 | fail |= (bool)memcmp(buf, buf_copy, size); | ||
239 | kfree(buf_copy); | ||
240 | } | ||
241 | rcu_read_unlock(); | ||
242 | } | ||
243 | kmem_cache_destroy(c); | ||
244 | |||
245 | *total_failures += fail; | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Check that the data written to an RCU-allocated object survives | ||
251 | * reallocation. | ||
252 | */ | ||
253 | static int __init do_kmem_cache_rcu_persistent(int size, int *total_failures) | ||
254 | { | ||
255 | struct kmem_cache *c; | ||
256 | void *buf, *buf_contents, *saved_ptr; | ||
257 | void **used_objects; | ||
258 | int i, iter, maxiter = 1024; | ||
259 | bool fail = false; | ||
260 | |||
261 | c = kmem_cache_create("test_cache", size, size, SLAB_TYPESAFE_BY_RCU, | ||
262 | NULL); | ||
263 | buf = kmem_cache_alloc(c, GFP_KERNEL); | ||
264 | saved_ptr = buf; | ||
265 | fill_with_garbage(buf, size); | ||
266 | buf_contents = kmalloc(size, GFP_KERNEL); | ||
267 | if (!buf_contents) | ||
268 | goto out; | ||
269 | used_objects = kmalloc_array(maxiter, sizeof(void *), GFP_KERNEL); | ||
270 | if (!used_objects) { | ||
271 | kfree(buf_contents); | ||
272 | goto out; | ||
273 | } | ||
274 | memcpy(buf_contents, buf, size); | ||
275 | kmem_cache_free(c, buf); | ||
276 | /* | ||
277 | * Run for a fixed number of iterations. If we never hit saved_ptr, | ||
278 | * assume the test passes. | ||
279 | */ | ||
280 | for (iter = 0; iter < maxiter; iter++) { | ||
281 | buf = kmem_cache_alloc(c, GFP_KERNEL); | ||
282 | used_objects[iter] = buf; | ||
283 | if (buf == saved_ptr) { | ||
284 | fail = memcmp(buf_contents, buf, size); | ||
285 | for (i = 0; i <= iter; i++) | ||
286 | kmem_cache_free(c, used_objects[i]); | ||
287 | goto free_out; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | free_out: | ||
292 | kmem_cache_destroy(c); | ||
293 | kfree(buf_contents); | ||
294 | kfree(used_objects); | ||
295 | out: | ||
296 | *total_failures += fail; | ||
297 | return 1; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * Test kmem_cache allocation by creating caches of different sizes, with and | ||
302 | * without constructors, with and without SLAB_TYPESAFE_BY_RCU. | ||
303 | */ | ||
304 | static int __init test_kmemcache(int *total_failures) | ||
305 | { | ||
306 | int failures = 0, num_tests = 0; | ||
307 | int i, flags, size; | ||
308 | bool ctor, rcu, zero; | ||
309 | |||
310 | for (i = 0; i < 10; i++) { | ||
311 | size = 8 << i; | ||
312 | for (flags = 0; flags < 8; flags++) { | ||
313 | ctor = flags & 1; | ||
314 | rcu = flags & 2; | ||
315 | zero = flags & 4; | ||
316 | if (ctor & zero) | ||
317 | continue; | ||
318 | num_tests += do_kmem_cache_size(size, ctor, rcu, zero, | ||
319 | &failures); | ||
320 | } | ||
321 | } | ||
322 | REPORT_FAILURES_IN_FN(); | ||
323 | *total_failures += failures; | ||
324 | return num_tests; | ||
325 | } | ||
326 | |||
327 | /* Test the behavior of SLAB_TYPESAFE_BY_RCU caches of different sizes. */ | ||
328 | static int __init test_rcu_persistent(int *total_failures) | ||
329 | { | ||
330 | int failures = 0, num_tests = 0; | ||
331 | int i, size; | ||
332 | |||
333 | for (i = 0; i < 10; i++) { | ||
334 | size = 8 << i; | ||
335 | num_tests += do_kmem_cache_rcu_persistent(size, &failures); | ||
336 | } | ||
337 | REPORT_FAILURES_IN_FN(); | ||
338 | *total_failures += failures; | ||
339 | return num_tests; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * Run the tests. Each test function returns the number of executed tests and | ||
344 | * updates |failures| with the number of failed tests. | ||
345 | */ | ||
346 | static int __init test_meminit_init(void) | ||
347 | { | ||
348 | int failures = 0, num_tests = 0; | ||
349 | |||
350 | num_tests += test_pages(&failures); | ||
351 | num_tests += test_kvmalloc(&failures); | ||
352 | num_tests += test_kmemcache(&failures); | ||
353 | num_tests += test_rcu_persistent(&failures); | ||
354 | |||
355 | if (failures == 0) | ||
356 | pr_info("all %d tests passed!\n", num_tests); | ||
357 | else | ||
358 | pr_info("failures: %d out of %d\n", failures, num_tests); | ||
359 | |||
360 | return failures ? -EINVAL : 0; | ||
361 | } | ||
362 | module_init(test_meminit_init); | ||
363 | |||
364 | MODULE_LICENSE("GPL"); | ||
diff --git a/lib/test_overflow.c b/lib/test_overflow.c index fc680562d8b6..7a4b6f6c5473 100644 --- a/lib/test_overflow.c +++ b/lib/test_overflow.c | |||
@@ -486,16 +486,17 @@ static int __init test_overflow_shift(void) | |||
486 | * Deal with the various forms of allocator arguments. See comments above | 486 | * Deal with the various forms of allocator arguments. See comments above |
487 | * the DEFINE_TEST_ALLOC() instances for mapping of the "bits". | 487 | * the DEFINE_TEST_ALLOC() instances for mapping of the "bits". |
488 | */ | 488 | */ |
489 | #define alloc010(alloc, arg, sz) alloc(sz, GFP_KERNEL) | 489 | #define alloc_GFP (GFP_KERNEL | __GFP_NOWARN) |
490 | #define alloc011(alloc, arg, sz) alloc(sz, GFP_KERNEL, NUMA_NO_NODE) | 490 | #define alloc010(alloc, arg, sz) alloc(sz, alloc_GFP) |
491 | #define alloc011(alloc, arg, sz) alloc(sz, alloc_GFP, NUMA_NO_NODE) | ||
491 | #define alloc000(alloc, arg, sz) alloc(sz) | 492 | #define alloc000(alloc, arg, sz) alloc(sz) |
492 | #define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) | 493 | #define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) |
493 | #define alloc110(alloc, arg, sz) alloc(arg, sz, GFP_KERNEL) | 494 | #define alloc110(alloc, arg, sz) alloc(arg, sz, alloc_GFP) |
494 | #define free0(free, arg, ptr) free(ptr) | 495 | #define free0(free, arg, ptr) free(ptr) |
495 | #define free1(free, arg, ptr) free(arg, ptr) | 496 | #define free1(free, arg, ptr) free(arg, ptr) |
496 | 497 | ||
497 | /* Wrap around to 8K */ | 498 | /* Wrap around to 16K */ |
498 | #define TEST_SIZE (9 << PAGE_SHIFT) | 499 | #define TEST_SIZE (5 * 4096) |
499 | 500 | ||
500 | #define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ | 501 | #define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ |
501 | static int __init test_ ## func (void *arg) \ | 502 | static int __init test_ ## func (void *arg) \ |
diff --git a/lib/test_string.c b/lib/test_string.c index bf8def01ed20..7b31f4a505bf 100644 --- a/lib/test_string.c +++ b/lib/test_string.c | |||
@@ -36,7 +36,7 @@ static __init int memset16_selftest(void) | |||
36 | fail: | 36 | fail: |
37 | kfree(p); | 37 | kfree(p); |
38 | if (i < 256) | 38 | if (i < 256) |
39 | return (i << 24) | (j << 16) | k; | 39 | return (i << 24) | (j << 16) | k | 0x8000; |
40 | return 0; | 40 | return 0; |
41 | } | 41 | } |
42 | 42 | ||
@@ -72,7 +72,7 @@ static __init int memset32_selftest(void) | |||
72 | fail: | 72 | fail: |
73 | kfree(p); | 73 | kfree(p); |
74 | if (i < 256) | 74 | if (i < 256) |
75 | return (i << 24) | (j << 16) | k; | 75 | return (i << 24) | (j << 16) | k | 0x8000; |
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
@@ -108,7 +108,74 @@ static __init int memset64_selftest(void) | |||
108 | fail: | 108 | fail: |
109 | kfree(p); | 109 | kfree(p); |
110 | if (i < 256) | 110 | if (i < 256) |
111 | return (i << 24) | (j << 16) | k; | 111 | return (i << 24) | (j << 16) | k | 0x8000; |
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static __init int strchr_selftest(void) | ||
116 | { | ||
117 | const char *test_string = "abcdefghijkl"; | ||
118 | const char *empty_string = ""; | ||
119 | char *result; | ||
120 | int i; | ||
121 | |||
122 | for (i = 0; i < strlen(test_string) + 1; i++) { | ||
123 | result = strchr(test_string, test_string[i]); | ||
124 | if (result - test_string != i) | ||
125 | return i + 'a'; | ||
126 | } | ||
127 | |||
128 | result = strchr(empty_string, '\0'); | ||
129 | if (result != empty_string) | ||
130 | return 0x101; | ||
131 | |||
132 | result = strchr(empty_string, 'a'); | ||
133 | if (result) | ||
134 | return 0x102; | ||
135 | |||
136 | result = strchr(test_string, 'z'); | ||
137 | if (result) | ||
138 | return 0x103; | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static __init int strnchr_selftest(void) | ||
144 | { | ||
145 | const char *test_string = "abcdefghijkl"; | ||
146 | const char *empty_string = ""; | ||
147 | char *result; | ||
148 | int i, j; | ||
149 | |||
150 | for (i = 0; i < strlen(test_string) + 1; i++) { | ||
151 | for (j = 0; j < strlen(test_string) + 2; j++) { | ||
152 | result = strnchr(test_string, j, test_string[i]); | ||
153 | if (j <= i) { | ||
154 | if (!result) | ||
155 | continue; | ||
156 | return ((i + 'a') << 8) | j; | ||
157 | } | ||
158 | if (result - test_string != i) | ||
159 | return ((i + 'a') << 8) | j; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | result = strnchr(empty_string, 0, '\0'); | ||
164 | if (result) | ||
165 | return 0x10001; | ||
166 | |||
167 | result = strnchr(empty_string, 1, '\0'); | ||
168 | if (result != empty_string) | ||
169 | return 0x10002; | ||
170 | |||
171 | result = strnchr(empty_string, 1, 'a'); | ||
172 | if (result) | ||
173 | return 0x10003; | ||
174 | |||
175 | result = strnchr(NULL, 0, '\0'); | ||
176 | if (result) | ||
177 | return 0x10004; | ||
178 | |||
112 | return 0; | 179 | return 0; |
113 | } | 180 | } |
114 | 181 | ||
@@ -131,6 +198,16 @@ static __init int string_selftest_init(void) | |||
131 | if (subtest) | 198 | if (subtest) |
132 | goto fail; | 199 | goto fail; |
133 | 200 | ||
201 | test = 4; | ||
202 | subtest = strchr_selftest(); | ||
203 | if (subtest) | ||
204 | goto fail; | ||
205 | |||
206 | test = 5; | ||
207 | subtest = strnchr_selftest(); | ||
208 | if (subtest) | ||
209 | goto fail; | ||
210 | |||
134 | pr_info("String selftests succeeded\n"); | 211 | pr_info("String selftests succeeded\n"); |
135 | return 0; | 212 | return 0; |
136 | fail: | 213 | fail: |