diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2012-03-29 07:55:44 -0400 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2012-03-29 18:41:24 -0400 |
commit | 456ca7ff24841bf2d2a2dfd690fe7d42ef70d932 (patch) | |
tree | 979edc05aadcf59f7f9896ceb4d03b6586f3f19b /drivers/misc | |
parent | 78724b8ef83fc2bcfbc0a72a7ad8a3ce5ad25e6a (diff) |
kgdbts: Fix kernel oops with CONFIG_DEBUG_RODATA
On x86 the kgdb test suite will oops when the kernel is compiled with
CONFIG_DEBUG_RODATA and you run the tests after boot time. This is
regression has existed since 2.6.26 by commit: b33cb815 (kgdbts: Use
HW breakpoints with CONFIG_DEBUG_RODATA).
The test suite can use hw breakpoints for all the tests, but it has to
execute the hardware breakpoint specific tests first in order to
determine that the hw breakpoints actually work. Specifically the
very first test causes an oops:
# echo V1I1 > /sys/module/kgdbts/parameters/kgdbts
kgdb: Registered I/O driver kgdbts.
kgdbts:RUN plant and detach test
Entering kdb (current=0xffff880017aa9320, pid 1078) on processor 0 due to Keyboard Entry
[0]kdb> kgdbts: ERROR PUT: end of test buffer on 'plant_and_detach_test' line 1 expected OK got $E14#aa
WARNING: at drivers/misc/kgdbts.c:730 run_simple_test+0x151/0x2c0()
[...oops clipped...]
This commit re-orders the running of the tests and puts the RODATA
check into its own function so as to correctly avoid the kernel oops
by detecting and using the hw breakpoints.
Cc: <stable@vger.kernel.org> # >= 2.6.26
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/kgdbts.c | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3f7ad83ed740..997e94d618ba 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -885,6 +885,22 @@ static void run_singlestep_break_test(void) | |||
885 | kgdbts_break_test(); | 885 | kgdbts_break_test(); |
886 | } | 886 | } |
887 | 887 | ||
888 | static void test_debug_rodata(void) | ||
889 | { | ||
890 | #ifdef CONFIG_DEBUG_RODATA | ||
891 | /* Until there is an api to write to read-only text segments, use | ||
892 | * HW breakpoints for the remainder of any tests, else print a | ||
893 | * failure message if hw breakpoints do not work. | ||
894 | */ | ||
895 | if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { | ||
896 | eprintk("kgdbts: HW breakpoints BROKEN, ending tests\n"); | ||
897 | return; | ||
898 | } | ||
899 | force_hwbrks = 1; | ||
900 | v1printk("kgdbts:Using HW breakpoints for SW breakpoint tests\n"); | ||
901 | #endif /* CONFIG_DEBUG_RODATA */ | ||
902 | } | ||
903 | |||
888 | static void kgdbts_run_tests(void) | 904 | static void kgdbts_run_tests(void) |
889 | { | 905 | { |
890 | char *ptr; | 906 | char *ptr; |
@@ -907,6 +923,18 @@ static void kgdbts_run_tests(void) | |||
907 | if (ptr) | 923 | if (ptr) |
908 | sstep_test = simple_strtol(ptr+1, NULL, 10); | 924 | sstep_test = simple_strtol(ptr+1, NULL, 10); |
909 | 925 | ||
926 | /* All HW break point tests */ | ||
927 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { | ||
928 | hwbreaks_ok = 1; | ||
929 | v1printk("kgdbts:RUN hw breakpoint test\n"); | ||
930 | run_breakpoint_test(1); | ||
931 | v1printk("kgdbts:RUN hw write breakpoint test\n"); | ||
932 | run_hw_break_test(1); | ||
933 | v1printk("kgdbts:RUN access write breakpoint test\n"); | ||
934 | run_hw_break_test(0); | ||
935 | } | ||
936 | test_debug_rodata(); | ||
937 | |||
910 | /* required internal KGDB tests */ | 938 | /* required internal KGDB tests */ |
911 | v1printk("kgdbts:RUN plant and detach test\n"); | 939 | v1printk("kgdbts:RUN plant and detach test\n"); |
912 | run_plant_and_detach_test(0); | 940 | run_plant_and_detach_test(0); |
@@ -924,35 +952,11 @@ static void kgdbts_run_tests(void) | |||
924 | 952 | ||
925 | /* ===Optional tests=== */ | 953 | /* ===Optional tests=== */ |
926 | 954 | ||
927 | /* All HW break point tests */ | ||
928 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { | ||
929 | hwbreaks_ok = 1; | ||
930 | v1printk("kgdbts:RUN hw breakpoint test\n"); | ||
931 | run_breakpoint_test(1); | ||
932 | v1printk("kgdbts:RUN hw write breakpoint test\n"); | ||
933 | run_hw_break_test(1); | ||
934 | v1printk("kgdbts:RUN access write breakpoint test\n"); | ||
935 | run_hw_break_test(0); | ||
936 | } | ||
937 | |||
938 | if (nmi_sleep) { | 955 | if (nmi_sleep) { |
939 | v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep); | 956 | v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep); |
940 | run_nmi_sleep_test(nmi_sleep); | 957 | run_nmi_sleep_test(nmi_sleep); |
941 | } | 958 | } |
942 | 959 | ||
943 | #ifdef CONFIG_DEBUG_RODATA | ||
944 | /* Until there is an api to write to read-only text segments, use | ||
945 | * HW breakpoints for the remainder of any tests, else print a | ||
946 | * failure message if hw breakpoints do not work. | ||
947 | */ | ||
948 | if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { | ||
949 | eprintk("kgdbts: HW breakpoints do not work," | ||
950 | "skipping remaining tests\n"); | ||
951 | return; | ||
952 | } | ||
953 | force_hwbrks = 1; | ||
954 | #endif /* CONFIG_DEBUG_RODATA */ | ||
955 | |||
956 | /* If the do_fork test is run it will be the last test that is | 960 | /* If the do_fork test is run it will be the last test that is |
957 | * executed because a kernel thread will be spawned at the very | 961 | * executed because a kernel thread will be spawned at the very |
958 | * end to unregister the debug hooks. | 962 | * end to unregister the debug hooks. |