Forráskód Böngészése

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
Linus Torvalds 17 éve
szülő
commit
5717922a1b
5 módosított fájl, 64 hozzáadás és 47 törlés
  1. 5 3
      Documentation/DocBook/kgdb.tmpl
  2. 43 32
      drivers/misc/kgdbts.c
  3. 3 1
      include/linux/kgdb.h
  4. 4 4
      kernel/kgdb.c
  5. 9 7
      lib/Kconfig.kgdb

+ 5 - 3
Documentation/DocBook/kgdb.tmpl

@@ -72,7 +72,7 @@
     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
     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
     breakpoints in kernel code and perform some limited execution
     stepping.
@@ -93,8 +93,10 @@
   <chapter id="CompilingAKernel">
     <title>Compiling a kernel</title>
     <para>
-    To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
-    and then select "KGDB: kernel debugging with remote gdb".
+    To enable <symbol>CONFIG_KGDB</symbol> you should first turn on
+    "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>
     Next you should choose one of more I/O drivers to interconnect debugging

+ 43 - 32
drivers/misc/kgdbts.c

@@ -47,6 +47,7 @@
  *       to test the HW NMI watchdog
  * F## = Break at do_fork 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.
  *
@@ -375,7 +376,7 @@ static void emul_sstep_get(char *arg)
 		break;
 	case 1:
 		/* set breakpoint */
-		break_helper("Z0", 0, sstep_addr);
+		break_helper("Z0", NULL, sstep_addr);
 		break;
 	case 2:
 		/* Continue */
@@ -383,7 +384,7 @@ static void emul_sstep_get(char *arg)
 		break;
 	case 3:
 		/* Clear breakpoint */
-		break_helper("z0", 0, sstep_addr);
+		break_helper("z0", NULL, sstep_addr);
 		break;
 	default:
 		eprintk("kgdbts: ERROR failed sstep get emulation\n");
