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:
  kgdb: kconfig fix xconfig/menuconfig element
  kgdb: fix signedness mixmatches, add statics, add declaration to header
  kgdb: 1000 loops for the single step test in kgdbts
  kgdb: trivial sparse fixes in kgdb test-suite
  kgdb: minor documentation fixes
This commit is contained in:
Linus Torvalds 2008-05-05 10:17:30 -07:00
Родитель 50f7ad2500 e024cbd257
Коммит 5717922a1b
5 изменённых файлов: 64 добавлений и 47 удалений

Просмотреть файл

@ -72,7 +72,7 @@
kgdb is a source level debugger for linux kernel. It is used along kgdb is a source level debugger for linux kernel. It is used along
with gdb to debug a linux kernel. The expectation is that gdb can with gdb to debug a linux kernel. The expectation is that gdb can
be used to "break in" to the kernel to inspect memory, variables be used to "break in" to the kernel to inspect memory, variables
and look through a cal stack information similar to what an and look through call stack information similar to what an
application developer would use gdb for. It is possible to place application developer would use gdb for. It is possible to place
breakpoints in kernel code and perform some limited execution breakpoints in kernel code and perform some limited execution
stepping. stepping.
@ -93,8 +93,10 @@
<chapter id="CompilingAKernel"> <chapter id="CompilingAKernel">
<title>Compiling a kernel</title> <title>Compiling a kernel</title>
<para> <para>
To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging" To enable <symbol>CONFIG_KGDB</symbol> you should first turn on
and then select "KGDB: kernel debugging with remote gdb". "Prompt for development and/or incomplete code/drivers"
(CONFIG_EXPERIMENTAL) in "General setup", then under the
"Kernel debugging" select "KGDB: kernel debugging with remote gdb".
</para> </para>
<para> <para>
Next you should choose one of more I/O drivers to interconnect debugging Next you should choose one of more I/O drivers to interconnect debugging

Просмотреть файл

