Hello All,
The remote serial protocol for GDB supports echoing program
output. This patch adds a new SERHND flag and hooks into serial_puts()
to allow this to happen. All XEN prtintk()s and dom0 console output
will get send to a remote GDB if it's attached and the serial console
shares the same port.
Tested on xenPPC.
Feedback greatly appreciated.
---
common/gdbstub.c | 28 +++++++++++++++++++++++++++-
drivers/char/console.c | 11 +++++++++++
drivers/char/serial.c | 5 +++++
include/asm-powerpc/debugger.h | 3 +++
include/xen/gdbstub.h | 2 ++
include/xen/serial.h | 5 +++++
6 files changed, 53 insertions(+), 1 deletion(-)
---
diff -r 9c4858991254 xen/common/gdbstub.c
--- a/xen/common/gdbstub.c Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/common/gdbstub.c Fri Sep 01 13:40:19 2006 +1000
@@ -470,6 +470,30 @@ __gdb_ctx = {
};
static struct gdb_context *gdb_ctx = &__gdb_ctx;
+/* FIXME: does this need to be protected by a lock?
+ * Can it clobber another packet? */
+void
+debugger_puts(const char *str)
+{
+ char *p;
+
+ gdb_start_packet(gdb_ctx);
+ gdb_write_to_packet_char('O', gdb_ctx);
+
+ for(p=(char *)str; *p != '\x0'; p++) {
+ gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx );
+ gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx );
+ }
+
+ gdb_send_packet(gdb_ctx);
+}
+
+int
+in_debugger(void)
+{
+ return gdb_ctx->currently_attached;
+}
+
/* trap handler: main entry point */
int
__trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
@@ -560,8 +584,10 @@ initialise_gdb(void)
initialise_gdb(void)
{
gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
- if ( gdb_ctx->serhnd != -1 )
+ if ( gdb_ctx->serhnd != -1 ) {
+ serial_maybe_add_flags(gdb_ctx->serhnd, SERHND_DEBUGGER);
printk("GDB stub initialised.\n");
+ }
serial_start_sync(gdb_ctx->serhnd);
}
diff -r 9c4858991254 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/drivers/char/console.c Fri Sep 01 13:40:19 2006 +1000
@@ -115,6 +115,17 @@ long read_console_ring(XEN_GUEST_HANDLE(
#define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
static char serial_rx_ring[SERIAL_RX_SIZE];
static unsigned int serial_rx_cons, serial_rx_prod;
+
+/* Enable debugger output on the serial console if it's the same
+ * port as the debugger */
+void serial_maybe_add_flags(int debugger_handle, int flags)
+{
+ /* If the debugger and the serial console differ only in
+ * whether SERHND_DEBUGGER is enabled, enable it for the console */
+ if ( (debugger_handle != -1 ) &&
+ (debugger_handle & ~flags) == sercon_handle )
+ sercon_handle |= flags;
+}
/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
#define SWITCH_CODE (opt_conswitch[0]-'a'+1)
diff -r 9c4858991254 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/drivers/char/serial.c Fri Sep 01 13:40:19 2006 +1000
@@ -14,6 +14,7 @@
#include <xen/sched.h>
#include <xen/mm.h>
#include <xen/serial.h>
+#include <asm/debugger.h> /* in_debugger() and debugger_puts() */
static struct serial_port com[2] = {
{ .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED },
@@ -153,6 +154,10 @@ void serial_puts(int handle, const char
if ( (handle == -1) || !port->driver || !port->driver->putc )
return;
+ if ( (handle & SERHND_DEBUGGER) && in_debugger() ) {
+ debugger_puts(s);
+ return;
+ }
spin_lock_irqsave(&port->tx_lock, flags);
diff -r 9c4858991254 xen/include/asm-powerpc/debugger.h
--- a/xen/include/asm-powerpc/debugger.h Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/include/asm-powerpc/debugger.h Fri Sep 01 13:40:19 2006 +1000
@@ -39,6 +39,9 @@ static inline int debugger_trap_fatal(
#define debugger_trap_fatal(_v, _r) (0)
#define debugger_trap_immediate() ((void)0)
+#define debugger_puts(str) ((void)0)
+#define in_debugger() (0)
+
#endif /* CRASH_DEBUG */
#endif
diff -r 9c4858991254 xen/include/xen/gdbstub.h
--- a/xen/include/xen/gdbstub.h Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/include/xen/gdbstub.h Fri Sep 01 13:40:19 2006 +1000
@@ -90,6 +90,8 @@ void gdb_arch_exit(struct cpu_user_regs
#define SIGTERM 15
void initialise_gdb(void);
+void debugger_puts(const char *str);
+int in_debugger(void);
#else
diff -r 9c4858991254 xen/include/xen/serial.h
--- a/xen/include/xen/serial.h Tue Aug 29 07:07:57 2006 -0400
+++ b/xen/include/xen/serial.h Fri Sep 01 13:40:19 2006 +1000
@@ -66,6 +66,7 @@ struct uart_driver {
#define SERHND_HI (1<<1) /* Mux/demux each transferred char by MSB. */
#define SERHND_LO (1<<2) /* Ditto, except that the MSB is cleared. */
#define SERHND_COOKED (1<<3) /* Newline/carriage-return translation? */
+#define SERHND_DEBUGGER (1<<4) /* Translate console messages for the debugger
*/
/* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
void serial_init_preirq(void);
@@ -132,6 +133,10 @@ void ns16550_init(int index, struct ns16
/* Baud rate was pre-configured before invoking the UART driver. */
#define BAUD_AUTO (-1)
+/* Enable debuggger output if the serial console and debugger are on the same
+ * port */
+void serial_maybe_add_flags(int debugger_handle, int flags);
+
#endif /* __XEN_SERIAL_H__ */
/*
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2007.linux.org.au/
Jan 15-20 2007 The Australian Linux Technical Conference!
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|