Skip to contentSkip to conversation

kernel debugger support for ipipe (2.6.26)

PATCH New Jan Kiszka 1 participant 1 message Jul 8, 2008

Subsystems (2)
lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

PATCH 1/1 kernel debugger support for ipipe (2.6.26)

Hi,

finally I found a few minutes to port forward our old kgdb patch series, once developed for a customer on 2.6.24, to latest 2.6.26-rcX.

As you may have heard, 2.6.26 will include a cleaned up and stripped down kgdb, so far supporting x86 only, but on the way to finally establish a patch-free kernel debugger for all Linux archs. For ipipe/Xenomai usage, a few additional patches are still required, both to kgdb itself as well as for the ipipe patch. Here we go:

- Install latest 2.6.26-rc (I've tested with -rc8)
- Pick up the following three patches from kgdb-dev (in that order):
http://git.kernel.org/?p=linux/kernel/git/jwessel/linux-2.6-kgdb.git;a=commitdiff;h=3ff4f23f5636d18895ac816758b317f44b5cea3d
http://git.kernel.org/?p=linux/kernel/git/jwessel/linux-2.6-kgdb.git;a=commitdiff;h=d147de2975ed851dab4ae9fbb12d5b63a12fd20a
http://git.kernel.org/?p=linux/kernel/git/jwessel/linux-2.6-kgdb.git;a=commitdiff;h=f9193cd86f1b51f4f2ad875718b822e3f0441e9a
- Apply latest ipipe for 2.6.26 (right now adeos-ipipe-2.6.26-rc7-x86-2.0-09)
- Apply ipipe-modular-kgdb-support.patch (that one could be merged into ipipe git already) and kgdb-2.6.26-ipipe-v3.patch (that depends on full-blown kgdb, thus will not apply to vanilla 2.6.26)

Find the latter two patches attached.

Time didn't permit to test this kgdb in all details under Xenomai, but basic tests look OK, including the new self test of kgdb. Feedback is welcome!

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
---
 arch/x86/kernel/ipipe.c |   88 +++++++++++++++++++++++++++++++-----------------
 include/linux/ipipe.h   |   13 +++++++
 kernel/ipipe/core.c     |   35 +++++++++++++++++++
 3 files changed, 106 insertions(+), 30 deletions(-)
arch/x86/kernel/ipipe.c +58 -30
Index: b/arch/x86/kernel/ipipe.c
===================================================================
@@ -697,8 +697,10 @@ static __ipipe_exptr __ipipe_std_extable
 #endif
 };
 
-#ifdef CONFIG_KGDB
+#if defined(CONFIG_KGDB) || defined(CONFIG_KGDB_MODULE)
 #include <linux/kgdb.h>
