diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 4 | ||||
-rw-r--r-- | lib/Kconfig.debug | 84 | ||||
-rw-r--r-- | lib/Makefile | 4 | ||||
-rw-r--r-- | lib/bitrev.c | 58 | ||||
-rw-r--r-- | lib/bug.c | 163 | ||||
-rw-r--r-- | lib/crc32.c | 28 | ||||
-rw-r--r-- | lib/fault-inject.c | 336 |
7 files changed, 629 insertions, 48 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 734ce95a93d1..47b172df3e31 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -4,6 +4,9 @@ | |||
4 | 4 | ||
5 | menu "Library routines" | 5 | menu "Library routines" |
6 | 6 | ||
7 | config BITREVERSE | ||
8 | tristate | ||
9 | |||
7 | config CRC_CCITT | 10 | config CRC_CCITT |
8 | tristate "CRC-CCITT functions" | 11 | tristate "CRC-CCITT functions" |
9 | help | 12 | help |
@@ -23,6 +26,7 @@ config CRC16 | |||
23 | config CRC32 | 26 | config CRC32 |
24 | tristate "CRC32 functions" | 27 | tristate "CRC32 functions" |
25 | default y | 28 | default y |
29 | select BITREVERSE | ||
26 | help | 30 | help |
27 | This option is provided for the case where no in-kernel-tree | 31 | This option is provided for the case where no in-kernel-tree |
28 | modules require CRC32 functions, but a module built outside the | 32 | modules require CRC32 functions, but a module built outside the |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index b75fed737f25..0701ddda1df8 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -47,6 +47,30 @@ config UNUSED_SYMBOLS | |||
47 | you really need it, and what the merge plan to the mainline kernel for | 47 | you really need it, and what the merge plan to the mainline kernel for |
48 | your module is. | 48 | your module is. |
49 | 49 | ||
50 | config DEBUG_FS | ||
51 | bool "Debug Filesystem" | ||
52 | depends on SYSFS | ||
53 | help | ||
54 | debugfs is a virtual file system that kernel developers use to put | ||
55 | debugging files into. Enable this option to be able to read and | ||
56 | write to these files. | ||
57 | |||
58 | If unsure, say N. | ||
59 | |||
60 | config HEADERS_CHECK | ||
61 | bool "Run 'make headers_check' when building vmlinux" | ||
62 | depends on !UML | ||
63 | help | ||
64 | This option will extract the user-visible kernel headers whenever | ||
65 | building the kernel, and will run basic sanity checks on them to | ||
66 | ensure that exported files do not attempt to include files which | ||
67 | were not exported, etc. | ||
68 | |||
69 | If you're making modifications to header files which are | ||
70 | relevant for userspace, say 'Y', and check the headers | ||
71 | exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in | ||
72 | your build tree), to make sure they're suitable. | ||
73 | |||
50 | config DEBUG_KERNEL | 74 | config DEBUG_KERNEL |
51 | bool "Kernel debugging" | 75 | bool "Kernel debugging" |
52 | help | 76 | help |
@@ -285,7 +309,7 @@ config DEBUG_HIGHMEM | |||
285 | config DEBUG_BUGVERBOSE | 309 | config DEBUG_BUGVERBOSE |
286 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED | 310 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED |
287 | depends on BUG | 311 | depends on BUG |
288 | depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH | 312 | depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG |
289 | default !EMBEDDED | 313 | default !EMBEDDED |
290 | help | 314 | help |
291 | Say Y here to make BUG() panics output the file name and line number | 315 | Say Y here to make BUG() panics output the file name and line number |
@@ -302,16 +326,6 @@ config DEBUG_INFO | |||
302 | 326 | ||
303 | If unsure, say N. | 327 | If unsure, say N. |
304 | 328 | ||
305 | config DEBUG_FS | ||
306 | bool "Debug Filesystem" | ||
307 | depends on SYSFS | ||
308 | help | ||
309 | debugfs is a virtual file system that kernel developers use to put | ||
310 | debugging files into. Enable this option to be able to read and | ||
311 | write to these files. | ||
312 | |||
313 | If unsure, say N. | ||
314 | |||
315 | config DEBUG_VM | 329 | config DEBUG_VM |
316 | bool "Debug VM" | 330 | bool "Debug VM" |
317 | depends on DEBUG_KERNEL | 331 | depends on DEBUG_KERNEL |
@@ -372,20 +386,6 @@ config FORCED_INLINING | |||
372 | become the default in the future, until then this option is there to | 386 | become the default in the future, until then this option is there to |
373 | test gcc for this. | 387 | test gcc for this. |
374 | 388 | ||
375 | config HEADERS_CHECK | ||
376 | bool "Run 'make headers_check' when building vmlinux" | ||
377 | depends on !UML | ||
378 | help | ||
379 | This option will extract the user-visible kernel headers whenever | ||
380 | building the kernel, and will run basic sanity checks on them to | ||
381 | ensure that exported files do not attempt to include files which | ||
382 | were not exported, etc. | ||
383 | |||
384 | If you're making modifications to header files which are | ||
385 | relevant for userspace, say 'Y', and check the headers | ||
386 | exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in | ||
387 | your build tree), to make sure they're suitable. | ||
388 | |||
389 | config RCU_TORTURE_TEST | 389 | config RCU_TORTURE_TEST |
390 | tristate "torture tests for RCU" | 390 | tristate "torture tests for RCU" |
391 | depends on DEBUG_KERNEL | 391 | depends on DEBUG_KERNEL |
@@ -402,6 +402,7 @@ config RCU_TORTURE_TEST | |||
402 | 402 | ||
403 | config LKDTM | 403 | config LKDTM |
404 | tristate "Linux Kernel Dump Test Tool Module" | 404 | tristate "Linux Kernel Dump Test Tool Module" |
405 | depends on DEBUG_KERNEL | ||
405 | depends on KPROBES | 406 | depends on KPROBES |
406 | default n | 407 | default n |
407 | help | 408 | help |
@@ -413,3 +414,36 @@ config LKDTM | |||
413 | 414 | ||
414 | Documentation on how to use the module can be found in | 415 | Documentation on how to use the module can be found in |
415 | drivers/misc/lkdtm.c | 416 | drivers/misc/lkdtm.c |
417 | |||
418 | config FAULT_INJECTION | ||
419 | bool "Fault-injection framework" | ||
420 | depends on DEBUG_KERNEL | ||
421 | depends on STACKTRACE | ||
422 | select FRAME_POINTER | ||
423 | help | ||
424 | Provide fault-injection framework. | ||
425 | For more details, see Documentation/fault-injection/. | ||
426 | |||
427 | config FAILSLAB | ||
428 | bool "Fault-injection capability for kmalloc" | ||
429 | depends on FAULT_INJECTION | ||
430 | help | ||
431 | Provide fault-injection capability for kmalloc. | ||
432 | |||
433 | config FAIL_PAGE_ALLOC | ||
434 | bool "Fault-injection capabilitiy for alloc_pages()" | ||
435 | depends on FAULT_INJECTION | ||
436 | help | ||
437 | Provide fault-injection capability for alloc_pages(). | ||
438 | |||
439 | config FAIL_MAKE_REQUEST | ||
440 | bool "Fault-injection capabilitiy for disk IO" | ||
441 | depends on FAULT_INJECTION | ||
442 | help | ||
443 | Provide fault-injection capability for disk IO. | ||
444 | |||
445 | config FAULT_INJECTION_DEBUG_FS | ||
446 | bool "Debugfs entries for fault-injection capabilities" | ||
447 | depends on FAULT_INJECTION && SYSFS && DEBUG_FS | ||
448 | help | ||
449 | Enable configuration of fault-injection capabilities via debugfs. | ||
diff --git a/lib/Makefile b/lib/Makefile index fea8f9035f07..2d6106af53cd 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -35,6 +35,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y) | |||
35 | lib-y += dec_and_lock.o | 35 | lib-y += dec_and_lock.o |
36 | endif | 36 | endif |
37 | 37 | ||
38 | obj-$(CONFIG_BITREVERSE) += bitrev.o | ||
38 | obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o | 39 | obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o |
39 | obj-$(CONFIG_CRC16) += crc16.o | 40 | obj-$(CONFIG_CRC16) += crc16.o |
40 | obj-$(CONFIG_CRC32) += crc32.o | 41 | obj-$(CONFIG_CRC32) += crc32.o |
@@ -54,6 +55,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o | |||
54 | obj-$(CONFIG_AUDIT_GENERIC) += audit.o | 55 | obj-$(CONFIG_AUDIT_GENERIC) += audit.o |
55 | 56 | ||
56 | obj-$(CONFIG_SWIOTLB) += swiotlb.o | 57 | obj-$(CONFIG_SWIOTLB) += swiotlb.o |
58 | obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o | ||
59 | |||
60 | lib-$(CONFIG_GENERIC_BUG) += bug.o | ||
57 | 61 | ||
58 | hostprogs-y := gen_crc32table | 62 | hostprogs-y := gen_crc32table |
59 | clean-files := crc32table.h | 63 | clean-files := crc32table.h |
diff --git a/lib/bitrev.c b/lib/bitrev.c new file mode 100644 index 000000000000..989aff73f881 --- /dev/null +++ b/lib/bitrev.c | |||
@@ -0,0 +1,58 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/bitrev.h> | ||
4 | |||
5 | MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>"); | ||
6 | MODULE_DESCRIPTION("Bit ordering reversal functions"); | ||
7 | MODULE_LICENSE("GPL"); | ||
8 | |||
9 | const u8 byte_rev_table[256] = { | ||
10 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | ||
11 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, | ||
12 | 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | ||
13 | 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, | ||
14 | 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, | ||
15 | 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | ||
16 | 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, | ||
17 | 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, | ||
18 | 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | ||
19 | 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, | ||
20 | 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | ||
21 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | ||
22 | 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, | ||
23 | 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, | ||
24 | 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | ||
25 | 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, | ||
26 | 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, | ||
27 | 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | ||
28 | 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, | ||
29 | 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, | ||
30 | 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | ||
31 | 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | ||
32 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, | ||
33 | 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | ||
34 | 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, | ||
35 | 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, | ||
36 | 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | ||
37 | 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, | ||
38 | 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, | ||
39 | 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | ||
40 | 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, | ||
41 | 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, | ||
42 | }; | ||
43 | EXPORT_SYMBOL_GPL(byte_rev_table); | ||
44 | |||
45 | static __always_inline u16 bitrev16(u16 x) | ||
46 | { | ||
47 | return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * bitrev32 - reverse the order of bits in a u32 value | ||
52 | * @x: value to be bit-reversed | ||
53 | */ | ||
54 | u32 bitrev32(u32 x) | ||
55 | { | ||
56 | return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16); | ||
57 | } | ||
58 | EXPORT_SYMBOL(bitrev32); | ||
diff --git a/lib/bug.c b/lib/bug.c new file mode 100644 index 000000000000..014b582c5c4b --- /dev/null +++ b/lib/bug.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | Generic support for BUG() | ||
3 | |||
4 | This respects the following config options: | ||
5 | |||
6 | CONFIG_BUG - emit BUG traps. Nothing happens without this. | ||
7 | CONFIG_GENERIC_BUG - enable this code. | ||
8 | CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG | ||
9 | |||
10 | CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable | ||
11 | (though they're generally always on). | ||
12 | |||
13 | CONFIG_GENERIC_BUG is set by each architecture using this code. | ||
14 | |||
15 | To use this, your architecture must: | ||
16 | |||
17 | 1. Set up the config options: | ||
18 | - Enable CONFIG_GENERIC_BUG if CONFIG_BUG | ||
19 | |||
20 | 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON) | ||
21 | - Define HAVE_ARCH_BUG | ||
22 | - Implement BUG() to generate a faulting instruction | ||
23 | - NOTE: struct bug_entry does not have "file" or "line" entries | ||
24 | when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate | ||
25 | the values accordingly. | ||
26 | |||
27 | 3. Implement the trap | ||
28 | - In the illegal instruction trap handler (typically), verify | ||
29 | that the fault was in kernel mode, and call report_bug() | ||
30 | - report_bug() will return whether it was a false alarm, a warning, | ||
31 | or an actual bug. | ||
32 | - You must implement the is_valid_bugaddr(bugaddr) callback which | ||
33 | returns true if the eip is a real kernel address, and it points | ||
34 | to the expected BUG trap instruction. | ||
35 | |||
36 | Jeremy Fitzhardinge <jeremy@goop.org> 2006 | ||
37 | */ | ||
38 | #include <linux/list.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/bug.h> | ||
41 | |||
42 | extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; | ||
43 | |||
44 | #ifdef CONFIG_MODULES | ||
45 | static LIST_HEAD(module_bug_list); | ||
46 | |||
47 | static const struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
48 | { | ||
49 | struct module *mod; | ||
50 | |||
51 | list_for_each_entry(mod, &module_bug_list, bug_list) { | ||
52 | const struct bug_entry *bug = mod->bug_table; | ||
53 | unsigned i; | ||
54 | |||
55 | for (i = 0; i < mod->num_bugs; ++i, ++bug) | ||
56 | if (bugaddr == bug->bug_addr) | ||
57 | return bug; | ||
58 | } | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
63 | struct module *mod) | ||
64 | { | ||
65 | char *secstrings; | ||
66 | unsigned int i; | ||
67 | |||
68 | mod->bug_table = NULL; | ||
69 | mod->num_bugs = 0; | ||
70 | |||
71 | /* Find the __bug_table section, if present */ | ||
72 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
73 | for (i = 1; i < hdr->e_shnum; i++) { | ||
74 | if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) | ||
75 | continue; | ||
76 | mod->bug_table = (void *) sechdrs[i].sh_addr; | ||
77 | mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Strictly speaking this should have a spinlock to protect against | ||
83 | * traversals, but since we only traverse on BUG()s, a spinlock | ||
84 | * could potentially lead to deadlock and thus be counter-productive. | ||
85 | */ | ||
86 | list_add(&mod->bug_list, &module_bug_list); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | void module_bug_cleanup(struct module *mod) | ||
92 | { | ||
93 | list_del(&mod->bug_list); | ||
94 | } | ||
95 | |||
96 | #else | ||
97 | |||
98 | static inline const struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
99 | { | ||
100 | return NULL; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | const struct bug_entry *find_bug(unsigned long bugaddr) | ||
105 | { | ||
106 | const struct bug_entry *bug; | ||
107 | |||
108 | for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) | ||
109 | if (bugaddr == bug->bug_addr) | ||
110 | return bug; | ||
111 | |||
112 | return module_find_bug(bugaddr); | ||
113 | } | ||
114 | |||
115 | enum bug_trap_type report_bug(unsigned long bugaddr) | ||
116 | { | ||
117 | const struct bug_entry *bug; | ||
118 | const char *file; | ||
119 | unsigned line, warning; | ||
120 | |||
121 | if (!is_valid_bugaddr(bugaddr)) | ||
122 | return BUG_TRAP_TYPE_NONE; | ||
123 | |||
124 | bug = find_bug(bugaddr); | ||
125 | |||
126 | printk(KERN_EMERG "------------[ cut here ]------------\n"); | ||
127 | |||
128 | file = NULL; | ||
129 | line = 0; | ||
130 | warning = 0; | ||
131 | |||
132 | if (bug) { | ||
133 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
134 | file = bug->file; | ||
135 | line = bug->line; | ||
136 | #endif | ||
137 | warning = (bug->flags & BUGFLAG_WARNING) != 0; | ||
138 | } | ||
139 | |||
140 | if (warning) { | ||
141 | /* this is a WARN_ON rather than BUG/BUG_ON */ | ||
142 | if (file) | ||
143 | printk(KERN_ERR "Badness at %s:%u\n", | ||
144 | file, line); | ||
145 | else | ||
146 | printk(KERN_ERR "Badness at %p " | ||
147 | "[verbose debug info unavailable]\n", | ||
148 | (void *)bugaddr); | ||
149 | |||
150 | dump_stack(); | ||
151 | return BUG_TRAP_TYPE_WARN; | ||
152 | } | ||
153 | |||
154 | if (file) | ||
155 | printk(KERN_CRIT "kernel BUG at %s:%u!\n", | ||
156 | file, line); | ||
157 | else | ||
158 | printk(KERN_CRIT "Kernel BUG at %p " | ||
159 | "[verbose debug info unavailable]\n", | ||
160 | (void *)bugaddr); | ||
161 | |||
162 | return BUG_TRAP_TYPE_BUG; | ||
163 | } | ||
diff --git a/lib/crc32.c b/lib/crc32.c index 285fd9bc61be..bfc33314c720 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
@@ -235,23 +235,8 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len) | |||
235 | } | 235 | } |
236 | #endif | 236 | #endif |
237 | 237 | ||
238 | /** | ||
239 | * bitreverse - reverse the order of bits in a u32 value | ||
240 | * @x: value to be bit-reversed | ||
241 | */ | ||
242 | u32 bitreverse(u32 x) | ||
243 | { | ||
244 | x = (x >> 16) | (x << 16); | ||
245 | x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00); | ||
246 | x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0); | ||
247 | x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc); | ||
248 | x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa); | ||
249 | return x; | ||
250 | } | ||
251 | |||
252 | EXPORT_SYMBOL(crc32_le); | 238 | EXPORT_SYMBOL(crc32_le); |
253 | EXPORT_SYMBOL(crc32_be); | 239 | EXPORT_SYMBOL(crc32_be); |
254 | EXPORT_SYMBOL(bitreverse); | ||
255 | 240 | ||
256 | /* | 241 | /* |
257 | * A brief CRC tutorial. | 242 | * A brief CRC tutorial. |
@@ -400,10 +385,7 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len) | |||
400 | static void bytereverse(unsigned char *buf, size_t len) | 385 | static void bytereverse(unsigned char *buf, size_t len) |
401 | { | 386 | { |
402 | while (len--) { | 387 | while (len--) { |
403 | unsigned char x = *buf; | 388 | unsigned char x = bitrev8(*buf); |
404 | x = (x >> 4) | (x << 4); | ||
405 | x = (x >> 2 & 0x33) | (x << 2 & 0xcc); | ||
406 | x = (x >> 1 & 0x55) | (x << 1 & 0xaa); | ||
407 | *buf++ = x; | 389 | *buf++ = x; |
408 | } | 390 | } |
409 | } | 391 | } |
@@ -460,11 +442,11 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len) | |||
460 | /* Now swap it around for the other test */ | 442 | /* Now swap it around for the other test */ |
461 | 443 | ||
462 | bytereverse(buf, len + 4); | 444 | bytereverse(buf, len + 4); |
463 | init = bitreverse(init); | 445 | init = bitrev32(init); |
464 | crc2 = bitreverse(crc1); | 446 | crc2 = bitrev32(crc1); |
465 | if (crc1 != bitreverse(crc2)) | 447 | if (crc1 != bitrev32(crc2)) |
466 | printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", | 448 | printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", |
467 | crc1, crc2, bitreverse(crc2)); | 449 | crc1, crc2, bitrev32(crc2)); |
468 | crc1 = crc32_le(init, buf, len); | 450 | crc1 = crc32_le(init, buf, len); |
469 | if (crc1 != crc2) | 451 | if (crc1 != crc2) |
470 | printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, | 452 | printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, |
diff --git a/lib/fault-inject.c b/lib/fault-inject.c new file mode 100644 index 000000000000..d143c0faf248 --- /dev/null +++ b/lib/fault-inject.c | |||
@@ -0,0 +1,336 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/random.h> | ||
4 | #include <linux/stat.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/fs.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/interrupt.h> | ||
9 | #include <linux/unwind.h> | ||
10 | #include <linux/stacktrace.h> | ||
11 | #include <linux/kallsyms.h> | ||
12 | #include <linux/fault-inject.h> | ||
13 | |||
14 | /* | ||
15 | * setup_fault_attr() is a helper function for various __setup handlers, so it | ||
16 | * returns 0 on error, because that is what __setup handlers do. | ||
17 | */ | ||
18 | int __init setup_fault_attr(struct fault_attr *attr, char *str) | ||
19 | { | ||
20 | unsigned long probability; | ||
21 | unsigned long interval; | ||
22 | int times; | ||
23 | int space; | ||
24 | |||
25 | /* "<interval>,<probability>,<space>,<times>" */ | ||
26 | if (sscanf(str, "%lu,%lu,%d,%d", | ||
27 | &interval, &probability, &space, ×) < 4) { | ||
28 | printk(KERN_WARNING | ||
29 | "FAULT_INJECTION: failed to parse arguments\n"); | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | attr->probability = probability; | ||
34 | attr->interval = interval; | ||
35 | atomic_set(&attr->times, times); | ||
36 | atomic_set(&attr->space, space); | ||
37 | |||
38 | return 1; | ||
39 | } | ||
40 | |||
41 | static void fail_dump(struct fault_attr *attr) | ||
42 | { | ||
43 | if (attr->verbose > 0) | ||
44 | printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n"); | ||
45 | if (attr->verbose > 1) | ||
46 | dump_stack(); | ||
47 | } | ||
48 | |||
49 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
50 | |||
51 | static bool fail_task(struct fault_attr *attr, struct task_struct *task) | ||
52 | { | ||
53 | return !in_interrupt() && task->make_it_fail; | ||
54 | } | ||
55 | |||
56 | #define MAX_STACK_TRACE_DEPTH 32 | ||
57 | |||
58 | #ifdef CONFIG_STACK_UNWIND | ||
59 | |||
60 | static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info, | ||
61 | void *arg) | ||
62 | { | ||
63 | int depth; | ||
64 | struct fault_attr *attr = arg; | ||
65 | bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX); | ||
66 | |||
67 | for (depth = 0; depth < attr->stacktrace_depth | ||
68 | && unwind(info) == 0 && UNW_PC(info); depth++) { | ||
69 | if (arch_unw_user_mode(info)) | ||
70 | break; | ||
71 | if (attr->reject_start <= UNW_PC(info) && | ||
72 | UNW_PC(info) < attr->reject_end) | ||
73 | return false; | ||
74 | if (attr->require_start <= UNW_PC(info) && | ||
75 | UNW_PC(info) < attr->require_end) | ||
76 | found = true; | ||
77 | } | ||
78 | return found; | ||
79 | } | ||
80 | |||
81 | static bool fail_stacktrace(struct fault_attr *attr) | ||
82 | { | ||
83 | struct unwind_frame_info info; | ||
84 | |||
85 | return unwind_init_running(&info, fail_stacktrace_callback, attr); | ||
86 | } | ||
87 | |||
88 | #elif defined(CONFIG_STACKTRACE) | ||
89 | |||
90 | static bool fail_stacktrace(struct fault_attr *attr) | ||
91 | { | ||
92 | struct stack_trace trace; | ||
93 | int depth = attr->stacktrace_depth; | ||
94 | unsigned long entries[MAX_STACK_TRACE_DEPTH]; | ||
95 | int n; | ||
96 | bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX); | ||
97 | |||
98 | if (depth == 0) | ||
99 | return found; | ||
100 | |||
101 | trace.nr_entries = 0; | ||
102 | trace.entries = entries; | ||
103 | trace.max_entries = depth; | ||
104 | trace.skip = 1; | ||
105 | trace.all_contexts = 0; | ||
106 | |||
107 | save_stack_trace(&trace, NULL); | ||
108 | for (n = 0; n < trace.nr_entries; n++) { | ||
109 | if (attr->reject_start <= entries[n] && | ||
110 | entries[n] < attr->reject_end) | ||
111 | return false; | ||
112 | if (attr->require_start <= entries[n] && | ||
113 | entries[n] < attr->require_end) | ||
114 | found = true; | ||
115 | } | ||
116 | return found; | ||
117 | } | ||
118 | |||
119 | #else | ||
120 | |||
121 | static inline bool fail_stacktrace(struct fault_attr *attr) | ||
122 | { | ||
123 | static bool firsttime = true; | ||
124 | |||
125 | if (firsttime) { | ||
126 | printk(KERN_WARNING | ||
127 | "This architecture does not implement save_stack_trace()\n"); | ||
128 | firsttime = false; | ||
129 | } | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | #endif | ||
134 | |||
135 | /* | ||
136 | * This code is stolen from failmalloc-1.0 | ||
137 | * http://www.nongnu.org/failmalloc/ | ||
138 | */ | ||
139 | |||
140 | bool should_fail(struct fault_attr *attr, ssize_t size) | ||
141 | { | ||
142 | if (attr->task_filter && !fail_task(attr, current)) | ||
143 | return false; | ||
144 | |||
145 | if (atomic_read(&attr->times) == 0) | ||
146 | return false; | ||
147 | |||
148 | if (atomic_read(&attr->space) > size) { | ||
149 | atomic_sub(size, &attr->space); | ||
150 | return false; | ||
151 | } | ||
152 | |||
153 | if (attr->interval > 1) { | ||
154 | attr->count++; | ||
155 | if (attr->count % attr->interval) | ||
156 | return false; | ||
157 | } | ||
158 | |||
159 | if (attr->probability <= random32() % 100) | ||
160 | return false; | ||
161 | |||
162 | if (!fail_stacktrace(attr)) | ||
163 | return false; | ||
164 | |||
165 | fail_dump(attr); | ||
166 | |||
167 | if (atomic_read(&attr->times) != -1) | ||
168 | atomic_dec_not_zero(&attr->times); | ||
169 | |||
170 | return true; | ||
171 | } | ||
172 | |||
173 | #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS | ||
174 | |||
175 | static void debugfs_ul_set(void *data, u64 val) | ||
176 | { | ||
177 | *(unsigned long *)data = val; | ||
178 | } | ||
179 | |||
180 | static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val) | ||
181 | { | ||
182 | *(unsigned long *)data = | ||
183 | val < MAX_STACK_TRACE_DEPTH ? | ||
184 | val : MAX_STACK_TRACE_DEPTH; | ||
185 | } | ||
186 | |||
187 | static u64 debugfs_ul_get(void *data) | ||
188 | { | ||
189 | return *(unsigned long *)data; | ||
190 | } | ||
191 | |||
192 | DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n"); | ||
193 | |||
194 | static struct dentry *debugfs_create_ul(const char *name, mode_t mode, | ||
195 | struct dentry *parent, unsigned long *value) | ||
196 | { | ||
197 | return debugfs_create_file(name, mode, parent, value, &fops_ul); | ||
198 | } | ||
199 | |||
200 | DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get, | ||
201 | debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n"); | ||
202 | |||
203 | static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH( | ||
204 | const char *name, mode_t mode, | ||
205 | struct dentry *parent, unsigned long *value) | ||
206 | { | ||
207 | return debugfs_create_file(name, mode, parent, value, | ||
208 | &fops_ul_MAX_STACK_TRACE_DEPTH); | ||
209 | } | ||
210 | |||
211 | static void debugfs_atomic_t_set(void *data, u64 val) | ||
212 | { | ||
213 | atomic_set((atomic_t *)data, val); | ||
214 | } | ||
215 | |||
216 | static u64 debugfs_atomic_t_get(void *data) | ||
217 | { | ||
218 | return atomic_read((atomic_t *)data); | ||
219 | } | ||
220 | |||
221 | DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, | ||
222 | debugfs_atomic_t_set, "%lld\n"); | ||
223 | |||
224 | static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode, | ||
225 | struct dentry *parent, atomic_t *value) | ||
226 | { | ||
227 | return debugfs_create_file(name, mode, parent, value, &fops_atomic_t); | ||
228 | } | ||
229 | |||
230 | void cleanup_fault_attr_dentries(struct fault_attr *attr) | ||
231 | { | ||
232 | debugfs_remove(attr->dentries.probability_file); | ||
233 | attr->dentries.probability_file = NULL; | ||
234 | |||
235 | debugfs_remove(attr->dentries.interval_file); | ||
236 | attr->dentries.interval_file = NULL; | ||
237 | |||
238 | debugfs_remove(attr->dentries.times_file); | ||
239 | attr->dentries.times_file = NULL; | ||
240 | |||
241 | debugfs_remove(attr->dentries.space_file); | ||
242 | attr->dentries.space_file = NULL; | ||
243 | |||
244 | debugfs_remove(attr->dentries.verbose_file); | ||
245 | attr->dentries.verbose_file = NULL; | ||
246 | |||
247 | debugfs_remove(attr->dentries.task_filter_file); | ||
248 | attr->dentries.task_filter_file = NULL; | ||
249 | |||
250 | debugfs_remove(attr->dentries.stacktrace_depth_file); | ||
251 | attr->dentries.stacktrace_depth_file = NULL; | ||
252 | |||
253 | debugfs_remove(attr->dentries.require_start_file); | ||
254 | attr->dentries.require_start_file = NULL; | ||
255 | |||
256 | debugfs_remove(attr->dentries.require_end_file); | ||
257 | attr->dentries.require_end_file = NULL; | ||
258 | |||
259 | debugfs_remove(attr->dentries.reject_start_file); | ||
260 | attr->dentries.reject_start_file = NULL; | ||
261 | |||
262 | debugfs_remove(attr->dentries.reject_end_file); | ||
263 | attr->dentries.reject_end_file = NULL; | ||
264 | |||
265 | if (attr->dentries.dir) | ||
266 | WARN_ON(!simple_empty(attr->dentries.dir)); | ||
267 | |||
268 | debugfs_remove(attr->dentries.dir); | ||
269 | attr->dentries.dir = NULL; | ||
270 | } | ||
271 | |||
272 | int init_fault_attr_dentries(struct fault_attr *attr, const char *name) | ||
273 | { | ||
274 | mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; | ||
275 | struct dentry *dir; | ||
276 | |||
277 | memset(&attr->dentries, 0, sizeof(attr->dentries)); | ||
278 | |||
279 | dir = debugfs_create_dir(name, NULL); | ||
280 | if (!dir) | ||
281 | goto fail; | ||
282 | attr->dentries.dir = dir; | ||
283 | |||
284 | attr->dentries.probability_file = | ||
285 | debugfs_create_ul("probability", mode, dir, &attr->probability); | ||
286 | |||
287 | attr->dentries.interval_file = | ||
288 | debugfs_create_ul("interval", mode, dir, &attr->interval); | ||
289 | |||
290 | attr->dentries.times_file = | ||
291 | debugfs_create_atomic_t("times", mode, dir, &attr->times); | ||
292 | |||
293 | attr->dentries.space_file = | ||
294 | debugfs_create_atomic_t("space", mode, dir, &attr->space); | ||
295 | |||
296 | attr->dentries.verbose_file = | ||
297 | debugfs_create_ul("verbose", mode, dir, &attr->verbose); | ||
298 | |||
299 | attr->dentries.task_filter_file = debugfs_create_bool("task-filter", | ||
300 | mode, dir, &attr->task_filter); | ||
301 | |||
302 | attr->dentries.stacktrace_depth_file = | ||
303 | debugfs_create_ul_MAX_STACK_TRACE_DEPTH( | ||
304 | "stacktrace-depth", mode, dir, &attr->stacktrace_depth); | ||
305 | |||
306 | attr->dentries.require_start_file = | ||
307 | debugfs_create_ul("require-start", mode, dir, &attr->require_start); | ||
308 | |||
309 | attr->dentries.require_end_file = | ||
310 | debugfs_create_ul("require-end", mode, dir, &attr->require_end); | ||
311 | |||
312 | attr->dentries.reject_start_file = | ||
313 | debugfs_create_ul("reject-start", mode, dir, &attr->reject_start); | ||
314 | |||
315 | attr->dentries.reject_end_file = | ||
316 | debugfs_create_ul("reject-end", mode, dir, &attr->reject_end); | ||
317 | |||
318 | |||
319 | if (!attr->dentries.probability_file || !attr->dentries.interval_file | ||
320 | || !attr->dentries.times_file || !attr->dentries.space_file | ||
321 | || !attr->dentries.verbose_file || !attr->dentries.task_filter_file | ||
322 | || !attr->dentries.stacktrace_depth_file | ||
323 | || !attr->dentries.require_start_file | ||
324 | || !attr->dentries.require_end_file | ||
325 | || !attr->dentries.reject_start_file | ||
326 | || !attr->dentries.reject_end_file | ||
327 | ) | ||
328 | goto fail; | ||
329 | |||
330 | return 0; | ||
331 | fail: | ||
332 | cleanup_fault_attr_dentries(attr); | ||
333 | return -ENOMEM; | ||
334 | } | ||
335 | |||
336 | #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ | ||