ia64/xen-unstable
changeset 11602:19b126974c1f
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>
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>
author | kfraser@localhost.localdomain |
---|---|
date | Sat Sep 23 14:47:00 2006 +0100 (2006-09-23) |
parents | 828c0c89d830 |
children | e4a496c2b2d1 |
files | xen/common/gdbstub.c xen/drivers/char/console.c xen/include/xen/console.h xen/include/xen/gdbstub.h |
line diff
1.1 --- a/xen/common/gdbstub.c Sat Sep 23 14:07:41 2006 +0100 1.2 +++ b/xen/common/gdbstub.c Sat Sep 23 14:47:00 2006 +0100 1.3 @@ -357,6 +357,25 @@ gdb_cmd_write_mem(unsigned long addr, un 1.4 gdb_send_packet(ctx); 1.5 } 1.6 1.7 +static void 1.8 +gdbstub_attach(struct gdb_context *ctx) 1.9 +{ 1.10 + static void gdbstub_console_puts(const char *str); 1.11 + if ( ctx->currently_attached ) 1.12 + return; 1.13 + ctx->currently_attached = 1; 1.14 + ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts); 1.15 +} 1.16 + 1.17 +static void 1.18 +gdbstub_detach(struct gdb_context *ctx) 1.19 +{ 1.20 + if ( !ctx->currently_attached ) 1.21 + return; 1.22 + ctx->currently_attached = 0; 1.23 + console_giveback(ctx->console_steal_id); 1.24 +} 1.25 + 1.26 /* command dispatcher */ 1.27 static int 1.28 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) 1.29 @@ -427,7 +446,7 @@ process_command(struct cpu_user_regs *re 1.30 gdb_arch_read_reg(addr, regs, ctx); 1.31 break; 1.32 case 'D': 1.33 - ctx->currently_attached = 0; 1.34 + gdbstub_detach(ctx); 1.35 gdb_send_reply("OK", ctx); 1.36 /* fall through */ 1.37 case 'k': 1.38 @@ -444,7 +463,7 @@ process_command(struct cpu_user_regs *re 1.39 ctx->in_buf[1] ) 1.40 addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long)); 1.41 if ( ctx->in_buf[0] != 'D' ) 1.42 - ctx->currently_attached = 1; 1.43 + gdbstub_attach(ctx); 1.44 resume = 1; 1.45 gdb_arch_resume(regs, addr, type, ctx); 1.46 break; 1.47 @@ -459,17 +478,29 @@ process_command(struct cpu_user_regs *re 1.48 1.49 static struct gdb_context 1.50 __gdb_ctx = { 1.51 - .serhnd = -1, 1.52 - .currently_attached = 0, 1.53 - .running = ATOMIC_INIT(1), 1.54 - .connected = 0, 1.55 - .signum = 1, 1.56 - .in_bytes = 0, 1.57 - .out_offset = 0, 1.58 - .out_csum = 0, 1.59 + .serhnd = -1, 1.60 + .running = ATOMIC_INIT(1), 1.61 + .signum = 1 1.62 }; 1.63 static struct gdb_context *gdb_ctx = &__gdb_ctx; 1.64 1.65 +static void 1.66 +gdbstub_console_puts(const char *str) 1.67 +{ 1.68 + const char *p; 1.69 + 1.70 + gdb_start_packet(gdb_ctx); 1.71 + gdb_write_to_packet_char('O', gdb_ctx); 1.72 + 1.73 + for ( p = str; *p != '\0'; p++ ) 1.74 + { 1.75 + gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx ); 1.76 + gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx ); 1.77 + } 1.78 + 1.79 + gdb_send_packet(gdb_ctx); 1.80 +} 1.81 + 1.82 /* trap handler: main entry point */ 1.83 int 1.84 __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) 1.85 @@ -525,6 +556,7 @@ int 1.86 1.87 gdb_arch_enter(regs); 1.88 gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); 1.89 + 1.90 /* If gdb is already attached, tell it we've stopped again. */ 1.91 if ( gdb_ctx->currently_attached ) 1.92 {
2.1 --- a/xen/drivers/char/console.c Sat Sep 23 14:07:41 2006 +0100 2.2 +++ b/xen/drivers/char/console.c Sat Sep 23 14:47:00 2006 +0100 2.3 @@ -116,6 +116,34 @@ long read_console_ring(XEN_GUEST_HANDLE( 2.4 static char serial_rx_ring[SERIAL_RX_SIZE]; 2.5 static unsigned int serial_rx_cons, serial_rx_prod; 2.6 2.7 +static void (*serial_steal_fn)(const char *); 2.8 + 2.9 +int console_steal(int handle, void (*fn)(const char *)) 2.10 +{ 2.11 + if ( (handle == -1) || (handle != sercon_handle) ) 2.12 + return 0; 2.13 + 2.14 + if ( serial_steal_fn == NULL ) 2.15 + return -EBUSY; 2.16 + 2.17 + serial_steal_fn = fn; 2.18 + return 1; 2.19 +} 2.20 + 2.21 +void console_giveback(int id) 2.22 +{ 2.23 + if ( id == 1 ) 2.24 + serial_steal_fn = NULL; 2.25 +} 2.26 + 2.27 +static void sercon_puts(const char *s) 2.28 +{ 2.29 + if ( serial_steal_fn != NULL ) 2.30 + (*serial_steal_fn)(s); 2.31 + else 2.32 + serial_puts(sercon_handle, s); 2.33 +} 2.34 + 2.35 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */ 2.36 #define SWITCH_CODE (opt_conswitch[0]-'a'+1) 2.37 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */ 2.38 @@ -191,7 +219,7 @@ static long guest_console_write(XEN_GUES 2.39 return -EFAULT; 2.40 kbuf[kcount] = '\0'; 2.41 2.42 - serial_puts(sercon_handle, kbuf); 2.43 + sercon_puts(kbuf); 2.44 2.45 for ( kptr = kbuf; *kptr != '\0'; kptr++ ) 2.46 vga_putchar(*kptr); 2.47 @@ -257,7 +285,7 @@ static inline void __putstr(const char * 2.48 { 2.49 int c; 2.50 2.51 - serial_puts(sercon_handle, str); 2.52 + sercon_puts(str); 2.53 2.54 while ( (c = *str++) != '\0' ) 2.55 { 2.56 @@ -448,11 +476,11 @@ static void debugtrace_dump_worker(void) 2.57 2.58 /* Print oldest portion of the ring. */ 2.59 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0); 2.60 - serial_puts(sercon_handle, &debugtrace_buf[debugtrace_prd]); 2.61 + sercon_puts(&debugtrace_buf[debugtrace_prd]); 2.62 2.63 /* Print youngest portion of the ring. */ 2.64 debugtrace_buf[debugtrace_prd] = '\0'; 2.65 - serial_puts(sercon_handle, &debugtrace_buf[0]); 2.66 + sercon_puts(&debugtrace_buf[0]); 2.67 2.68 memset(debugtrace_buf, '\0', debugtrace_bytes); 2.69
3.1 --- a/xen/include/xen/console.h Sat Sep 23 14:07:41 2006 +0100 3.2 +++ b/xen/include/xen/console.h Sat Sep 23 14:47:00 2006 +0100 3.3 @@ -26,4 +26,13 @@ void console_force_lock(void); 3.4 void console_start_sync(void); 3.5 void console_end_sync(void); 3.6 3.7 +/* 3.8 + * Steal output from the console. Returns +ve identifier, else -ve error. 3.9 + * Takes the handle of the serial line to steal, and steal callback function. 3.10 + */ 3.11 +int console_steal(int handle, void (*fn)(const char *)); 3.12 + 3.13 +/* Give back stolen console. Takes the identifier returned by console_steal. */ 3.14 +void console_giveback(int id); 3.15 + 3.16 #endif /* __CONSOLE_H__ */
4.1 --- a/xen/include/xen/gdbstub.h Sat Sep 23 14:07:41 2006 +0100 4.2 +++ b/xen/include/xen/gdbstub.h Sat Sep 23 14:47:00 2006 +0100 4.3 @@ -33,7 +33,8 @@ char str2hex(const char *str); 4.4 unsigned long str2ulong(const char *str, unsigned long bytes); 4.5 4.6 struct gdb_context { 4.7 - int serhnd; 4.8 + int serhnd; /* handle on our serial line */ 4.9 + int console_steal_id; /* handle on stolen console */ 4.10 int currently_attached:1; 4.11 atomic_t running; 4.12 unsigned long connected;