@ -47,6 +47,7 @@
* to test the HW NMI watchdog * to test the HW NMI watchdog
* F## = Break at do_fork for ## iterations * F## = Break at do_fork for ## iterations
* S## = Break at sys_open for ## iterations * S## = Break at sys_open for ## iterations
* I## = Run the single step test ## iterations
* *
* NOTE: that the do_fork and sys_open tests are mutually exclusive. * NOTE: that the do_fork and sys_open tests are mutually exclusive.
* *
@ -375,7 +376,7 @@ static void emul_sstep_get(char *arg)
break; break;
case 1: case 1:
/* set breakpoint */ /* set breakpoint */
break_helper("Z0", 0, sstep_addr); break_helper("Z0", NULL, sstep_addr);
break; break;
case 2: case 2:
/* Continue */ /* Continue */
@ -383,7 +384,7 @@ static void emul_sstep_get(char *arg)
break; break;
case 3: case 3:
/* Clear breakpoint */ /* Clear breakpoint */
break_helper("z0", 0, sstep_addr); break_helper("z0", NULL, sstep_addr);
break; break;
default: default:
eprintk("kgdbts: ERROR failed sstep get emulation\n"); eprintk("kgdbts: ERROR failed sstep get emulation\n");
@ -465,11 +466,11 @@ static struct test_struct sw_breakpoint_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "kgdbts_break_test", 0, check_and_rewind_pc }, { "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, { "write", "OK", write_regs },
{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "D", "OK" }, /* Detach */ { "D", "OK" }, /* Detach */
{ "D", "OK", 0, got_break }, /* If the test worked we made it here */ { "D", "OK", NULL, got_break }, /* On success we made it here */
{ "", "" }, { "", "" },
}; };
@ -499,14 +500,14 @@ static struct test_struct singlestep_break_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "kgdbts_break_test", 0, check_and_rewind_pc }, { "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, /* Write registers */ { "write", "OK", write_regs }, /* Write registers */
{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "kgdbts_break_test", 0, check_single_step }, { "g", "kgdbts_break_test", NULL, check_single_step },
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "kgdbts_break_test", 0, check_and_rewind_pc }, { "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, /* Write registers */ { "write", "OK", write_regs }, /* Write registers */
{ "D", "OK" }, /* Remove all breakpoints and continues */ { "D", "OK" }, /* Remove all breakpoints and continues */
{ "", "" }, { "", "" },
@ -520,14 +521,14 @@ static struct test_struct do_fork_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */ { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "do_fork", 0, check_and_rewind_pc }, /* check location */ { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
{ "write", "OK", write_regs }, /* Write registers */ { "write", "OK", write_regs }, /* Write registers */
{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "do_fork", 0, check_single_step }, { "g", "do_fork", NULL, check_single_step },
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */ { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */ { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
{ "", "" }, { "", "" },
}; };
@ -538,14 +539,14 @@ static struct test_struct sys_open_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */ { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "sys_open", 0, check_and_rewind_pc }, /* check location */ { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
{ "write", "OK", write_regs }, /* Write registers */ { "write", "OK", write_regs }, /* Write registers */
{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "sys_open", 0, check_single_step }, { "g", "sys_open", NULL, check_single_step },
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */ { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */ { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
{ "", "" }, { "", "" },
}; };
@ -556,11 +557,11 @@ static struct test_struct hw_breakpoint_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "kgdbts_break_test", "OK", hw_break, }, /* set hw breakpoint */ { "kgdbts_break_test", "OK", hw_break, }, /* set hw breakpoint */
{ "c", "T0*", }, /* Continue */ { "c", "T0*", }, /* Continue */
{ "g", "kgdbts_break_test", 0, check_and_rewind_pc }, { "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, { "write", "OK", write_regs },
{ "kgdbts_break_test", "OK", hw_rem_break }, /*remove breakpoint */ { "kgdbts_break_test", "OK", hw_rem_break }, /*remove breakpoint */
{ "D", "OK" }, /* Detach */ { "D", "OK" }, /* Detach */
{ "D", "OK", 0, got_break }, /* If the test worked we made it here */ { "D", "OK", NULL, got_break }, /* On success we made it here */
{ "", "" }, { "", "" },
}; };
@ -570,12 +571,12 @@ static struct test_struct hw_breakpoint_test[] = {
static struct test_struct hw_write_break_test[] = { static struct test_struct hw_write_break_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "hw_break_val", "OK", hw_write_break, }, /* set hw breakpoint */ { "hw_break_val", "OK", hw_write_break, }, /* set hw breakpoint */
{ "c", "T0*", 0, got_break }, /* Continue */ { "c", "T0*", NULL, got_break }, /* Continue */
{ "g", "silent", 0, check_and_rewind_pc }, { "g", "silent", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, { "write", "OK", write_regs },
{ "hw_break_val", "OK", hw_rem_write_break }, /*remove breakpoint */ { "hw_break_val", "OK", hw_rem_write_break }, /*remove breakpoint */
{ "D", "OK" }, /* Detach */ { "D", "OK" }, /* Detach */
{ "D", "OK", 0, got_break }, /* If the test worked we made it here */ { "D", "OK", NULL, got_break }, /* On success we made it here */
{ "", "" }, { "", "" },
}; };
@ -585,12 +586,12 @@ static struct test_struct hw_write_break_test[] = {
static struct test_struct hw_access_break_test[] = { static struct test_struct hw_access_break_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "hw_break_val", "OK", hw_access_break, }, /* set hw breakpoint */ { "hw_break_val", "OK", hw_access_break, }, /* set hw breakpoint */
{ "c", "T0*", 0, got_break }, /* Continue */ { "c", "T0*", NULL, got_break }, /* Continue */
{ "g", "silent", 0, check_and_rewind_pc }, { "g", "silent", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, { "write", "OK", write_regs },
{ "hw_break_val", "OK", hw_rem_access_break }, /*remove breakpoint */ { "hw_break_val", "OK", hw_rem_access_break }, /*remove breakpoint */
{ "D", "OK" }, /* Detach */ { "D", "OK" }, /* Detach */
{ "D", "OK", 0, got_break }, /* If the test worked we made it here */ { "D", "OK", NULL, got_break }, /* On success we made it here */
{ "", "" }, { "", "" },
}; };
@ -599,9 +600,9 @@ static struct test_struct hw_access_break_test[] = {
*/ */
static struct test_struct nmi_sleep_test[] = { static struct test_struct nmi_sleep_test[] = {
{ "?", "S0*" }, /* Clear break points */ { "?", "S0*" }, /* Clear break points */
{ "c", "T0*", 0, got_break }, /* Continue */ { "c", "T0*", NULL, got_break }, /* Continue */
{ "D", "OK" }, /* Detach */ { "D", "OK" }, /* Detach */
{ "D", "OK", 0, got_break }, /* If the test worked we made it here */ { "D", "OK", NULL, got_break }, /* On success we made it here */
{ "", "" }, { "", "" },
}; };
@ -874,18 +875,23 @@ static void kgdbts_run_tests(void)
{ {
char *ptr; char *ptr;
int fork_test = 0; int fork_test = 0;
int sys_open_test = 0; int do_sys_open_test = 0;
int sstep_test = 1000;
int nmi_sleep = 0; int nmi_sleep = 0;
int i;
ptr = strstr(config, "F"); ptr = strstr(config, "F");
if (ptr) if (ptr)
fork_test = simple_strtol(ptr+1, NULL, 10); fork_test = simple_strtol(ptr + 1, NULL, 10);
ptr = strstr(config, "S"); ptr = strstr(config, "S");
if (ptr) if (ptr)
sys_open_test = simple_strtol(ptr+1, NULL, 10); do_sys_open_test = simple_strtol(ptr + 1, NULL, 10);
ptr = strstr(config, "N"); ptr = strstr(config, "N");
if (ptr) if (ptr)
nmi_sleep = simple_strtol(ptr+1, NULL, 10); nmi_sleep = simple_strtol(ptr+1, NULL, 10);
ptr = strstr(config, "I");
if (ptr)
sstep_test = simple_strtol(ptr+1, NULL, 10);
/* required internal KGDB tests */ /* required internal KGDB tests */
v1printk("kgdbts:RUN plant and detach test\n"); v1printk("kgdbts:RUN plant and detach test\n");
@ -894,8 +900,13 @@ static void kgdbts_run_tests(void)
run_breakpoint_test(0); run_breakpoint_test(0);
v1printk("kgdbts:RUN bad memory access test\n"); v1printk("kgdbts:RUN bad memory access test\n");
run_bad_read_test(); run_bad_read_test();
v1printk("kgdbts:RUN singlestep breakpoint test\n"); v1printk("kgdbts:RUN singlestep test %i iterations\n", sstep_test);
run_singlestep_break_test(); for (i = 0; i < sstep_test; i++) {
run_singlestep_break_test();
if (i % 100 == 0)
v1printk("kgdbts:RUN singlestep [%i/%i]\n",
i, sstep_test);
}
/* ===Optional tests=== */ /* ===Optional tests=== */
@ -922,7 +933,7 @@ static void kgdbts_run_tests(void)
repeat_test = fork_test; repeat_test = fork_test;
printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n", printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n",
repeat_test); repeat_test);
kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg"); kthread_run(kgdbts_unreg_thread, NULL, "kgdbts_unreg");
run_do_fork_test(); run_do_fork_test();
return; return;
} }
@ -931,11 +942,11 @@ static void kgdbts_run_tests(void)
* executed because a kernel thread will be spawned at the very * executed because a kernel thread will be spawned at the very
* end to unregister the debug hooks. * end to unregister the debug hooks.
*/ */
if (sys_open_test) { if (do_sys_open_test) {
repeat_test = sys_open_test; repeat_test = do_sys_open_test;
printk(KERN_INFO "kgdbts:RUN sys_open for %i breakpoints\n", printk(KERN_INFO "kgdbts:RUN sys_open for %i breakpoints\n",
repeat_test); repeat_test);
kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg"); kthread_run(kgdbts_unreg_thread, NULL, "kgdbts_unreg");
run_sys_open_test(); run_sys_open_test();
return; return;
} }

