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

[Xen-changelog] [xen-unstable] Use GDB 'O' packets for console output if the serial line is shared



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 19b126974c1f0bd4f075562931356bd84d11a372
# Parent  828c0c89d8309427f65d5293173f24487c5dd7d4
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.

Based on a patch from Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/common/gdbstub.c       |   52 ++++++++++++++++++++++++++++++++++++---------
 xen/drivers/char/console.c |   36 +++++++++++++++++++++++++++----
 xen/include/xen/console.h  |    9 +++++++
 xen/include/xen/gdbstub.h  |    3 +-
 4 files changed, 85 insertions(+), 15 deletions(-)

diff -r 828c0c89d830 -r 19b126974c1f xen/common/gdbstub.c
--- a/xen/common/gdbstub.c      Sat Sep 23 14:07:41 2006 +0100
+++ b/xen/common/gdbstub.c      Sat Sep 23 14:47:00 2006 +0100
@@ -357,6 +357,25 @@ gdb_cmd_write_mem(unsigned long addr, un
     gdb_send_packet(ctx);
 }
 
+static void
+gdbstub_attach(struct gdb_context *ctx)
+{
+    static void gdbstub_console_puts(const char *str);
+    if ( ctx->currently_attached )
+        return;    
+    ctx->currently_attached = 1;
+    ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts);
+}
+
+static void
+gdbstub_detach(struct gdb_context *ctx)
+{
+    if ( !ctx->currently_attached )
+        return;
+    ctx->currently_attached = 0;
+    console_giveback(ctx->console_steal_id);
+}
+
 /* command dispatcher */
 static int 
 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
@@ -427,7 +446,7 @@ process_command(struct cpu_user_regs *re
         gdb_arch_read_reg(addr, regs, ctx);
         break;
     case 'D':
-        ctx->currently_attached = 0;
+        gdbstub_detach(ctx);
         gdb_send_reply("OK", ctx);
         /* fall through */
     case 'k':
@@ -444,7 +463,7 @@ process_command(struct cpu_user_regs *re
              ctx->in_buf[1] )
             addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long));
         if ( ctx->in_buf[0] != 'D' )
-            ctx->currently_attached = 1;
+            gdbstub_attach(ctx);
         resume = 1;
         gdb_arch_resume(regs, addr, type, ctx);
         break;
@@ -459,16 +478,28 @@ process_command(struct cpu_user_regs *re
 
 static struct gdb_context
 __gdb_ctx = {
-    .serhnd             = -1,
-    .currently_attached = 0,
-    .running            = ATOMIC_INIT(1),
-    .connected          = 0,
-    .signum             = 1,
-    .in_bytes           = 0,
-    .out_offset         = 0,
-    .out_csum           = 0,
+    .serhnd  = -1,
+    .running = ATOMIC_INIT(1),
+    .signum  = 1
 };
 static struct gdb_context *gdb_ctx = &__gdb_ctx;
+
+static void
+gdbstub_console_puts(const char *str)
+{
+    const char *p;
+
+    gdb_start_packet(gdb_ctx);
+    gdb_write_to_packet_char('O', gdb_ctx);
+
+    for ( p = str; *p != '\0'; 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);
+}
 
 /* trap handler: main entry point */
 int 
@@ -525,6 +556,7 @@ __trap_to_gdb(struct cpu_user_regs *regs
 
     gdb_arch_enter(regs);
     gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
+
     /* If gdb is already attached, tell it we've stopped again. */
     if ( gdb_ctx->currently_attached )
     {
diff -r 828c0c89d830 -r 19b126974c1f xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Sat Sep 23 14:07:41 2006 +0100
+++ b/xen/drivers/char/console.c        Sat Sep 23 14:47:00 2006 +0100
@@ -116,6 +116,34 @@ 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;
 
+static void (*serial_steal_fn)(const char *);
+
+int console_steal(int handle, void (*fn)(const char *))
+{
+    if ( (handle == -1) || (handle != sercon_handle) )
+        return 0;
+
+    if ( serial_steal_fn == NULL )
+        return -EBUSY;
+
+    serial_steal_fn = fn;
+    return 1;
+}
+
+void console_giveback(int id)
+{
+    if ( id == 1 )
+        serial_steal_fn = NULL;
+}
+
+static void sercon_puts(const char *s)
+{
+    if ( serial_steal_fn != NULL )
+        (*serial_steal_fn)(s);
+    else
+        serial_puts(sercon_handle, s);
+}
+
 /* 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,7 +219,7 @@ static long guest_console_write(XEN_GUES
             return -EFAULT;
         kbuf[kcount] = '\0';
 
-        serial_puts(sercon_handle, kbuf);
+        sercon_puts(kbuf);
 
         for ( kptr = kbuf; *kptr != '\0'; kptr++ )
             vga_putchar(*kptr);
@@ -257,7 +285,7 @@ static inline void __putstr(const char *
 {
     int c;
 
-    serial_puts(sercon_handle, str);
+    sercon_puts(str);
 
     while ( (c = *str++) != '\0' )
     {
@@ -448,11 +476,11 @@ static void debugtrace_dump_worker(void)
 
     /* Print oldest portion of the ring. */
     ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
-    serial_puts(sercon_handle, &debugtrace_buf[debugtrace_prd]);
+    sercon_puts(&debugtrace_buf[debugtrace_prd]);
 
     /* Print youngest portion of the ring. */
     debugtrace_buf[debugtrace_prd] = '\0';
-    serial_puts(sercon_handle, &debugtrace_buf[0]);
+    sercon_puts(&debugtrace_buf[0]);
 
     memset(debugtrace_buf, '\0', debugtrace_bytes);
 
diff -r 828c0c89d830 -r 19b126974c1f xen/include/xen/console.h
--- a/xen/include/xen/console.h Sat Sep 23 14:07:41 2006 +0100
+++ b/xen/include/xen/console.h Sat Sep 23 14:47:00 2006 +0100
@@ -26,4 +26,13 @@ void console_start_sync(void);
 void console_start_sync(void);
 void console_end_sync(void);
 
+/*
+ * Steal output from the console. Returns +ve identifier, else -ve error.
+ * Takes the handle of the serial line to steal, and steal callback function.
+ */
+int console_steal(int handle, void (*fn)(const char *));
+
+/* Give back stolen console. Takes the identifier returned by console_steal. */
+void console_giveback(int id);
+
 #endif /* __CONSOLE_H__ */
diff -r 828c0c89d830 -r 19b126974c1f xen/include/xen/gdbstub.h
--- a/xen/include/xen/gdbstub.h Sat Sep 23 14:07:41 2006 +0100
+++ b/xen/include/xen/gdbstub.h Sat Sep 23 14:47:00 2006 +0100
@@ -33,7 +33,8 @@ unsigned long str2ulong(const char *str,
 unsigned long str2ulong(const char *str, unsigned long bytes);
 
 struct gdb_context {
-    int                 serhnd;
+    int                 serhnd;           /* handle on our serial line */
+    int                 console_steal_id; /* handle on stolen console */
     int                 currently_attached:1;
     atomic_t            running;
     unsigned long       connected;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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