+#include <linux/kdebug.h>
+#include <asm/uaccess.h>
 
 static int __ipipe_xlate_signo[] = {
 
@@ -746,24 +748,34 @@ int __ipipe_handle_exception(struct pt_r
 		barrier();
 	}
 
-#ifdef CONFIG_KGDB
-	/* catch exception KGDB is interested in over non-root domains */
-	if (!ipipe_root_domain_p &&
-	    __ipipe_xlate_signo[vector] >= 0 &&
-	    !kgdb_handle_exception(vector, __ipipe_xlate_signo[vector], error_code, regs)) {
-		if (!flags)
-			__clear_bit(IPIPE_STALL_FLAG,
-				    &ipipe_root_cpudom_var(status));
-		return 1;
+#if defined(CONFIG_KGDB) || defined(CONFIG_KGDB_MODULE)
+	if (unlikely(__ipipe_kgdb_notify)) {
+		const struct exception_table_entry *fixup;
+		struct die_args args;
+
+		/* Fixup kgdb-own faults immediately. */
+		if (*__ipipe_kgdb_may_fault) {
+			fixup = search_exception_tables(regs->ip);
+			BUG_ON(!fixup);
+			regs->ip = fixup->fixup;
+			goto exit_stop;
+		}
+
+		/* Catch any exception over non-root domains that
+		 * kgdb might be interested in. */
+		if (!ipipe_root_domain_p && __ipipe_xlate_signo[vector] >= 0) {
+			args.regs = regs;
+			args.err = error_code;
+			args.trapnr = vector;
+			args.signr = __ipipe_xlate_signo[vector];
+			if (__ipipe_kgdb_notify(NULL, DIE_TRAP, &args) == NOTIFY_STOP)
+				goto exit_stop;
+		}
 	}
 #endif /* CONFIG_KGDB */
 
-	if (unlikely(ipipe_trap_notify(vector, regs))) {
-		if (!flags)
-			__clear_bit(IPIPE_STALL_FLAG,
-				    &ipipe_root_cpudom_var(status));
-		return 1;
-	}
+	if (unlikely(ipipe_trap_notify(vector, regs)))
+		goto exit_stop;
 
 	/* Detect unhandled faults over non-root domains. */
 
@@ -800,23 +812,31 @@ int __ipipe_handle_exception(struct pt_r
 	__fixup_if(regs);
 
 	return 0;
+
+exit_stop:
+	if (!flags)
+		__clear_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
+	return 1;
 }
 
 int __ipipe_divert_exception(struct pt_regs *regs, int vector)
 {
-#ifdef CONFIG_KGDB
-	/* catch int1 and int3 over non-root domains */
-#ifdef CONFIG_X86_32
-	if (!ipipe_root_domain_p && vector != ex_do_device_not_available) {
-#else
-	if (!ipipe_root_domain_p) {
-#endif
-		unsigned int condition = 0;
-
-		if (vector == 1)
-			get_debugreg(condition, 6);
-		if (!kgdb_handle_exception(vector, SIGTRAP, condition, regs))
-			return 1;
+#if defined(CONFIG_KGDB) || defined(CONFIG_KGDB_MODULE)
+	/* Catch debug and breakpoint exception over non-root domains. */
+	if (__ipipe_kgdb_notify && !ipipe_root_domain_p) {
+		struct die_args args = { .regs = regs, .signr = SIGTRAP };
+
+		if (vector == 1) {
+			get_debugreg(args.err, 6);
+			args.trapnr = 0;
+			if (__ipipe_kgdb_notify(NULL, DIE_DEBUG, &args) == NOTIFY_STOP)
+				return 1;
+		} else if (vector == 3) {
+			args.err = 0;
+			args.trapnr = 3;
+			if (__ipipe_kgdb_notify(NULL, DIE_INT3, &args) == NOTIFY_STOP)
+				return 1;
+		}
 	}
 #endif /* CONFIG_KGDB */
 
@@ -865,8 +885,16 @@ int __ipipe_handle_irq(struct pt_regs *r
 		irq = vector;
 		m_ack = 1;
 	}
-
 #endif /* !CONFIG_X86_32 */
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_KGDB_MODULE)
+	if (unlikely(irq == __ipipe_kgdb_irq)) {
+		ipipe_root_domain->irqs[irq].acknowledge(irq);
+		__ipipe_kgdb_irq_handler(irq, NULL);
+		irq_desc[irq].ipipe_end(irq, &irq_desc[irq]);
+		goto finalize_nosync;
+	}
+#endif /* CONFIG_KGDB */
 	head = __ipipe_pipeline.next;
 	next_domain = list_entry(head, struct ipipe_domain, p_link);
 	if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
include/linux/ipipe.h +13 -0
Index: b/include/linux/ipipe.h
===================================================================
@@ -26,6 +26,7 @@
 #include <linux/cache.h>
 #include <linux/percpu.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
 #include <linux/linkage.h>
 #include <linux/ipipe_base.h>
 #include <linux/ipipe_compat.h>
@@ -512,6 +513,18 @@ static inline void local_irq_restore_nos
 
 #define ipipe_root_domain_p		(ipipe_current_domain == ipipe_root_domain)
 
+extern int *__ipipe_kgdb_may_fault;
+extern int (*__ipipe_kgdb_notify)(struct notifier_block *, unsigned long, void *);
+
+extern int __ipipe_kgdb_irq;
+extern int (*__ipipe_kgdb_irq_handler)(int, void *);
+
+#define IPIPE_KGDB_IRQ_NONE	-1
+
+void ipipe_kgdb_set_fault_handler(int *kgdb_may_fault,
+	int (*handler)(struct notifier_block *, unsigned long, void *));
+void ipipe_kgdb_set_irq_handler(int irq, int (*handler)(int, void *));
+
 #else	/* !CONFIG_IPIPE */
 
 #define ipipe_init()			do { } while(0)
kernel/ipipe/core.c +35 -0
Index: b/kernel/ipipe/core.c
===================================================================
@@ -1586,6 +1586,41 @@ void ipipe_check_context(struct ipipe_do
 EXPORT_SYMBOL(ipipe_check_context);
 #endif /* CONFIG_IPIPE_DEBUG_CONTEXT */
 
+#if defined(CONFIG_KGDB) || defined(CONFIG_KGDB_MODULE)
+int *__ipipe_kgdb_may_fault = NULL;
+int (*__ipipe_kgdb_notify)(struct notifier_block *, unsigned long, void *);
+
+void ipipe_kgdb_set_fault_handler(int *kgdb_may_fault,
+	int (*handler)(struct notifier_block *, unsigned long, void *))
+{
+	unsigned long flags;
+
+	flags = ipipe_critical_enter(NULL);
+
+	__ipipe_kgdb_may_fault = kgdb_may_fault;
+	__ipipe_kgdb_notify = handler;
+
+	ipipe_critical_exit(flags);
+}
+EXPORT_SYMBOL_GPL(ipipe_kgdb_set_fault_handler);
+
+int __ipipe_kgdb_irq = IPIPE_KGDB_IRQ_NONE;
+irq_handler_t __ipipe_kgdb_irq_handler;
+
+void ipipe_kgdb_set_irq_handler(int irq, irq_handler_t handler)
+{
+	unsigned long flags;
+
+	flags = ipipe_critical_enter(NULL);
+
+	__ipipe_kgdb_irq = irq;
+	__ipipe_kgdb_irq_handler = handler;
+
+	ipipe_critical_exit(flags);
+}
+EXPORT_SYMBOL_GPL(ipipe_kgdb_set_irq_handler);
+#endif /* CONFIG_KGDB */
+
 EXPORT_SYMBOL(ipipe_virtualize_irq);
 EXPORT_SYMBOL(ipipe_control_irq);
 EXPORT_SYMBOL(ipipe_suspend_domain);
---
 arch/x86/kernel/kgdb.c     |   11 ++++-
 drivers/serial/8250_kgdb.c |   15 ++++++++
 kernel/kgdb.c              |   84 ++++++++++++++++++++++++++++++++-------------
 lib/Kconfig.kgdb           |    1 
 4 files changed, 86 insertions(+), 25 deletions(-)
drivers/serial/8250_kgdb.c +15 -0
Index: b/drivers/serial/8250_kgdb.c
===================================================================
@@ -363,6 +363,9 @@ static int kgdb8250_late_init(void)
 			goto rollback;
 	}
 
+#ifdef CONFIG_IPIPE
+	ipipe_kgdb_set_irq_handler(kgdb8250_port.irq, kgdb8250_interrupt);
+#endif
 	if (request_irq(kgdb8250_port.irq, kgdb8250_interrupt, IRQF_SHARED,
 			"kgdb", &kgdb8250_port) == 0) {
 		/* Turn on RX interrupt only. */
@@ -402,6 +405,14 @@ static void kgdb8250_cleanup(void)
 	kgdb8250_iowrite(0, UART_IER);
 	(void) kgdb8250_ioread(UART_RX);
 
+#ifdef CONFIG_IPIPE
+	/* We cannot run module_get/put over I-pipe domains, so enforce the
+	 * deregistration protocol here. */
+	while (kgdb_connected)
+		kgdb_breakpoint();
+
+	ipipe_kgdb_set_irq_handler(IPIPE_KGDB_IRQ_NONE, NULL);
+#endif /* CONFIG_IPIPE */
 	if (kgdb8250_irq >= 0)
 		free_irq(kgdb8250_irq, &kgdb8250_port);
 
@@ -457,6 +468,7 @@ static int kgdb8250_set_config(const cha
 	return kgdb8250_late_init();
 }
 
+#ifndef CONFIG_IPIPE
 static void kgdb8250_pre_exception_handler(void)
 {
 	if (!kgdb_connected)
@@ -468,14 +480,17 @@ static void kgdb8250_post_exception_hand
 	if (!kgdb_connected)
 		module_put(THIS_MODULE);
 }
+#endif /* !CONFIG_IPIPE */
 
 static struct kgdb_io kgdb8250_io_ops = {
 	.name = "kgdb8250",
 	.read_char = kgdb8250_get_debug_char,
 	.write_char = kgdb8250_put_debug_char,
 	.init = kgdb8250_early_init,
+#ifndef CONFIG_IPIPE
 	.pre_exception = kgdb8250_pre_exception_handler,
 	.post_exception = kgdb8250_post_exception_handler,
+#endif /* !CONFIG_IPIPE */
 };
 
 module_init(kgdb8250_late_init);
kernel/kgdb.c +61 -23

218 lines not on this page · raw message

arch/x86/kernel/kgdb.c +9 -2
Index: b/arch/x86/kernel/kgdb.c
===================================================================
@@ -489,9 +489,9 @@ kgdb_notify(struct notifier_block *self,
 	unsigned long flags;
 	int ret;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	ret = __kgdb_notify(ptr, cmd);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return ret;
 }
@@ -513,6 +513,10 @@ static struct notifier_block kgdb_notifi
  */
 int kgdb_arch_init(void)
 {
+#ifdef CONFIG_IPIPE
+	extern int kgdb_may_fault;
+	ipipe_kgdb_set_fault_handler(&kgdb_may_fault, kgdb_notify);
+#endif
 	return register_die_notifier(&kgdb_notifier);
 }
 
@@ -525,6 +529,9 @@ int kgdb_arch_init(void)
 void kgdb_arch_exit(void)
 {
 	unregister_die_notifier(&kgdb_notifier);
+#ifdef CONFIG_IPIPE
+	ipipe_kgdb_set_fault_handler(NULL, NULL);
+#endif
 }
 
 /**
lib/Kconfig.kgdb +1 -0
Index: b/lib/Kconfig.kgdb
===================================================================
@@ -20,6 +20,7 @@ if KGDB
 
 config KGDB_SERIAL_CONSOLE
 	tristate "KGDB: use kgdb over the serial console"
+	depends on !IPIPE
 	select CONSOLE_POLL
 	select MAGIC_SYSRQ
 	default y