Просмотреть файл

@ -261,10 +261,12 @@ struct kgdb_io {
extern struct kgdb_arch arch_kgdb_ops; extern struct kgdb_arch arch_kgdb_ops;
extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs);
extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
extern int kgdb_hex2long(char **ptr, long *long_val); extern int kgdb_hex2long(char **ptr, unsigned long *long_val);
extern int kgdb_mem2hex(char *mem, char *buf, int count); extern int kgdb_mem2hex(char *mem, char *buf, int count);
extern int kgdb_hex2mem(char *buf, char *mem, int count); extern int kgdb_hex2mem(char *buf, char *mem, int count);

Просмотреть файл

@ -61,7 +61,7 @@ struct kgdb_state {
int err_code; int err_code;
int cpu; int cpu;
int pass_exception; int pass_exception;
long threadid; unsigned long threadid;
long kgdb_usethreadid; long kgdb_usethreadid;
struct pt_regs *linux_regs; struct pt_regs *linux_regs;
}; };
@ -146,7 +146,7 @@ atomic_t kgdb_cpu_doing_single_step = ATOMIC_INIT(-1);
* the other CPUs might interfere with your debugging context, so * the other CPUs might interfere with your debugging context, so
* use this with care: * use this with care:
*/ */
int kgdb_do_roundup = 1; static int kgdb_do_roundup = 1;
static int __init opt_nokgdbroundup(char *str) static int __init opt_nokgdbroundup(char *str)
{ {
@ -438,7 +438,7 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
* While we find nice hex chars, build a long_val. * While we find nice hex chars, build a long_val.
* Return number of chars processed. * Return number of chars processed.
*/ */
int kgdb_hex2long(char **ptr, long *long_val) int kgdb_hex2long(char **ptr, unsigned long *long_val)
{ {
int hex_val; int hex_val;
int num = 0; int num = 0;
@ -709,7 +709,7 @@ int kgdb_isremovedbreak(unsigned long addr)
return 0; return 0;
} }
int remove_all_break(void) static int remove_all_break(void)
{ {
unsigned long addr; unsigned long addr;
int error; int error;

Просмотреть файл

@ -1,4 +1,10 @@
config HAVE_ARCH_KGDB_SHADOW_INFO
bool
config HAVE_ARCH_KGDB
bool
menuconfig KGDB menuconfig KGDB
bool "KGDB: kernel debugging with remote gdb" bool "KGDB: kernel debugging with remote gdb"
select FRAME_POINTER select FRAME_POINTER
@ -10,15 +16,10 @@ menuconfig KGDB
at http://kgdb.sourceforge.net as well as in DocBook form at http://kgdb.sourceforge.net as well as in DocBook form
in Documentation/DocBook/. If unsure, say N. in Documentation/DocBook/. If unsure, say N.
config HAVE_ARCH_KGDB_SHADOW_INFO if KGDB
bool
config HAVE_ARCH_KGDB
bool
config KGDB_SERIAL_CONSOLE config KGDB_SERIAL_CONSOLE
tristate "KGDB: use kgdb over the serial console" tristate "KGDB: use kgdb over the serial console"
depends on KGDB
select CONSOLE_POLL select CONSOLE_POLL
select MAGIC_SYSRQ select MAGIC_SYSRQ
default y default y
@ -28,7 +29,6 @@ config KGDB_SERIAL_CONSOLE
config KGDB_TESTS config KGDB_TESTS
bool "KGDB: internal test suite" bool "KGDB: internal test suite"
depends on KGDB
default n default n
help help
This is a kgdb I/O module specifically designed to test This is a kgdb I/O module specifically designed to test
@ -56,3 +56,5 @@ config KGDB_TESTS_BOOT_STRING
boot. See the drivers/misc/kgdbts.c for detailed boot. See the drivers/misc/kgdbts.c for detailed
information about other strings you could use beyond the information about other strings you could use beyond the
default of V1F100. default of V1F100.
endif # KGDB