diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2013-04-29 19:18:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 21:28:20 -0400 |
commit | f91eb62f71b31e69e405663ff8d047bc3b9f7525 (patch) | |
tree | 7a61eb166aa50db4436dcaa3f5d0f385530dcb59 /init | |
parent | 8543ae1296f6ec1490c7afab6ae0fe97bf87ebf8 (diff) |
init: scream bloody murder if interrupts are enabled too early
As I was testing a lot of my code recently, and having several
"successes", I accidentally noticed in the dmesg this little line:
start_kernel(): bug: interrupts were enabled *very* early, fixing it
Sure enough, one of my patches two commits ago enabled interrupts early.
The sad part here is that I never noticed it, and I ran several tests with
ktest too, and ktest did not notice this line.
What ktest looks for (and so does many other automated testing scripts) is
a back trace produced by a WARN_ON() or BUG(). As a back trace was never
produced, my buggy patch could have slipped into linux-next, or even
worse, mainline.
Adding a WARN(!irqs_disabled()) makes this bug a little more obvious:
PID hash table entries: 4096 (order: 3, 32768 bytes)
__ex_table already sorted, skipping sort
Checking aperture...
No AGP bridge found
Calgary: detecting Calgary via BIOS EBDA area
Calgary: Unable to locate Rio Grande table in EBDA - bailing!
Memory: 2003252k/2054848k available (4857k kernel code, 460k absent, 51136k reserved, 6210k data, 1096k init)
------------[ cut here ]------------
WARNING: at /home/rostedt/work/git/linux-trace.git/init/main.c:543 start_kernel+0x21e/0x415()
Hardware name: To Be Filled By O.E.M.
Interrupts were enabled *very* early, fixing it
Modules linked in:
Pid: 0, comm: swapper/0 Not tainted 3.8.0-test+ #286
Call Trace:
warn_slowpath_common+0x83/0x9b
warn_slowpath_fmt+0x46/0x48
start_kernel+0x21e/0x415
x86_64_start_reservations+0x10e/0x112
x86_64_start_kernel+0x102/0x111
---[ end trace 007d8b0491b4f5d8 ]---
Preemptible hierarchical RCU implementation.
RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
NR_IRQS:4352 nr_irqs:712 16
Console: colour VGA+ 80x25
console [ttyS0] enabled, bootconsole disabled
Do you see it?
The original version of this patch just slapped a WARN_ON() in there and
kept the printk(). Ard van Breemen suggested using the WARN() interface,
which makes the code a bit cleaner.
Also, while examining other warnings in init/main.c, I found two other
locations that deserve a bloody murder scream if their conditions are hit,
and updated them accordingly.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ard van Breemen <ard@telegraafnet.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'init')
-rw-r--r-- | init/main.c | 13 |
1 files changed, 3 insertions, 10 deletions
diff --git a/init/main.c b/init/main.c index 63534a141b4e..26cd398acf2a 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -539,11 +539,8 @@ asmlinkage void __init start_kernel(void) | |||
539 | * fragile until we cpu_idle() for the first time. | 539 | * fragile until we cpu_idle() for the first time. |
540 | */ | 540 | */ |
541 | preempt_disable(); | 541 | preempt_disable(); |
542 | if (!irqs_disabled()) { | 542 | if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n")) |
543 | printk(KERN_WARNING "start_kernel(): bug: interrupts were " | ||
544 | "enabled *very* early, fixing it\n"); | ||
545 | local_irq_disable(); | 543 | local_irq_disable(); |
546 | } | ||
547 | idr_init_cache(); | 544 | idr_init_cache(); |
548 | perf_event_init(); | 545 | perf_event_init(); |
549 | rcu_init(); | 546 | rcu_init(); |
@@ -558,9 +555,7 @@ asmlinkage void __init start_kernel(void) | |||
558 | time_init(); | 555 | time_init(); |
559 | profile_init(); | 556 | profile_init(); |
560 | call_function_init(); | 557 | call_function_init(); |
561 | if (!irqs_disabled()) | 558 | WARN(!irqs_disabled(), "Interrupts were enabled early\n"); |
562 | printk(KERN_CRIT "start_kernel(): bug: interrupts were " | ||
563 | "enabled early\n"); | ||
564 | early_boot_irqs_disabled = false; | 559 | early_boot_irqs_disabled = false; |
565 | local_irq_enable(); | 560 | local_irq_enable(); |
566 | 561 | ||
@@ -702,9 +697,7 @@ int __init_or_module do_one_initcall(initcall_t fn) | |||
702 | strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); | 697 | strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); |
703 | local_irq_enable(); | 698 | local_irq_enable(); |
704 | } | 699 | } |
705 | if (msgbuf[0]) { | 700 | WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf); |
706 | printk("initcall %pF returned with %s\n", fn, msgbuf); | ||
707 | } | ||
708 | 701 | ||
709 | return ret; | 702 | return ret; |
710 | } | 703 | } |