aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/gdbstub.c
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-09-23 14:47:00 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-09-23 14:47:00 +0100
commitc180e655c186e6cacc56bbdd20bb301f5df2b10b (patch)
tree6c08620ec67ad46d5b60fd0091625371fb17a887 /xen/common/gdbstub.c
parentd85cf94621ab3531828430b0b50f860d0ff81887 (diff)
downloadxen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.tar.gz
xen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.tar.bz2
xen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.zip
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@bakeyournoodle.com> Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/common/gdbstub.c')
-rw-r--r--xen/common/gdbstub.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/xen/common/gdbstub.c b/xen/common/gdbstub.c
index 8934122925..257547ed19 100644
--- a/xen/common/gdbstub.c
+++ b/xen/common/gdbstub.c
@@ -357,6 +357,25 @@ gdb_cmd_write_mem(unsigned long addr, unsigned long length,
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 *regs, struct gdb_context *ctx)
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 *regs, struct gdb_context *ctx)
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,17 +478,29 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
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
__trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
@@ -525,6 +556,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
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 )
{