diff options
Diffstat (limited to 'drivers/misc/kgdbts.c')
-rw-r--r-- | drivers/misc/kgdbts.c | 160 |
1 files changed, 115 insertions, 45 deletions
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3f7ad83ed74..3aa9a969b37 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -134,12 +134,17 @@ static int force_hwbrks; | |||
134 | static int hwbreaks_ok; | 134 | static int hwbreaks_ok; |
135 | static int hw_break_val; | 135 | static int hw_break_val; |
136 | static int hw_break_val2; | 136 | static int hw_break_val2; |
137 | static int cont_instead_of_sstep; | ||
138 | static unsigned long cont_thread_id; | ||
139 | static unsigned long sstep_thread_id; | ||
137 | #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) | 140 | #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) |
138 | static int arch_needs_sstep_emulation = 1; | 141 | static int arch_needs_sstep_emulation = 1; |
139 | #else | 142 | #else |
140 | static int arch_needs_sstep_emulation; | 143 | static int arch_needs_sstep_emulation; |
141 | #endif | 144 | #endif |
145 | static unsigned long cont_addr; | ||
142 | static unsigned long sstep_addr; | 146 | static unsigned long sstep_addr; |
147 | static int restart_from_top_after_write; | ||
143 | static int sstep_state; | 148 | static int sstep_state; |
144 | 149 | ||
145 | /* Storage for the registers, in GDB format. */ | 150 | /* Storage for the registers, in GDB format. */ |
@@ -187,7 +192,8 @@ static int kgdbts_unreg_thread(void *ptr) | |||
187 | */ | 192 | */ |
188 | while (!final_ack) | 193 | while (!final_ack) |
189 | msleep_interruptible(1500); | 194 | msleep_interruptible(1500); |
190 | 195 | /* Pause for any other threads to exit after final ack. */ | |
196 | msleep_interruptible(1000); | ||
191 | if (configured) | 197 | if (configured) |
192 | kgdb_unregister_io_module(&kgdbts_io_ops); | 198 | kgdb_unregister_io_module(&kgdbts_io_ops); |
193 | configured = 0; | 199 | configured = 0; |
@@ -211,7 +217,7 @@ static unsigned long lookup_addr(char *arg) | |||
211 | if (!strcmp(arg, "kgdbts_break_test")) | 217 | if (!strcmp(arg, "kgdbts_break_test")) |
212 | addr = (unsigned long)kgdbts_break_test; | 218 | addr = (unsigned long)kgdbts_break_test; |
213 | else if (!strcmp(arg, "sys_open")) | 219 | else if (!strcmp(arg, "sys_open")) |
214 | addr = (unsigned long)sys_open; | 220 | addr = (unsigned long)do_sys_open; |
215 | else if (!strcmp(arg, "do_fork")) | 221 | else if (!strcmp(arg, "do_fork")) |
216 | addr = (unsigned long)do_fork; | 222 | addr = (unsigned long)do_fork; |
217 | else if (!strcmp(arg, "hw_break_val")) | 223 | else if (!strcmp(arg, "hw_break_val")) |
@@ -283,6 +289,16 @@ static void hw_break_val_write(void) | |||
283 | hw_break_val++; | 289 | hw_break_val++; |
284 | } | 290 | } |
285 | 291 | ||
292 | static int get_thread_id_continue(char *put_str, char *arg) | ||
293 | { | ||
294 | char *ptr = &put_str[11]; | ||
295 | |||
296 | if (put_str[1] != 'T' || put_str[2] != '0') | ||
297 | return 1; | ||
298 | kgdb_hex2long(&ptr, &cont_thread_id); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
286 | static int check_and_rewind_pc(char *put_str, char *arg) | 302 | static int check_and_rewind_pc(char *put_str, char *arg) |
287 | { | 303 | { |
288 | unsigned long addr = lookup_addr(arg); | 304 | unsigned long addr = lookup_addr(arg); |
@@ -299,13 +315,21 @@ static int check_and_rewind_pc(char *put_str, char *arg) | |||
299 | if (addr + BREAK_INSTR_SIZE == ip) | 315 | if (addr + BREAK_INSTR_SIZE == ip) |
300 | offset = -BREAK_INSTR_SIZE; | 316 | offset = -BREAK_INSTR_SIZE; |
301 | #endif | 317 | #endif |
302 | if (strcmp(arg, "silent") && ip + offset != addr) { | 318 | |
319 | if (arch_needs_sstep_emulation && sstep_addr && | ||
320 | ip + offset == sstep_addr && | ||
321 | ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) { | ||
322 | /* This is special case for emulated single step */ | ||
323 | v2printk("Emul: rewind hit single step bp\n"); | ||
324 | restart_from_top_after_write = 1; | ||
325 | } else if (strcmp(arg, "silent") && ip + offset != addr) { | ||
303 | eprintk("kgdbts: BP mismatch %lx expected %lx\n", | 326 | eprintk("kgdbts: BP mismatch %lx expected %lx\n", |
304 | ip + offset, addr); | 327 | ip + offset, addr); |
305 | return 1; | 328 | return 1; |
306 | } | 329 | } |
307 | /* Readjust the instruction pointer if needed */ | 330 | /* Readjust the instruction pointer if needed */ |
308 | ip += offset; | 331 | ip += offset; |
332 | cont_addr = ip; | ||
309 | #ifdef GDB_ADJUSTS_BREAK_OFFSET | 333 | #ifdef GDB_ADJUSTS_BREAK_OFFSET |
310 | instruction_pointer_set(&kgdbts_regs, ip); | 334 | instruction_pointer_set(&kgdbts_regs, ip); |
311 | #endif | 335 | #endif |
@@ -315,6 +339,8 @@ static int check_and_rewind_pc(char *put_str, char *arg) | |||
315 | static int check_single_step(char *put_str, char *arg) | 339 | static int check_single_step(char *put_str, char *arg) |
316 | { | 340 | { |
317 | unsigned long addr = lookup_addr(arg); | 341 | unsigned long addr = lookup_addr(arg); |
342 | static int matched_id; | ||
343 | |||
318 | /* | 344 | /* |
319 | * From an arch indepent point of view the instruction pointer | 345 | * From an arch indepent point of view the instruction pointer |
320 | * should be on a different instruction | 346 | * should be on a different instruction |
@@ -324,6 +350,29 @@ static int check_single_step(char *put_str, char *arg) | |||
324 | gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); | 350 | gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); |
325 | v2printk("Singlestep stopped at IP: %lx\n", | 351 | v2printk("Singlestep stopped at IP: %lx\n", |
326 | instruction_pointer(&kgdbts_regs)); | 352 | instruction_pointer(&kgdbts_regs)); |
353 | |||
354 | if (sstep_thread_id != cont_thread_id) { | ||
355 | /* | ||
356 | * Ensure we stopped in the same thread id as before, else the | ||
357 | * debugger should continue until the original thread that was | ||
358 | * single stepped is scheduled again, emulating gdb's behavior. | ||
359 | */ | ||
360 | v2printk("ThrID does not match: %lx\n", cont_thread_id); | ||
361 | if (arch_needs_sstep_emulation) { | ||
362 | if (matched_id && | ||
363 | instruction_pointer(&kgdbts_regs) != addr) | ||
364 | goto continue_test; | ||
365 | matched_id++; | ||
366 | ts.idx -= 2; | ||
367 | sstep_state = 0; | ||
368 | return 0; | ||
369 | } | ||
370 | cont_instead_of_sstep = 1; | ||
371 | ts.idx -= 4; | ||
372 | return 0; | ||
373 | } | ||
374 | continue_test: | ||
375 | matched_id = 0; | ||
327 | if (instruction_pointer(&kgdbts_regs) == addr) { | 376 | if (instruction_pointer(&kgdbts_regs) == addr) { |
328 | eprintk("kgdbts: SingleStep failed at %lx\n", | 377 | eprintk("kgdbts: SingleStep failed at %lx\n", |
329 | instruction_pointer(&kgdbts_regs)); | 378 | instruction_pointer(&kgdbts_regs)); |
@@ -365,10 +414,40 @@ static int got_break(char *put_str, char *arg) | |||
365 | return 1; | 414 | return 1; |
366 | } | 415 | } |
367 | 416 | ||
417 | static void get_cont_catch(char *arg) | ||
418 | { | ||
419 | /* Always send detach because the test is completed at this point */ | ||
420 | fill_get_buf("D"); | ||
421 | } | ||
422 | |||
423 | static int put_cont_catch(char *put_str, char *arg) | ||
424 | { | ||
425 | /* This is at the end of the test and we catch any and all input */ | ||
426 | v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id); | ||
427 | ts.idx--; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int emul_reset(char *put_str, char *arg) | ||
432 | { | ||
433 | if (strncmp(put_str, "$OK", 3)) | ||
434 | return 1; | ||
435 | if (restart_from_top_after_write) { | ||
436 | restart_from_top_after_write = 0; | ||
437 | ts.idx = -1; | ||
438 | } | ||
439 | return 0; | ||
440 | } | ||
441 | |||
368 | static void emul_sstep_get(char *arg) | 442 | static void emul_sstep_get(char *arg) |
369 | { | 443 | { |
370 | if (!arch_needs_sstep_emulation) { | 444 | if (!arch_needs_sstep_emulation) { |
371 | fill_get_buf(arg); | 445 | if (cont_instead_of_sstep) { |
446 | cont_instead_of_sstep = 0; | ||
447 | fill_get_buf("c"); | ||
448 | } else { | ||
449 | fill_get_buf(arg); | ||
450 | } | ||
372 | return; | 451 | return; |
373 | } | 452 | } |
374 | switch (sstep_state) { | 453 | switch (sstep_state) { |
@@ -398,9 +477,11 @@ static void emul_sstep_get(char *arg) | |||
398 | static int emul_sstep_put(char *put_str, char *arg) | 477 | static int emul_sstep_put(char *put_str, char *arg) |
399 | { | 478 | { |
400 | if (!arch_needs_sstep_emulation) { | 479 | if (!arch_needs_sstep_emulation) { |
401 | if (!strncmp(put_str+1, arg, 2)) | 480 | char *ptr = &put_str[11]; |
402 | return 0; | 481 | if (put_str[1] != 'T' || put_str[2] != '0') |
403 | return 1; | 482 | return 1; |
483 | kgdb_hex2long(&ptr, &sstep_thread_id); | ||
484 | return 0; | ||
404 | } | 485 | } |
405 | switch (sstep_state) { | 486 | switch (sstep_state) { |
406 | case 1: | 487 | case 1: |
@@ -411,8 +492,7 @@ static int emul_sstep_put(char *put_str, char *arg) | |||
411 | v2printk("Stopped at IP: %lx\n", | 492 | v2printk("Stopped at IP: %lx\n", |
412 | instruction_pointer(&kgdbts_regs)); | 493 | instruction_pointer(&kgdbts_regs)); |
413 | /* Want to stop at IP + break instruction size by default */ | 494 | /* Want to stop at IP + break instruction size by default */ |
414 | sstep_addr = instruction_pointer(&kgdbts_regs) + | 495 | sstep_addr = cont_addr + BREAK_INSTR_SIZE; |
415 | BREAK_INSTR_SIZE; | ||
416 | break; | 496 | break; |
417 | case 2: | 497 | case 2: |
418 | if (strncmp(put_str, "$OK", 3)) { | 498 | if (strncmp(put_str, "$OK", 3)) { |
@@ -424,6 +504,9 @@ static int emul_sstep_put(char *put_str, char *arg) | |||
424 | if (strncmp(put_str, "$T0", 3)) { | 504 | if (strncmp(put_str, "$T0", 3)) { |
425 | eprintk("kgdbts: failed continue sstep\n"); | 505 | eprintk("kgdbts: failed continue sstep\n"); |
426 | return 1; | 506 | return 1; |
507 | } else { | ||
508 | char *ptr = &put_str[11]; | ||
509 | kgdb_hex2long(&ptr, &sstep_thread_id); | ||
427 | } | 510 | } |
428 | break; | 511 | break; |
429 | case 4: | 512 | case 4: |
@@ -502,10 +585,10 @@ static struct test_struct bad_read_test[] = { | |||
502 | static struct test_struct singlestep_break_test[] = { | 585 | static struct test_struct singlestep_break_test[] = { |
503 | { "?", "S0*" }, /* Clear break points */ | 586 | { "?", "S0*" }, /* Clear break points */ |
504 | { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ | 587 | { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ |
505 | { "c", "T0*", }, /* Continue */ | 588 | { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ |
589 | { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ | ||
506 | { "g", "kgdbts_break_test", NULL, check_and_rewind_pc }, | 590 | { "g", "kgdbts_break_test", NULL, check_and_rewind_pc }, |
507 | { "write", "OK", write_regs }, /* Write registers */ | 591 | { "write", "OK", write_regs }, /* Write registers */ |
508 | { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ | ||
509 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ | 592 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ |
510 | { "g", "kgdbts_break_test", NULL, check_single_step }, | 593 | { "g", "kgdbts_break_test", NULL, check_single_step }, |
511 | { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ | 594 | { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ |
@@ -523,16 +606,16 @@ static struct test_struct singlestep_break_test[] = { | |||
523 | static struct test_struct do_fork_test[] = { | 606 | static struct test_struct do_fork_test[] = { |
524 | { "?", "S0*" }, /* Clear break points */ | 607 | { "?", "S0*" }, /* Clear break points */ |
525 | { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ | 608 | { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ |
526 | { "c", "T0*", }, /* Continue */ | 609 | { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ |
527 | { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */ | ||
528 | { "write", "OK", write_regs }, /* Write registers */ | ||
529 | { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ | 610 | { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ |
611 | { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */ | ||
612 | { "write", "OK", write_regs, emul_reset }, /* Write registers */ | ||
530 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ | 613 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ |
531 | { "g", "do_fork", NULL, check_single_step }, | 614 | { "g", "do_fork", NULL, check_single_step }, |
532 | { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ | 615 | { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ |
533 | { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ | 616 | { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ |
534 | { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ | 617 | { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ |
535 | { "", "" }, | 618 | { "", "", get_cont_catch, put_cont_catch }, |
536 | }; | 619 | }; |
537 | 620 | ||
538 | /* Test for hitting a breakpoint at sys_open for what ever the number | 621 | /* Test for hitting a breakpoint at sys_open for what ever the number |
@@ -541,16 +624,16 @@ static struct test_struct do_fork_test[] = { | |||
541 | static struct test_struct sys_open_test[] = { | 624 | static struct test_struct sys_open_test[] = { |
542 | { "?", "S0*" }, /* Clear break points */ | 625 | { "?", "S0*" }, /* Clear break points */ |
543 | { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ | 626 | { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ |
544 | { "c", "T0*", }, /* Continue */ | 627 | { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ |
545 | { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */ | ||
546 | { "write", "OK", write_regs }, /* Write registers */ | ||
547 | { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ | 628 | { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ |
629 | { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */ | ||
630 | { "write", "OK", write_regs, emul_reset }, /* Write registers */ | ||
548 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ | 631 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ |
549 | { "g", "sys_open", NULL, check_single_step }, | 632 | { "g", "sys_open", NULL, check_single_step }, |
550 | { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ | 633 | { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ |
551 | { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ | 634 | { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ |
552 | { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ | 635 | { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ |
553 | { "", "" }, | 636 | { "", "", get_cont_catch, put_cont_catch }, |
554 | }; | 637 | }; |
555 | 638 | ||
556 | /* | 639 | /* |
@@ -693,8 +776,8 @@ static int run_simple_test(int is_get_char, int chr) | |||
693 | /* This callback is a put char which is when kgdb sends data to | 776 | /* This callback is a put char which is when kgdb sends data to |
694 | * this I/O module. | 777 | * this I/O module. |
695 | */ | 778 | */ |
696 | if (ts.tst[ts.idx].get[0] == '\0' && | 779 | if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' && |
697 | ts.tst[ts.idx].put[0] == '\0') { | 780 | !ts.tst[ts.idx].get_handler) { |
698 | eprintk("kgdbts: ERROR: beyond end of test on" | 781 | eprintk("kgdbts: ERROR: beyond end of test on" |
699 | " '%s' line %i\n", ts.name, ts.idx); | 782 | " '%s' line %i\n", ts.name, ts.idx); |
700 | return 0; | 783 | return 0; |
@@ -907,6 +990,17 @@ static void kgdbts_run_tests(void) | |||
907 | if (ptr) | 990 | if (ptr) |
908 | sstep_test = simple_strtol(ptr+1, NULL, 10); | 991 | sstep_test = simple_strtol(ptr+1, NULL, 10); |
909 | 992 | ||
993 | /* All HW break point tests */ | ||
994 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { | ||
995 | hwbreaks_ok = 1; | ||
996 | v1printk("kgdbts:RUN hw breakpoint test\n"); | ||
997 | run_breakpoint_test(1); | ||
998 | v1printk("kgdbts:RUN hw write breakpoint test\n"); | ||
999 | run_hw_break_test(1); | ||
1000 | v1printk("kgdbts:RUN access write breakpoint test\n"); | ||
1001 | run_hw_break_test(0); | ||
1002 | } | ||
1003 | |||
910 | /* required internal KGDB tests */ | 1004 | /* required internal KGDB tests */ |
911 | v1printk("kgdbts:RUN plant and detach test\n"); | 1005 | v1printk("kgdbts:RUN plant and detach test\n"); |
912 | run_plant_and_detach_test(0); | 1006 | run_plant_and_detach_test(0); |
@@ -924,35 +1018,11 @@ static void kgdbts_run_tests(void) | |||
924 | 1018 | ||
925 | /* ===Optional tests=== */ | 1019 | /* ===Optional tests=== */ |
926 | 1020 | ||
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) { | 1021 | if (nmi_sleep) { |
939 | v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep); | 1022 | v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep); |
940 | run_nmi_sleep_test(nmi_sleep); | 1023 | run_nmi_sleep_test(nmi_sleep); |
941 | } | 1024 | } |
942 | 1025 | ||
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 | 1026 | /* 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 | 1027 | * executed because a kernel thread will be spawned at the very |
958 | * end to unregister the debug hooks. | 1028 | * end to unregister the debug hooks. |