diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | include/linux/jiffies.h | 2 | ||||
-rw-r--r-- | init/calibrate.c | 2 | ||||
-rw-r--r-- | kernel/printk.c | 59 | ||||
-rw-r--r-- | lib/Kconfig.debug | 18 |
5 files changed, 85 insertions, 1 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 085e4a095eaa..760ed5776174 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -349,6 +349,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
349 | blkmtd_bs= | 349 | blkmtd_bs= |
350 | blkmtd_count= | 350 | blkmtd_count= |
351 | 351 | ||
352 | boot_delay= Milliseconds to delay each printk during boot. | ||
353 | Values larger than 10 seconds (10000) are changed to | ||
354 | no delay (0). | ||
355 | Format: integer | ||
356 | |||
352 | bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) | 357 | bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) |
353 | bttv.radio= Most important insmod options are available as | 358 | bttv.radio= Most important insmod options are available as |
354 | kernel args too. | 359 | kernel args too. |
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index e757a74b9d17..8b080024bbc1 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
@@ -148,6 +148,8 @@ static inline u64 get_jiffies_64(void) | |||
148 | */ | 148 | */ |
149 | #define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1) | 149 | #define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1) |
150 | 150 | ||
151 | extern unsigned long preset_lpj; | ||
152 | |||
151 | /* | 153 | /* |
152 | * We want to do realistic conversions of time so we need to use the same | 154 | * We want to do realistic conversions of time so we need to use the same |
153 | * values the update wall clock code uses as the jiffies size. This value | 155 | * values the update wall clock code uses as the jiffies size. This value |
diff --git a/init/calibrate.c b/init/calibrate.c index 40ff3b404895..2d3d73bd4ce1 100644 --- a/init/calibrate.c +++ b/init/calibrate.c | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #include <asm/timex.h> | 11 | #include <asm/timex.h> |
12 | 12 | ||
13 | static unsigned long preset_lpj; | 13 | unsigned long preset_lpj; |
14 | static int __init lpj_setup(char *str) | 14 | static int __init lpj_setup(char *str) |
15 | { | 15 | { |
16 | preset_lpj = simple_strtoul(str,NULL,0); | 16 | preset_lpj = simple_strtoul(str,NULL,0); |
diff --git a/kernel/printk.c b/kernel/printk.c index 8451dfc31d25..b2b5c3a22a36 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/tty_driver.h> | 22 | #include <linux/tty_driver.h> |
23 | #include <linux/console.h> | 23 | #include <linux/console.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/jiffies.h> | ||
26 | #include <linux/nmi.h> | ||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
27 | #include <linux/interrupt.h> /* For in_interrupt() */ | 29 | #include <linux/interrupt.h> /* For in_interrupt() */ |
@@ -162,6 +164,61 @@ out: | |||
162 | 164 | ||
163 | __setup("log_buf_len=", log_buf_len_setup); | 165 | __setup("log_buf_len=", log_buf_len_setup); |
164 | 166 | ||
167 | #ifdef CONFIG_BOOT_PRINTK_DELAY | ||
168 | |||
169 | static unsigned int boot_delay; /* msecs delay after each printk during bootup */ | ||
170 | static unsigned long long printk_delay_msec; /* per msec, based on boot_delay */ | ||
171 | |||
172 | static int __init boot_delay_setup(char *str) | ||
173 | { | ||
174 | unsigned long lpj; | ||
175 | unsigned long long loops_per_msec; | ||
176 | |||
177 | lpj = preset_lpj ? preset_lpj : 1000000; /* some guess */ | ||
178 | loops_per_msec = (unsigned long long)lpj / 1000 * HZ; | ||
179 | |||
180 | get_option(&str, &boot_delay); | ||
181 | if (boot_delay > 10 * 1000) | ||
182 | boot_delay = 0; | ||
183 | |||
184 | printk_delay_msec = loops_per_msec; | ||
185 | printk(KERN_DEBUG "boot_delay: %u, preset_lpj: %ld, lpj: %lu, " | ||
186 | "HZ: %d, printk_delay_msec: %llu\n", | ||
187 | boot_delay, preset_lpj, lpj, HZ, printk_delay_msec); | ||
188 | return 1; | ||
189 | } | ||
190 | __setup("boot_delay=", boot_delay_setup); | ||
191 | |||
192 | static void boot_delay_msec(void) | ||
193 | { | ||
194 | unsigned long long k; | ||
195 | unsigned long timeout; | ||
196 | |||
197 | if (boot_delay == 0 || system_state != SYSTEM_BOOTING) | ||
198 | return; | ||
199 | |||
200 | k = (unsigned long long)printk_delay_msec * boot_delay; | ||
201 | |||
202 | timeout = jiffies + msecs_to_jiffies(boot_delay); | ||
203 | while (k) { | ||
204 | k--; | ||
205 | cpu_relax(); | ||
206 | /* | ||
207 | * use (volatile) jiffies to prevent | ||
208 | * compiler reduction; loop termination via jiffies | ||
209 | * is secondary and may or may not happen. | ||
210 | */ | ||
211 | if (time_after(jiffies, timeout)) | ||
212 | break; | ||
213 | touch_nmi_watchdog(); | ||
214 | } | ||
215 | } | ||
216 | #else | ||
217 | static inline void boot_delay_msec(void) | ||
218 | { | ||
219 | } | ||
220 | #endif | ||
221 | |||
165 | /* | 222 | /* |
166 | * Commands to do_syslog: | 223 | * Commands to do_syslog: |
167 | * | 224 | * |
@@ -527,6 +584,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
527 | static char printk_buf[1024]; | 584 | static char printk_buf[1024]; |
528 | static int log_level_unknown = 1; | 585 | static int log_level_unknown = 1; |
529 | 586 | ||
587 | boot_delay_msec(); | ||
588 | |||
530 | preempt_disable(); | 589 | preempt_disable(); |
531 | if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) | 590 | if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) |
532 | /* If a crash is occurring during printk() on this CPU, | 591 | /* If a crash is occurring during printk() on this CPU, |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 396c38b3cb69..7d16e6433302 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -413,6 +413,24 @@ config FORCED_INLINING | |||
413 | become the default in the future, until then this option is there to | 413 | become the default in the future, until then this option is there to |
414 | test gcc for this. | 414 | test gcc for this. |
415 | 415 | ||
416 | config BOOT_PRINTK_DELAY | ||
417 | bool "Delay each boot printk message by N milliseconds" | ||
418 | depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY | ||
419 | help | ||
420 | This build option allows you to read kernel boot messages | ||
421 | by inserting a short delay after each one. The delay is | ||
422 | specified in milliseconds on the kernel command line, | ||
423 | using "boot_delay=N". | ||
424 | |||
425 | It is likely that you would also need to use "lpj=M" to preset | ||
426 | the "loops per jiffie" value. | ||
427 | See a previous boot log for the "lpj" value to use for your | ||
428 | system, and then set "lpj=M" before setting "boot_delay=N". | ||
429 | NOTE: Using this option may adversely affect SMP systems. | ||
430 | I.e., processors other than the first one may not boot up. | ||
431 | BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect | ||
432 | what it believes to be lockup conditions. | ||
433 | |||
416 | config RCU_TORTURE_TEST | 434 | config RCU_TORTURE_TEST |
417 | tristate "torture tests for RCU" | 435 | tristate "torture tests for RCU" |
418 | depends on DEBUG_KERNEL | 436 | depends on DEBUG_KERNEL |