diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2008-03-20 14:43:44 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 14:05:43 -0400 |
commit | 974460c5bfd9f6c38aa3dda189a63f9fc351035f (patch) | |
tree | fbfe9c79956e5fb31ff3da72b628d72d31d5f453 /drivers/misc | |
parent | e3e2aaf7dc0d82a055e084cfd48b9257c0c66b68 (diff) |
kgdb: allow static kgdbts boot configuration
This patch adds in the ability to compile the kgdb internal test
string into the kernel so as to run the tests at boot without changing
the kernel boot arguments. This patch also changes all the error
paths to invoke WARN_ON(1) which will emit the line number of the file
and dump the kernel stack when an error occurs.
You can disable the tests in a kernel that is built this way
using "kgdbts="
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/kgdbts.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index cbc4822b5847..6d6286c4eeac 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -112,6 +112,10 @@ | |||
112 | printk(KERN_INFO a); \ | 112 | printk(KERN_INFO a); \ |
113 | touch_nmi_watchdog(); \ | 113 | touch_nmi_watchdog(); \ |
114 | } while (0) | 114 | } while (0) |
115 | #define eprintk(a...) do { \ | ||
116 | printk(KERN_ERR a); \ | ||
117 | WARN_ON(1); \ | ||
118 | } while (0) | ||
115 | #define MAX_CONFIG_LEN 40 | 119 | #define MAX_CONFIG_LEN 40 |
116 | 120 | ||
117 | static const char hexchars[] = "0123456789abcdef"; | 121 | static const char hexchars[] = "0123456789abcdef"; |
@@ -145,7 +149,11 @@ static struct pt_regs kgdbts_regs; | |||
145 | /* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ | 149 | /* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ |
146 | static int configured = -1; | 150 | static int configured = -1; |
147 | 151 | ||
152 | #ifdef CONFIG_KGDB_TESTS_BOOT_STRING | ||
153 | static char config[MAX_CONFIG_LEN] = CONFIG_KGDB_TESTS_BOOT_STRING; | ||
154 | #else | ||
148 | static char config[MAX_CONFIG_LEN]; | 155 | static char config[MAX_CONFIG_LEN]; |
156 | #endif | ||
149 | static struct kparam_string kps = { | 157 | static struct kparam_string kps = { |
150 | .string = config, | 158 | .string = config, |
151 | .maxlen = MAX_CONFIG_LEN, | 159 | .maxlen = MAX_CONFIG_LEN, |
@@ -289,7 +297,7 @@ static int check_and_rewind_pc(char *put_str, char *arg) | |||
289 | #endif | 297 | #endif |
290 | if (strcmp(arg, "silent") && | 298 | if (strcmp(arg, "silent") && |
291 | instruction_pointer(&kgdbts_regs) + offset != addr) { | 299 | instruction_pointer(&kgdbts_regs) + offset != addr) { |
292 | printk(KERN_ERR "kgdbts: BP mismatch %lx expected %lx\n", | 300 | eprintk("kgdbts: BP mismatch %lx expected %lx\n", |
293 | instruction_pointer(&kgdbts_regs) + offset, addr); | 301 | instruction_pointer(&kgdbts_regs) + offset, addr); |
294 | return 1; | 302 | return 1; |
295 | } | 303 | } |
@@ -313,7 +321,7 @@ static int check_single_step(char *put_str, char *arg) | |||
313 | v2printk("Singlestep stopped at IP: %lx\n", | 321 | v2printk("Singlestep stopped at IP: %lx\n", |
314 | instruction_pointer(&kgdbts_regs)); | 322 | instruction_pointer(&kgdbts_regs)); |
315 | if (instruction_pointer(&kgdbts_regs) == addr) { | 323 | if (instruction_pointer(&kgdbts_regs) == addr) { |
316 | printk(KERN_ERR "kgdbts: SingleStep failed at %lx\n", | 324 | eprintk("kgdbts: SingleStep failed at %lx\n", |
317 | instruction_pointer(&kgdbts_regs)); | 325 | instruction_pointer(&kgdbts_regs)); |
318 | return 1; | 326 | return 1; |
319 | } | 327 | } |
@@ -378,7 +386,7 @@ static void emul_sstep_get(char *arg) | |||
378 | break_helper("z0", 0, sstep_addr); | 386 | break_helper("z0", 0, sstep_addr); |
379 | break; | 387 | break; |
380 | default: | 388 | default: |
381 | printk(KERN_ERR "kgdbts: ERROR failed sstep get emulation\n"); | 389 | eprintk("kgdbts: ERROR failed sstep get emulation\n"); |
382 | } | 390 | } |
383 | sstep_state++; | 391 | sstep_state++; |
384 | } | 392 | } |
@@ -404,26 +412,26 @@ static int emul_sstep_put(char *put_str, char *arg) | |||
404 | break; | 412 | break; |
405 | case 2: | 413 | case 2: |
406 | if (strncmp(put_str, "$OK", 3)) { | 414 | if (strncmp(put_str, "$OK", 3)) { |
407 | printk(KERN_ERR "kgdbts: failed sstep break set\n"); | 415 | eprintk("kgdbts: failed sstep break set\n"); |
408 | return 1; | 416 | return 1; |
409 | } | 417 | } |
410 | break; | 418 | break; |
411 | case 3: | 419 | case 3: |
412 | if (strncmp(put_str, "$T0", 3)) { | 420 | if (strncmp(put_str, "$T0", 3)) { |
413 | printk(KERN_ERR "kgdbts: failed continue sstep\n"); | 421 | eprintk("kgdbts: failed continue sstep\n"); |
414 | return 1; | 422 | return 1; |
415 | } | 423 | } |
416 | break; | 424 | break; |
417 | case 4: | 425 | case 4: |
418 | if (strncmp(put_str, "$OK", 3)) { | 426 | if (strncmp(put_str, "$OK", 3)) { |
419 | printk(KERN_ERR "kgdbts: failed sstep break unset\n"); | 427 | eprintk("kgdbts: failed sstep break unset\n"); |
420 | return 1; | 428 | return 1; |
421 | } | 429 | } |
422 | /* Single step is complete so continue on! */ | 430 | /* Single step is complete so continue on! */ |
423 | sstep_state = 0; | 431 | sstep_state = 0; |
424 | return 0; | 432 | return 0; |
425 | default: | 433 | default: |
426 | printk(KERN_ERR "kgdbts: ERROR failed sstep put emulation\n"); | 434 | eprintk("kgdbts: ERROR failed sstep put emulation\n"); |
427 | } | 435 | } |
428 | 436 | ||
429 | /* Continue on the same test line until emulation is complete */ | 437 | /* Continue on the same test line until emulation is complete */ |
@@ -668,8 +676,7 @@ static int run_simple_test(int is_get_char, int chr) | |||
668 | } | 676 | } |
669 | 677 | ||
670 | if (get_buf[get_buf_cnt] == '\0') { | 678 | if (get_buf[get_buf_cnt] == '\0') { |
671 | printk(KERN_ERR | 679 | eprintk("kgdbts: ERROR GET: EOB on '%s' at %i\n", |
672 | "kgdbts: ERROR GET: end of buffer on '%s' at %i\n", | ||
673 | ts.name, ts.idx); | 680 | ts.name, ts.idx); |
674 | get_buf_cnt = 0; | 681 | get_buf_cnt = 0; |
675 | fill_get_buf("D"); | 682 | fill_get_buf("D"); |
@@ -684,13 +691,13 @@ static int run_simple_test(int is_get_char, int chr) | |||
684 | */ | 691 | */ |
685 | if (ts.tst[ts.idx].get[0] == '\0' && | 692 | if (ts.tst[ts.idx].get[0] == '\0' && |
686 | ts.tst[ts.idx].put[0] == '\0') { | 693 | ts.tst[ts.idx].put[0] == '\0') { |
687 | printk(KERN_ERR "kgdbts: ERROR: beyond end of test on" | 694 | eprintk("kgdbts: ERROR: beyond end of test on" |
688 | " '%s' line %i\n", ts.name, ts.idx); | 695 | " '%s' line %i\n", ts.name, ts.idx); |
689 | return 0; | 696 | return 0; |
690 | } | 697 | } |
691 | 698 | ||
692 | if (put_buf_cnt >= BUFMAX) { | 699 | if (put_buf_cnt >= BUFMAX) { |
693 | printk(KERN_ERR "kgdbts: ERROR: put buffer overflow on" | 700 | eprintk("kgdbts: ERROR: put buffer overflow on" |
694 | " '%s' line %i\n", ts.name, ts.idx); | 701 | " '%s' line %i\n", ts.name, ts.idx); |
695 | put_buf_cnt = 0; | 702 | put_buf_cnt = 0; |
696 | return 0; | 703 | return 0; |
@@ -708,7 +715,7 @@ static int run_simple_test(int is_get_char, int chr) | |||
708 | v2printk("put%i: %s\n", ts.idx, put_buf); | 715 | v2printk("put%i: %s\n", ts.idx, put_buf); |
709 | /* Trigger check here */ | 716 | /* Trigger check here */ |
710 | if (ts.validate_put && ts.validate_put(put_buf)) { | 717 | if (ts.validate_put && ts.validate_put(put_buf)) { |
711 | printk(KERN_ERR "kgdbts: ERROR PUT: end of test " | 718 | eprintk("kgdbts: ERROR PUT: end of test " |
712 | "buffer on '%s' line %i expected %s got %s\n", | 719 | "buffer on '%s' line %i expected %s got %s\n", |
713 | ts.name, ts.idx, ts.tst[ts.idx].put, put_buf); | 720 | ts.name, ts.idx, ts.tst[ts.idx].put, put_buf); |
714 | } | 721 | } |
@@ -772,7 +779,7 @@ static void run_breakpoint_test(int is_hw_breakpoint) | |||
772 | if (test_complete) | 779 | if (test_complete) |
773 | return; | 780 | return; |
774 | 781 | ||
775 | printk(KERN_ERR "kgdbts: ERROR %s test failed\n", ts.name); | 782 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); |
776 | } | 783 | } |
777 | 784 | ||
778 | static void run_hw_break_test(int is_write_test) | 785 | static void run_hw_break_test(int is_write_test) |
@@ -791,7 +798,7 @@ static void run_hw_break_test(int is_write_test) | |||
791 | hw_break_val_access(); | 798 | hw_break_val_access(); |
792 | if (is_write_test) { | 799 | if (is_write_test) { |
793 | if (test_complete == 2) | 800 | if (test_complete == 2) |
794 | printk(KERN_ERR "kgdbts: ERROR %s broke on access\n", | 801 | eprintk("kgdbts: ERROR %s broke on access\n", |
795 | ts.name); | 802 | ts.name); |
796 | hw_break_val_write(); | 803 | hw_break_val_write(); |
797 | } | 804 | } |
@@ -800,7 +807,7 @@ static void run_hw_break_test(int is_write_test) | |||
800 | if (test_complete == 1) | 807 | if (test_complete == 1) |
801 | return; | 808 | return; |
802 | 809 | ||
803 | printk(KERN_ERR "kgdbts: ERROR %s test failed\n", ts.name); | 810 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); |
804 | } | 811 | } |
805 | 812 | ||
806 | static void run_nmi_sleep_test(int nmi_sleep) | 813 | static void run_nmi_sleep_test(int nmi_sleep) |
@@ -817,12 +824,12 @@ static void run_nmi_sleep_test(int nmi_sleep) | |||
817 | touch_nmi_watchdog(); | 824 | touch_nmi_watchdog(); |
818 | local_irq_restore(flags); | 825 | local_irq_restore(flags); |
819 | if (test_complete != 2) | 826 | if (test_complete != 2) |
820 | printk(KERN_ERR "kgdbts: ERROR nmi_test did not hit nmi\n"); | 827 | eprintk("kgdbts: ERROR nmi_test did not hit nmi\n"); |
821 | kgdb_breakpoint(); | 828 | kgdb_breakpoint(); |
822 | if (test_complete == 1) | 829 | if (test_complete == 1) |
823 | return; | 830 | return; |
824 | 831 | ||
825 | printk(KERN_ERR "kgdbts: ERROR %s test failed\n", ts.name); | 832 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); |
826 | } | 833 | } |
827 | 834 | ||
828 | static void run_bad_read_test(void) | 835 | static void run_bad_read_test(void) |