# 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
|