diff options
| -rw-r--r-- | arch/x86/kernel/kgdb.c | 60 | ||||
| -rw-r--r-- | drivers/misc/kgdbts.c | 160 | ||||
| -rw-r--r-- | include/linux/kgdb.h | 7 | ||||
| -rw-r--r-- | kernel/debug/debug_core.c | 53 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_io.c | 2 |
5 files changed, 204 insertions, 78 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index db6720edfdd0..8bfb6146f753 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
| @@ -43,6 +43,8 @@ | |||
| 43 | #include <linux/smp.h> | 43 | #include <linux/smp.h> |
| 44 | #include <linux/nmi.h> | 44 | #include <linux/nmi.h> |
| 45 | #include <linux/hw_breakpoint.h> | 45 | #include <linux/hw_breakpoint.h> |
| 46 | #include <linux/uaccess.h> | ||
| 47 | #include <linux/memory.h> | ||
| 46 | 48 | ||
| 47 | #include <asm/debugreg.h> | 49 | #include <asm/debugreg.h> |
| 48 | #include <asm/apicdef.h> | 50 | #include <asm/apicdef.h> |
| @@ -741,6 +743,64 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) | |||
| 741 | regs->ip = ip; | 743 | regs->ip = ip; |
| 742 | } | 744 | } |
| 743 | 745 | ||
| 746 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
| 747 | { | ||
| 748 | int err; | ||
| 749 | char opc[BREAK_INSTR_SIZE]; | ||
| 750 | |||
| 751 | bpt->type = BP_BREAKPOINT; | ||
| 752 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | ||
| 753 | BREAK_INSTR_SIZE); | ||
| 754 | if (err) | ||
| 755 | return err; | ||
| 756 | err = probe_kernel_write((char *)bpt->bpt_addr, | ||
| 757 | arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); | ||
| 758 | #ifdef CONFIG_DEBUG_RODATA | ||
| 759 | if (!err) | ||
| 760 | return err; | ||
| 761 | /* | ||
| 762 | * It is safe to call text_poke() because normal kernel execution | ||
| 763 | * is stopped on all cores, so long as the text_mutex is not locked. | ||
| 764 | */ | ||
| 765 | if (mutex_is_locked(&text_mutex)) | ||
| 766 | return -EBUSY; | ||
| 767 | text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, | ||
| 768 | BREAK_INSTR_SIZE); | ||
| 769 | err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); | ||
| 770 | if (err) | ||
| 771 | return err; | ||
| 772 | if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE)) | ||
| 773 | return -EINVAL; | ||
| 774 | bpt->type = BP_POKE_BREAKPOINT; | ||
| 775 | #endif /* CONFIG_DEBUG_RODATA */ | ||
| 776 | return err; | ||
| 777 | } | ||
| 778 | |||
| 779 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
| 780 | { | ||
| 781 | #ifdef CONFIG_DEBUG_RODATA | ||
| 782 | int err; | ||
| 783 | char opc[BREAK_INSTR_SIZE]; | ||
| 784 | |||
| 785 | if (bpt->type != BP_POKE_BREAKPOINT) | ||
| 786 | goto knl_write; | ||
| 787 | /* | ||
| 788 | * It is safe to call text_poke() because normal kernel execution | ||
| 789 | * is stopped on all cores, so long as the text_mutex is not locked. | ||
| 790 | */ | ||
| 791 | if (mutex_is_locked(&text_mutex)) | ||
| 792 | goto knl_write; | ||
| 793 | text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE); | ||
| 794 | err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); | ||
| 795 | if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) | ||
| 796 | goto knl_write; | ||
| 797 | return err; | ||
| 798 | knl_write: | ||
| 799 | #endif /* CONFIG_DEBUG_RODATA */ | ||
| 800 | return probe_kernel_write((char *)bpt->bpt_addr, | ||
| 801 | (char *)bpt->saved_instr, BREAK_INSTR_SIZE); | ||
| 802 | } | ||
| 803 | |||
| 744 | struct kgdb_arch arch_kgdb_ops = { | 804 | struct kgdb_arch arch_kgdb_ops = { |
| 745 | /* Breakpoint instruction: */ | 805 | /* Breakpoint instruction: */ |
| 746 | .gdb_bpt_instr = { 0xcc }, | 806 | .gdb_bpt_instr = { 0xcc }, |
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3f7ad83ed740..3aa9a969b373 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. |
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index fa391835508d..c4d2fc194ede 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h | |||
| @@ -63,7 +63,8 @@ enum kgdb_bptype { | |||
| 63 | BP_HARDWARE_BREAKPOINT, | 63 | BP_HARDWARE_BREAKPOINT, |
| 64 | BP_WRITE_WATCHPOINT, | 64 | BP_WRITE_WATCHPOINT, |
| 65 | BP_READ_WATCHPOINT, | 65 | BP_READ_WATCHPOINT, |
| 66 | BP_ACCESS_WATCHPOINT | 66 | BP_ACCESS_WATCHPOINT, |
| 67 | BP_POKE_BREAKPOINT, | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | enum kgdb_bpstate { | 70 | enum kgdb_bpstate { |
| @@ -207,8 +208,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc); | |||
| 207 | 208 | ||
| 208 | /* Optional functions. */ | 209 | /* Optional functions. */ |
| 209 | extern int kgdb_validate_break_address(unsigned long addr); | 210 | extern int kgdb_validate_break_address(unsigned long addr); |
| 210 | extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); | 211 | extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt); |
| 211 | extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); | 212 | extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt); |
| 212 | 213 | ||
| 213 | /** | 214 | /** |
| 214 | * kgdb_arch_late - Perform any architecture specific initalization. | 215 | * kgdb_arch_late - Perform any architecture specific initalization. |
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 1dc53bae56e1..0557f24c6bca 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
| @@ -160,37 +160,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup); | |||
| 160 | * Weak aliases for breakpoint management, | 160 | * Weak aliases for breakpoint management, |
| 161 | * can be overriden by architectures when needed: | 161 | * can be overriden by architectures when needed: |
| 162 | */ | 162 | */ |
| 163 | int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | 163 | int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) |
| 164 | { | 164 | { |
| 165 | int err; | 165 | int err; |
| 166 | 166 | ||
| 167 | err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); | 167 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, |
| 168 | BREAK_INSTR_SIZE); | ||
| 168 | if (err) | 169 | if (err) |
| 169 | return err; | 170 | return err; |
| 170 | 171 | err = probe_kernel_write((char *)bpt->bpt_addr, | |
| 171 | return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, | 172 | arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); |
| 172 | BREAK_INSTR_SIZE); | 173 | return err; |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) | 176 | int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) |
| 176 | { | 177 | { |
| 177 | return probe_kernel_write((char *)addr, | 178 | return probe_kernel_write((char *)bpt->bpt_addr, |
| 178 | (char *)bundle, BREAK_INSTR_SIZE); | 179 | (char *)bpt->saved_instr, BREAK_INSTR_SIZE); |
| 179 | } | 180 | } |
| 180 | 181 | ||
| 181 | int __weak kgdb_validate_break_address(unsigned long addr) | 182 | int __weak kgdb_validate_break_address(unsigned long addr) |
| 182 | { | 183 | { |
| 183 | char tmp_variable[BREAK_INSTR_SIZE]; | 184 | struct kgdb_bkpt tmp; |
| 184 | int err; | 185 | int err; |
| 185 | /* Validate setting the breakpoint and then removing it. In the | 186 | /* Validate setting the breakpoint and then removing it. If the |
| 186 | * remove fails, the kernel needs to emit a bad message because we | 187 | * remove fails, the kernel needs to emit a bad message because we |
| 187 | * are deep trouble not being able to put things back the way we | 188 | * are deep trouble not being able to put things back the way we |
| 188 | * found them. | 189 | * found them. |
| 189 | */ | 190 | */ |
| 190 | err = kgdb_arch_set_breakpoint(addr, tmp_variable); | 191 | tmp.bpt_addr = addr; |
| 192 | err = kgdb_arch_set_breakpoint(&tmp); | ||
| 191 | if (err) | 193 | if (err) |
| 192 | return err; | 194 | return err; |
| 193 | err = kgdb_arch_remove_breakpoint(addr, tmp_variable); | 195 | err = kgdb_arch_remove_breakpoint(&tmp); |
| 194 | if (err) | 196 | if (err) |
| 195 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " | 197 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " |
| 196 | "memory destroyed at: %lx", addr); | 198 | "memory destroyed at: %lx", addr); |
| @@ -234,7 +236,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) | |||
| 234 | */ | 236 | */ |
| 235 | int dbg_activate_sw_breakpoints(void) | 237 | int dbg_activate_sw_breakpoints(void) |
| 236 | { | 238 | { |
| 237 | unsigned long addr; | ||
| 238 | int error; | 239 | int error; |
| 239 | int ret = 0; | 240 | int ret = 0; |
| 240 | int i; | 241 | int i; |
| @@ -243,16 +244,15 @@ int dbg_activate_sw_breakpoints(void) | |||
| 243 | if (kgdb_break[i].state != BP_SET) | 244 | if (kgdb_break[i].state != BP_SET) |
| 244 | continue; | 245 | continue; |
| 245 | 246 | ||
| 246 | addr = kgdb_break[i].bpt_addr; | 247 | error = kgdb_arch_set_breakpoint(&kgdb_break[i]); |
| 247 | error = kgdb_arch_set_breakpoint(addr, | ||
| 248 | kgdb_break[i].saved_instr); | ||
| 249 | if (error) { | 248 | if (error) { |
| 250 | ret = error; | 249 | ret = error; |
| 251 | printk(KERN_INFO "KGDB: BP install failed: %lx", addr); | 250 | printk(KERN_INFO "KGDB: BP install failed: %lx", |
| 251 | kgdb_break[i].bpt_addr); | ||
| 252 | continue; | 252 | continue; |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | kgdb_flush_swbreak_addr(addr); | 255 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); |
| 256 | kgdb_break[i].state = BP_ACTIVE; | 256 | kgdb_break[i].state = BP_ACTIVE; |
| 257 | } | 257 | } |
| 258 | return ret; | 258 | return ret; |
| @@ -301,7 +301,6 @@ int dbg_set_sw_break(unsigned long addr) | |||
| 301 | 301 | ||
| 302 | int dbg_deactivate_sw_breakpoints(void) | 302 | int dbg_deactivate_sw_breakpoints(void) |
| 303 | { | 303 | { |
| 304 | unsigned long addr; | ||
| 305 | int error; | 304 | int error; |
| 306 | int ret = 0; | 305 | int ret = 0; |
| 307 | int i; | 306 | int i; |
| @@ -309,15 +308,14 @@ int dbg_deactivate_sw_breakpoints(void) | |||
| 309 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 308 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 310 | if (kgdb_break[i].state != BP_ACTIVE) | 309 | if (kgdb_break[i].state != BP_ACTIVE) |
| 311 | continue; | 310 | continue; |
| 312 | addr = kgdb_break[i].bpt_addr; | 311 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
| 313 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 314 | kgdb_break[i].saved_instr); | ||
| 315 | if (error) { | 312 | if (error) { |
| 316 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); | 313 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", |
| 314 | kgdb_break[i].bpt_addr); | ||
| 317 | ret = error; | 315 | ret = error; |
| 318 | } | 316 | } |
| 319 | 317 | ||
| 320 | kgdb_flush_swbreak_addr(addr); | 318 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); |
| 321 | kgdb_break[i].state = BP_SET; | 319 | kgdb_break[i].state = BP_SET; |
| 322 | } | 320 | } |
| 323 | return ret; | 321 | return ret; |
| @@ -351,7 +349,6 @@ int kgdb_isremovedbreak(unsigned long addr) | |||
| 351 | 349 | ||
| 352 | int dbg_remove_all_break(void) | 350 | int dbg_remove_all_break(void) |
| 353 | { | 351 | { |
| 354 | unsigned long addr; | ||
| 355 | int error; | 352 | int error; |
| 356 | int i; | 353 | int i; |
| 357 | 354 | ||
| @@ -359,12 +356,10 @@ int dbg_remove_all_break(void) | |||
| 359 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 356 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 360 | if (kgdb_break[i].state != BP_ACTIVE) | 357 | if (kgdb_break[i].state != BP_ACTIVE) |
| 361 | goto setundefined; | 358 | goto setundefined; |
| 362 | addr = kgdb_break[i].bpt_addr; | 359 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
| 363 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 364 | kgdb_break[i].saved_instr); | ||
| 365 | if (error) | 360 | if (error) |
| 366 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", | 361 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", |
| 367 | addr); | 362 | kgdb_break[i].bpt_addr); |
| 368 | setundefined: | 363 | setundefined: |
| 369 | kgdb_break[i].state = BP_UNDEFINED; | 364 | kgdb_break[i].state = BP_UNDEFINED; |
| 370 | } | 365 | } |
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 9b5f17da1c56..bb9520f0f6ff 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c | |||
| @@ -743,7 +743,7 @@ kdb_printit: | |||
| 743 | kdb_input_flush(); | 743 | kdb_input_flush(); |
| 744 | c = console_drivers; | 744 | c = console_drivers; |
| 745 | 745 | ||
| 746 | if (!dbg_io_ops->is_console) { | 746 | if (dbg_io_ops && !dbg_io_ops->is_console) { |
| 747 | len = strlen(moreprompt); | 747 | len = strlen(moreprompt); |
| 748 | cp = moreprompt; | 748 | cp = moreprompt; |
| 749 | while (len--) { | 749 | while (len--) { |
