diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/kgdbts.c | 33 |
1 files changed, 26 insertions, 7 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. |