[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [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 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.