Tony Breeds
2006-Sep-19 05:10 UTC
[Xen-devel] [RESEND] [PATCH] Use GDB ''O'' packets for console output
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 sent to a remote GDB if it''s attached and the serial console shares the same port. Tested on xenPPC. Feedback greatly appreciated. Signed-off-by: Tony Breeds <tony@bakeyournoodle.com> --- 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@lists.xensource.com http://lists.xensource.com/xen-devel 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@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2006-Sep-19 07:27 UTC
Re: [Xen-devel] [RESEND] [PATCH] Use GDB ''O'' packets for console output
Sharing a single serial line between console and gdbstub isn''t a mode we particularly considered. Without something like this patch, I suppose ordinary console output and gdb packets get mixed together on the line and confuse the gdb session? Does gdb actually print out the console data with your patch? It''s not nice to tell core serial code about the debugger. The switch between raw output and output-via-gdbstub should be entirely in console.c. -- Keir On 19/9/06 6:10 am, "Tony Breeds" <tony@bakeyournoodle.com> wrote:> 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 sent to a remote GDB if it''s attached and the serial console > shares the same port._______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tony Breeds
2006-Sep-21 03:41 UTC
Re: [Xen-devel] [RESEND] [PATCH] Use GDB ''O'' packets for console output
On Tue, Sep 19, 2006 at 08:27:09AM +0100, Keir Fraser wrote: Hi Kier, Sorry for the delay in my reply.> Sharing a single serial line between console and gdbstub isn''t a mode we > particularly considered.It''s needed when you only have one functional serial port.> Without something like this patch, I suppose > ordinary console output and gdb packets get mixed together on the line and > confuse the gdb session?Yup.> Does gdb actually print out the console data with > your patch?Sure does. for example: (gdb) target remote | ~/bin/gdb-remote Remote debugging using | ~/bin/gdb-remote __start_xen (mbi=0x74a430) at setup.c:336 336 if (opt_nosmp || ofd_boot_cpu == -1) { (gdb) b domctl.c:getdomaininfo Breakpoint 1 at 0x4020f8: file domctl.c, line 85. (gdb) c Continuing. (XEN) spinning up at most 16 total processors ... ... <snip> xen and dom0 boot output ... Blade4 login: (XEN) Waiting for GDB to attach... Breakpoint 1, getdomaininfo (d=0xa080, info=0xfad8) at domctl.c:85 85 u64 cpu_time = 0; (gdb)> It''s not nice to tell core serial code about the debugger. The switch > between raw output and output-via-gdbstub should be entirely in console.c.Attached is a patch that doesn''t touch the serial layer at all, and also compiles on x86/ia64. --- From: Tony Breeds <tony@bakeyournoodle.com> Use GDB ''O'' packets for console output if the serial line is shared and GDB is attached. It may be necessary for gdb and the console to share a serial port. This patch utilises the GDB protocol to encode console output. Feedback greatly appreciated. Signed-off-by: Tony Breeds <tony@bakeyournoodle.com> --- Compiled on x86_32/ia64 (with various values of debug= and crash_debug=) Tested on PPC xen/common/gdbstub.c | 26 +++++++++++++++++++++++++- xen/drivers/char/console.c | 27 ++++++++++++++++++++++----- xen/include/asm-ia64/debugger.h | 3 +++ xen/include/asm-powerpc/debugger.h | 3 +++ xen/include/asm-x86/debugger.h | 4 ++++ xen/include/xen/console.h | 3 +++ xen/include/xen/gdbstub.h | 2 ++ 7 files changed, 62 insertions(+), 6 deletions(-) --- diff -r 7a20fed8be73 xen/common/gdbstub.c --- a/xen/common/gdbstub.c Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/common/gdbstub.c Thu Sep 21 13:04:27 2006 +1000 @@ -470,6 +470,28 @@ __gdb_ctx = { }; static struct gdb_context *gdb_ctx = &__gdb_ctx; +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 +582,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 ) { + console_enable_debugger_io(gdb_ctx->serhnd); printk("GDB stub initialised.\n"); + } serial_start_sync(gdb_ctx->serhnd); } diff -r 7a20fed8be73 xen/drivers/char/console.c --- a/xen/drivers/char/console.c Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/drivers/char/console.c Thu Sep 21 13:04:27 2006 +1000 @@ -27,6 +27,8 @@ #include <asm/debugger.h> #include <asm/io.h> +/* If a debugger is attached send console output to it */ +static int use_debugger_io = 0; /* console: comma-separated list of console outputs. */ static char opt_console[30] = OPT_CONSOLE_STR; string_param("console", opt_console); @@ -116,6 +118,14 @@ static char serial_rx_ring[SERIAL_RX_SIZ 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 console_enable_debugger_io(int debugger_handle) +{ + if ( debugger_handle != -1 && debugger_handle == sercon_handle ) + use_debugger_io = 1; +} + /* CTRL-<switch_char> switches input direction between Xen and DOM0. */ #define SWITCH_CODE (opt_conswitch[0]-''a''+1) static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */ @@ -191,11 +201,14 @@ static long guest_console_write(XEN_GUES return -EFAULT; kbuf[kcount] = ''\0''; - serial_puts(sercon_handle, kbuf); - - for ( kptr = kbuf; *kptr != ''\0''; kptr++ ) - vga_putchar(*kptr); - + if ( use_debugger_io && in_debugger() ) + debugger_puts(kbuf); + else { + serial_puts(sercon_handle, kbuf); + + for ( kptr = kbuf; *kptr != ''\0''; kptr++ ) + vga_putchar(*kptr); + } guest_handle_add_offset(buffer, kcount); count -= kcount; } @@ -257,6 +270,10 @@ static inline void __putstr(const char * { int c; + if ( use_debugger_io && in_debugger() ) { + debugger_puts(str); + return; + } serial_puts(sercon_handle, str); while ( (c = *str++) != ''\0'' ) diff -r 7a20fed8be73 xen/include/asm-ia64/debugger.h --- a/xen/include/asm-ia64/debugger.h Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/include/asm-ia64/debugger.h Thu Sep 21 13:04:27 2006 +1000 @@ -111,6 +111,9 @@ static inline int debugger_trap_fatal( } #define debugger_trap_immediate() ((void)0) + +#define debugger_puts(str) ((void)0) +#define in_debugger() (0) #endif #endif // __ASSEMBLLY__ diff -r 7a20fed8be73 xen/include/asm-powerpc/debugger.h --- a/xen/include/asm-powerpc/debugger.h Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/include/asm-powerpc/debugger.h Thu Sep 21 13:04:27 2006 +1000 @@ -54,6 +54,9 @@ static inline void debugger_trap_immedia show_backtrace(sp, lr, lr); } +#define debugger_puts(str) ((void)0) +#define in_debugger() (0) + #endif /* CRASH_DEBUG */ #endif diff -r 7a20fed8be73 xen/include/asm-x86/debugger.h --- a/xen/include/asm-x86/debugger.h Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/include/asm-x86/debugger.h Thu Sep 21 13:04:27 2006 +1000 @@ -102,6 +102,10 @@ static inline int debugger_trap_entry( #define debugger_trap_fatal(v, r) (__debugger_trap_fatal(v, r)) #ifndef debugger_trap_immediate #define debugger_trap_immediate() (__debugger_trap_immediate()) + +#define debugger_puts(str) ((void)0) +#define in_debugger() (0) + #endif #endif /* __X86_DEBUGGER_H__ */ diff -r 7a20fed8be73 xen/include/xen/console.h --- a/xen/include/xen/console.h Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/include/xen/console.h Thu Sep 21 13:04:27 2006 +1000 @@ -26,4 +26,7 @@ void console_start_sync(void); void console_start_sync(void); void console_end_sync(void); +/* Enable debuggger output if the serial console and debugger are on the same + * port */ +void console_enable_debugger_io(int debugger_handle); #endif /* __CONSOLE_H__ */ diff -r 7a20fed8be73 xen/include/xen/gdbstub.h --- a/xen/include/xen/gdbstub.h Sat Sep 16 09:34:26 2006 -0400 +++ b/xen/include/xen/gdbstub.h Thu Sep 21 13:04:27 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 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@lists.xensource.com http://lists.xensource.com/xen-devel