@@ -465,11 +466,11 @@ static struct test_struct sw_breakpoint_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
 	{ "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 },
 	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "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 */
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
 	{ "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 */
 	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "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 */
 	{ "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 */
 	{ "D", "OK" }, /* Remove all breakpoints and continues */
 	{ "", "" },
@@ -520,14 +521,14 @@ static struct test_struct do_fork_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
 	{ "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 */
 	{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "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 */
 	{ "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 */
 	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
 	{ "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 */
 	{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "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 */
 	{ "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 */
 	{ "kgdbts_break_test", "OK", hw_break, }, /* set hw breakpoint */
 	{ "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 },
 	{ "kgdbts_break_test", "OK", hw_rem_break }, /*remove breakpoint */
 	{ "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[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "hw_break_val", "OK", hw_write_break, }, /* set hw breakpoint */
-	{ "c", "T0*", 0, got_break }, /* Continue */
-	{ "g", "silent", 0, check_and_rewind_pc },
+	{ "c", "T0*", NULL, got_break }, /* Continue */
+	{ "g", "silent", NULL, check_and_rewind_pc },
 	{ "write", "OK", write_regs },
 	{ "hw_break_val", "OK", hw_rem_write_break }, /*remove breakpoint */
 	{ "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[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "hw_break_val", "OK", hw_access_break, }, /* set hw breakpoint */
-	{ "c", "T0*", 0, got_break }, /* Continue */
-	{ "g", "silent", 0, check_and_rewind_pc },
+	{ "c", "T0*", NULL, got_break }, /* Continue */
+	{ "g", "silent", NULL, check_and_rewind_pc },
 	{ "write", "OK", write_regs },
 	{ "hw_break_val", "OK", hw_rem_access_break }, /*remove breakpoint */
 	{ "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[] = {
 	{ "?", "S0*" }, /* Clear break points */
-	{ "c", "T0*", 0, got_break }, /* Continue */
+	{ "c", "T0*", NULL, got_break }, /* Continue */
 	{ "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;
 	int fork_test = 0;
-	int sys_open_test = 0;
+	int do_sys_open_test = 0;
+	int sstep_test = 1000;
 	int nmi_sleep = 0;
+	int i;
 
 	ptr = strstr(config, "F");
 	if (ptr)
-		fork_test = simple_strtol(ptr+1, NULL, 10);
+		fork_test = simple_strtol(ptr + 1, NULL, 10);
 	ptr = strstr(config, "S");
 	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");
 	if (ptr)
 		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 */
 	v1printk("kgdbts:RUN plant and detach test\n");
@@ -894,8 +900,13 @@ static void kgdbts_run_tests(void)
 	run_breakpoint_test(0);
 	v1printk("kgdbts:RUN bad memory access test\n");
 	run_bad_read_test();
-	v1printk("kgdbts:RUN singlestep breakpoint test\n");
-	run_singlestep_break_test();
+	v1printk("kgdbts:RUN singlestep test %i iterations\n", sstep_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=== */
 
@@ -922,7 +933,7 @@ static void kgdbts_run_tests(void)
 		repeat_test = fork_test;
 		printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n",
 			repeat_test);
-		kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
+		kthread_run(kgdbts_unreg_thread, NULL, "kgdbts_unreg");
 		run_do_fork_test();
 		return;
 	}
@@ -931,11 +942,11 @@ static void kgdbts_run_tests(void)
 	 * executed because a kernel thread will be spawned at the very
 	 * end to unregister the debug hooks.
 	 */
-	if (sys_open_test) {
-		repeat_test = sys_open_test;
+	if (do_sys_open_test) {
+		repeat_test = do_sys_open_test;
 		printk(KERN_INFO "kgdbts:RUN sys_open for %i breakpoints\n",
 			repeat_test);
-		kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
+		kthread_run(kgdbts_unreg_thread, NULL, "kgdbts_unreg");
 		run_sys_open_test();
 		return;
 	}

+ 3 - 1
include/linux/kgdb.h

@@ -261,10 +261,12 @@ struct kgdb_io {
 
 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 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_hex2mem(char *buf, char *mem, int count);
 

+ 4 - 4
kernel/kgdb.c

@@ -61,7 +61,7 @@ struct kgdb_state {
 	int			err_code;
 	int			cpu;
 	int			pass_exception;
-	long			threadid;
+	unsigned long		threadid;
 	long			kgdb_usethreadid;
 	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
  * use this with care:
  */
-int				kgdb_do_roundup = 1;
+static int kgdb_do_roundup = 1;
 
 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.
  * 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 num = 0;
@@ -709,7 +709,7 @@ int kgdb_isremovedbreak(unsigned long addr)
 	return 0;
 }
 
-int remove_all_break(void)
+static int remove_all_break(void)
 {
 	unsigned long addr;
 	int error;

+ 9 - 7
lib/Kconfig.kgdb

@@ -1,4 +1,10 @@
 
+config HAVE_ARCH_KGDB_SHADOW_INFO
+	bool
+
+config HAVE_ARCH_KGDB
+	bool
+
 menuconfig KGDB
 	bool "KGDB: kernel debugging with remote gdb"
 	select FRAME_POINTER
@@ -10,15 +16,10 @@ menuconfig KGDB
 	  at http://kgdb.sourceforge.net as well as in DocBook form
 	  in Documentation/DocBook/.  If unsure, say N.
 
-config HAVE_ARCH_KGDB_SHADOW_INFO
-	bool
-
-config HAVE_ARCH_KGDB
-	bool
+if KGDB
 
 config KGDB_SERIAL_CONSOLE
 	tristate "KGDB: use kgdb over the serial console"
-	depends on KGDB
 	select CONSOLE_POLL
 	select MAGIC_SYSRQ
 	default y
@@ -28,7 +29,6 @@ config KGDB_SERIAL_CONSOLE
 
 config KGDB_TESTS
 	bool "KGDB: internal test suite"
-	depends on KGDB
 	default n
 	help
 	  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
 	  information about other strings you could use beyond the
 	  default of V1F100.
+
+endif # KGDB