diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-04 11:08:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-04 11:08:27 -0400 |
commit | 3b5b60b821e0e97531df9b0ba295283ab5a8859a (patch) | |
tree | e94b3e4945f4b5bb592989445ebbda790a047b96 | |
parent | d430a227d272fa514bade388bf511dba4ec2962a (diff) | |
parent | b33cb815b565a94c654a0fe8e62e36f5b4053888 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb:
kgdbts: Use HW breakpoints with CONFIG_DEBUG_RODATA
kgdb: use common ascii helpers and put_unaligned_be32 helper
-rw-r--r-- | drivers/misc/kgdbts.c | 33 | ||||
-rw-r--r-- | kernel/kgdb.c | 16 |
2 files changed, 32 insertions, 17 deletions
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index fa394104339c..e4ff50b95a5e 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -102,7 +102,6 @@ | |||
102 | #include <linux/nmi.h> | 102 | #include <linux/nmi.h> |
103 | #include <linux/delay.h> | 103 | #include <linux/delay.h> |
104 | #include <linux/kthread.h> | 104 | #include <linux/kthread.h> |
105 | #include <linux/delay.h> | ||
106 | 105 | ||
107 | #define v1printk(a...) do { \ | 106 | #define v1printk(a...) do { \ |
108 | if (verbose) \ | 107 | if (verbose) \ |
@@ -119,7 +118,6 @@ | |||
119 | } while (0) | 118 | } while (0) |
120 | #define MAX_CONFIG_LEN 40 | 119 | #define MAX_CONFIG_LEN 40 |
121 | 120 | ||
122 | static const char hexchars[] = "0123456789abcdef"; | ||
123 | static struct kgdb_io kgdbts_io_ops; | 121 | static struct kgdb_io kgdbts_io_ops; |
124 | static char get_buf[BUFMAX]; | 122 | static char get_buf[BUFMAX]; |
125 | static int get_buf_cnt; | 123 | static int get_buf_cnt; |
@@ -131,6 +129,8 @@ static int repeat_test; | |||
131 | static int test_complete; | 129 | static int test_complete; |
132 | static int send_ack; | 130 | static int send_ack; |
133 | static int final_ack; | 131 | static int final_ack; |
132 | static int force_hwbrks; | ||
133 | static int hwbreaks_ok; | ||
134 | static int hw_break_val; | 134 | static int hw_break_val; |
135 | static int hw_break_val2; | 135 | static int hw_break_val2; |
136 | #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) | 136 | #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) |
@@ -234,12 +234,12 @@ static void break_helper(char *bp_type, char *arg, unsigned long vaddr) | |||
234 | 234 | ||
235 | static void sw_break(char *arg) | 235 | static void sw_break(char *arg) |
236 | { | 236 | { |
237 | break_helper("Z0", arg, 0); | 237 | break_helper(force_hwbrks ? "Z1" : "Z0", arg, 0); |
238 | } | 238 | } |
239 | 239 | ||
240 | static void sw_rem_break(char *arg) | 240 | static void sw_rem_break(char *arg) |
241 | { | 241 | { |
242 | break_helper("z0", arg, 0); | 242 | break_helper(force_hwbrks ? "z1" : "z0", arg, 0); |
243 | } | 243 | } |
244 | 244 | ||
245 | static void hw_break(char *arg) | 245 | static void hw_break(char *arg) |
@@ -619,8 +619,8 @@ static void fill_get_buf(char *buf) | |||
619 | count++; | 619 | count++; |
620 | } | 620 | } |
621 | strcat(get_buf, "#"); | 621 | strcat(get_buf, "#"); |
622 | get_buf[count + 2] = hexchars[checksum >> 4]; | 622 | get_buf[count + 2] = hex_asc_hi(checksum); |
623 | get_buf[count + 3] = hexchars[checksum & 0xf]; | 623 | get_buf[count + 3] = hex_asc_lo(checksum); |
624 | get_buf[count + 4] = '\0'; | 624 | get_buf[count + 4] = '\0'; |
625 | v2printk("get%i: %s\n", ts.idx, get_buf); | 625 | v2printk("get%i: %s\n", ts.idx, get_buf); |
626 | } | 626 | } |
@@ -781,6 +781,8 @@ static void run_breakpoint_test(int is_hw_breakpoint) | |||
781 | return; | 781 | return; |
782 | 782 | ||
783 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); | 783 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); |
784 | if (is_hw_breakpoint) | ||
785 | hwbreaks_ok = 0; | ||
784 | } | 786 | } |
785 | 787 | ||
786 | static void run_hw_break_test(int is_write_test) | 788 | static void run_hw_break_test(int is_write_test) |
@@ -798,9 +800,11 @@ static void run_hw_break_test(int is_write_test) | |||
798 | kgdb_breakpoint(); | 800 | kgdb_breakpoint(); |
799 | hw_break_val_access(); | 801 | hw_break_val_access(); |
800 | if (is_write_test) { | 802 | if (is_write_test) { |
801 | if (test_complete == 2) | 803 | if (test_complete == 2) { |
802 | eprintk("kgdbts: ERROR %s broke on access\n", | 804 | eprintk("kgdbts: ERROR %s broke on access\n", |
803 | ts.name); | 805 | ts.name); |
806 | hwbreaks_ok = 0; | ||
807 | } | ||
804 | hw_break_val_write(); | 808 | hw_break_val_write(); |
805 | } | 809 | } |
806 | kgdb_breakpoint(); | 810 | kgdb_breakpoint(); |
@@ -809,6 +813,7 @@ static void run_hw_break_test(int is_write_test) | |||
809 | return; | 813 | return; |
810 | 814 | ||
811 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); | 815 | eprintk("kgdbts: ERROR %s test failed\n", ts.name); |
816 | hwbreaks_ok = 0; | ||
812 | } | 817 | } |
813 | 818 | ||
814 | static void run_nmi_sleep_test(int nmi_sleep) | 819 | static void run_nmi_sleep_test(int nmi_sleep) |
@@ -912,6 +917,7 @@ static void kgdbts_run_tests(void) | |||
912 | 917 | ||
913 | /* All HW break point tests */ | 918 | /* All HW break point tests */ |
914 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { | 919 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { |
920 | hwbreaks_ok = 1; | ||
915 | v1printk("kgdbts:RUN hw breakpoint test\n"); | 921 | v1printk("kgdbts:RUN hw breakpoint test\n"); |
916 | run_breakpoint_test(1); | 922 | run_breakpoint_test(1); |
917 | v1printk("kgdbts:RUN hw write breakpoint test\n"); | 923 | v1printk("kgdbts:RUN hw write breakpoint test\n"); |
@@ -925,6 +931,19 @@ static void kgdbts_run_tests(void) | |||
925 | run_nmi_sleep_test(nmi_sleep); | 931 | run_nmi_sleep_test(nmi_sleep); |
926 | } | 932 | } |
927 | 933 | ||
934 | #ifdef CONFIG_DEBUG_RODATA | ||
935 | /* Until there is an api to write to read-only text segments, use | ||
936 | * HW breakpoints for the remainder of any tests, else print a | ||
937 | * failure message if hw breakpoints do not work. | ||
938 | */ | ||
939 | if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { | ||
940 | eprintk("kgdbts: HW breakpoints do not work," | ||
941 | "skipping remaining tests\n"); | ||
942 | return; | ||
943 | } | ||
944 | force_hwbrks = 1; | ||
945 | #endif /* CONFIG_DEBUG_RODATA */ | ||
946 | |||
928 | /* If the do_fork test is run it will be the last test that is | 947 | /* If the do_fork test is run it will be the last test that is |
929 | * executed because a kernel thread will be spawned at the very | 948 | * executed because a kernel thread will be spawned at the very |
930 | * end to unregister the debug hooks. | 949 | * end to unregister the debug hooks. |
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 14787de568b3..79e3c90113c2 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <asm/byteorder.h> | 52 | #include <asm/byteorder.h> |
53 | #include <asm/atomic.h> | 53 | #include <asm/atomic.h> |
54 | #include <asm/system.h> | 54 | #include <asm/system.h> |
55 | #include <asm/unaligned.h> | ||
55 | 56 | ||
56 | static int kgdb_break_asap; | 57 | static int kgdb_break_asap; |
57 | 58 | ||
@@ -227,8 +228,6 @@ void __weak kgdb_disable_hw_debug(struct pt_regs *regs) | |||
227 | * GDB remote protocol parser: | 228 | * GDB remote protocol parser: |
228 | */ | 229 | */ |
229 | 230 | ||
230 | static const char hexchars[] = "0123456789abcdef"; | ||
231 | |||
232 | static int hex(char ch) | 231 | static int hex(char ch) |
233 | { | 232 | { |
234 | if ((ch >= 'a') && (ch <= 'f')) | 233 | if ((ch >= 'a') && (ch <= 'f')) |
@@ -316,8 +315,8 @@ static void put_packet(char *buffer) | |||
316 | } | 315 | } |
317 | 316 | ||
318 | kgdb_io_ops->write_char('#'); | 317 | kgdb_io_ops->write_char('#'); |
319 | kgdb_io_ops->write_char(hexchars[checksum >> 4]); | 318 | kgdb_io_ops->write_char(hex_asc_hi(checksum)); |
320 | kgdb_io_ops->write_char(hexchars[checksum & 0xf]); | 319 | kgdb_io_ops->write_char(hex_asc_lo(checksum)); |
321 | if (kgdb_io_ops->flush) | 320 | if (kgdb_io_ops->flush) |
322 | kgdb_io_ops->flush(); | 321 | kgdb_io_ops->flush(); |
323 | 322 | ||
@@ -478,8 +477,8 @@ static void error_packet(char *pkt, int error) | |||
478 | { | 477 | { |
479 | error = -error; | 478 | error = -error; |
480 | pkt[0] = 'E'; | 479 | pkt[0] = 'E'; |
481 | pkt[1] = hexchars[(error / 10)]; | 480 | pkt[1] = hex_asc[(error / 10)]; |
482 | pkt[2] = hexchars[(error % 10)]; | 481 | pkt[2] = hex_asc[(error % 10)]; |
483 | pkt[3] = '\0'; | 482 | pkt[3] = '\0'; |
484 | } | 483 | } |
485 | 484 | ||
@@ -510,10 +509,7 @@ static void int_to_threadref(unsigned char *id, int value) | |||
510 | scan = (unsigned char *)id; | 509 | scan = (unsigned char *)id; |
511 | while (i--) | 510 | while (i--) |
512 | *scan++ = 0; | 511 | *scan++ = 0; |
513 | *scan++ = (value >> 24) & 0xff; | 512 | put_unaligned_be32(value, scan); |
514 | *scan++ = (value >> 16) & 0xff; | ||
515 | *scan++ = (value >> 8) & 0xff; | ||
516 | *scan++ = (value & 0xff); | ||
517 | } | 513 | } |
518 | 514 | ||
519 | static struct task_struct *getthread(struct pt_regs *regs, int tid) | 515 | static struct task_struct *getthread(struct pt_regs *regs, int tid) |