ia64/xen-unstable

changeset 1951:0efb230c9804

bitkeeper revision 1.1098.1.1 (4107c16f_jhuAGUiMBcotuiFhO6dHQ)

Add a simple debugger for Xen and domain 0. This isn't anything
like as complete as PDB; it can't access any userspace other than
the current process's and it can't make any changes to a running
process. On the other hand, it's probably slightly less fragile.
The code's a lot cleaner, as well.
author sos22@donkeykong.cl.cam.ac.uk
date Wed Jul 28 15:08:31 2004 +0000 (2004-07-28)
parents 81936d3b712c
children 049ca85b7b73
files .rootkeys BitKeeper/etc/logging_ok xen/arch/x86/x86_32/xdb_trap.S xen/arch/x86/xdb.c xen/common/domain.c xen/common/kernel.c xen/common/keyhandler.c xen/drivers/char/console.c xen/drivers/char/serial.c
line diff
     1.1 --- a/.rootkeys	Thu Jul 15 15:54:53 2004 +0000
     1.2 +++ b/.rootkeys	Wed Jul 28 15:08:31 2004 +0000
     1.3 @@ -449,10 +449,12 @@ 3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/
     1.4  3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/x86/x86_32/entry.S
     1.5  3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/x86/x86_32/mm.c
     1.6  3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c
     1.7 +4107c15e_NqNYew2EXroXz2mgTAMWQ xen/arch/x86/x86_32/xdb_trap.S
     1.8  3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds
     1.9  40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S
    1.10  40e96d3ahBTZqbTViInnq0lM03vs7A xen/arch/x86/x86_64/usercopy.c
    1.11  40e96d3akN3Hu_J5Bk-WXD8OGscrYQ xen/arch/x86/x86_64/xen.lds
    1.12 +4107c15e-VmEcLsE-7JCXZaabI8C7A xen/arch/x86/xdb.c
    1.13  3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
    1.14  3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c
    1.15  4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
     2.1 --- a/BitKeeper/etc/logging_ok	Thu Jul 15 15:54:53 2004 +0000
     2.2 +++ b/BitKeeper/etc/logging_ok	Wed Jul 28 15:08:31 2004 +0000
     2.3 @@ -38,6 +38,7 @@ smh22@boulderdash.cl.cam.ac.uk
     2.4  smh22@labyrinth.cl.cam.ac.uk
     2.5  smh22@tempest.cl.cam.ac.uk
     2.6  smh22@uridium.cl.cam.ac.uk
     2.7 +sos22@donkeykong.cl.cam.ac.uk
     2.8  sos22@labyrinth.cl.cam.ac.uk
     2.9  tlh20@elite.cl.cam.ac.uk
    2.10  tlh20@labyrinth.cl.cam.ac.uk
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/x86/x86_32/xdb_trap.S	Wed Jul 28 15:08:31 2004 +0000
     3.3 @@ -0,0 +1,35 @@
     3.4 +.global trap_to_xendbg
     3.5 +.extern __trap_to_xendbg
     3.6 +	
     3.7 +#define SAVE_ALL_NOSEGREGS \
     3.8 +	pushw $0;  \
     3.9 +        pushw %gs; \
    3.10 +	pushw $0;  \
    3.11 +        pushw %fs; \
    3.12 +	pushw $0;  \
    3.13 +        pushw %es; \
    3.14 +	pushw $0;  \
    3.15 +        pushw %ds; \
    3.16 +        pushl %eax; \
    3.17 +        pushl %ebp; \
    3.18 +        pushl %edi; \
    3.19 +        pushl %esi; \
    3.20 +        pushl %edx; \
    3.21 +        pushl %ecx; \
    3.22 +        pushl %ebx;
    3.23 +
    3.24 +	// Save the register state and call __trap_to_xendbg 
    3.25 +trap_to_xendbg:
    3.26 +	pushw $0
    3.27 +	pushw %ss
    3.28 +	pushl %esp //We'll fix this up later, in __trap_to_xendbg, by adding 8
    3.29 +	pushf
    3.30 +	pushw $0
    3.31 +	pushw %cs
    3.32 +	pushl 16(%esp)
    3.33 +1:	pushl $0 		// Orig_eax
    3.34 +	SAVE_ALL_NOSEGREGS
    3.35 +	pushl %esp
    3.36 +	call __trap_to_xendbg
    3.37 +	add $72, %esp
    3.38 +	ret
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/arch/x86/xdb.c	Wed Jul 28 15:08:31 2004 +0000
     4.3 @@ -0,0 +1,378 @@
     4.4 +/* Simple hacked-up version of pdb for us in post-mortem debugging of
     4.5 +   Xen and domain 0. This should be a little cleaner, hopefully.  Note
     4.6 +   that we can't share a serial line with PDB. */
     4.7 +#include <xen/lib.h>
     4.8 +#include <asm/uaccess.h>
     4.9 +#include <xen/serial.h>
    4.10 +#include <asm/irq.h>
    4.11 +#include <xen/spinlock.h>
    4.12 +
    4.13 +/* Printk isn't particularly safe just after we've trapped to the
    4.14 +   debugger. so avoid it. */
    4.15 +#define dbg_printk(...)
    4.16 +
    4.17 +static int
    4.18 +xendbg_serhnd = -1;
    4.19 +
    4.20 +static void
    4.21 +xendbg_put_char(u8 data)
    4.22 +{
    4.23 +	serial_putc(xendbg_serhnd, data);
    4.24 +}
    4.25 +
    4.26 +static u8
    4.27 +xendbg_get_char(void)
    4.28 +{
    4.29 +	u8 ch;
    4.30 +	extern unsigned char __serial_getc(int handle);
    4.31 +	ch = __serial_getc(xendbg_serhnd);
    4.32 +	return ch;
    4.33 +}
    4.34 +
    4.35 +static int
    4.36 +hex_char_val(unsigned char c)
    4.37 +{
    4.38 +	if (c >= '0' && c <= '9')
    4.39 +		return c - '0';
    4.40 +	else if (c >= 'a' && c <= 'f')
    4.41 +		return c - 'a' + 10;
    4.42 +	else if (c >= 'A' && c <= 'F')
    4.43 +		return c - 'A' + 10;
    4.44 +	else
    4.45 +		BUG();
    4.46 +}
    4.47 +
    4.48 +static unsigned char
    4.49 +val_to_hex_char(unsigned val)
    4.50 +{
    4.51 +	if (val < 10)
    4.52 +		return val + '0';
    4.53 +	else if (val < 16)
    4.54 +		return val - 10 + 'a';
    4.55 +	else
    4.56 +		BUG();
    4.57 +}
    4.58 +
    4.59 +/* Receive a command.  Returns -1 on csum error, 0 otherwise. */
    4.60 +/* Does not acknowledge. */
    4.61 +static int
    4.62 +attempt_receive_packet(char *recv_buf)
    4.63 +{
    4.64 +	int count;
    4.65 +	u8 csum;
    4.66 +	u8 received_csum;
    4.67 +	u8 ch;
    4.68 +
    4.69 +	/* Skip over everything up to the first '$' */
    4.70 +	while ((ch = xendbg_get_char()) != '$')
    4.71 +		;
    4.72 +	csum = 0;
    4.73 +	for (count = 0; count < 4096; count++) {
    4.74 +		ch = xendbg_get_char();
    4.75 +		if (ch == '#')
    4.76 +			break;
    4.77 +		recv_buf[count] = ch;
    4.78 +		csum += ch;
    4.79 +	}
    4.80 +	if (count == 4096) {
    4.81 +		dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
    4.82 +		return -1;
    4.83 +	}
    4.84 +	recv_buf[count] = 0;
    4.85 +	received_csum = hex_char_val(xendbg_get_char()) * 16 +
    4.86 +		hex_char_val(xendbg_get_char());
    4.87 +	if (received_csum == csum) {
    4.88 +		return 0;
    4.89 +	} else {
    4.90 +		return -1;
    4.91 +	}
    4.92 +}
    4.93 +
    4.94 +/* Send a string of bytes to the debugger. */
    4.95 +static void
    4.96 +xendbg_send(const char *buf, int count)
    4.97 +{
    4.98 +	int x;
    4.99 +	for (x = 0; x < count; x++)
   4.100 +		xendbg_put_char(buf[x]);
   4.101 +}
   4.102 +
   4.103 +/* Receive a command, discarding up to ten packets with csum
   4.104 + * errors.  Acknowledges all received packets. */
   4.105 +static int
   4.106 +receive_command(char *recv_buf)
   4.107 +{
   4.108 +	int r;
   4.109 +	int count;
   4.110 +
   4.111 +	count = 0;
   4.112 +	do {
   4.113 +		r = attempt_receive_packet(recv_buf);
   4.114 +		if (r < 0)
   4.115 +			xendbg_send("-", 1);
   4.116 +		else
   4.117 +			xendbg_send("+", 1);
   4.118 +		count++;
   4.119 +	} while (r < 0 && count < 10);
   4.120 +	return r;
   4.121 +}
   4.122 +
   4.123 +static void
   4.124 +u32_to_hex_u8(unsigned char val, char *buf)
   4.125 +{
   4.126 +	if (val >= 256)
   4.127 +		BUG();
   4.128 +	sprintf(buf, "%.02x\n", val);
   4.129 +}
   4.130 +
   4.131 +static void
   4.132 +u32_to_hex_u32(unsigned val, char *buf)
   4.133 +{
   4.134 +	sprintf(buf, "%.08x\n", val);
   4.135 +}
   4.136 +
   4.137 +static void
   4.138 +xendbg_send_hex_u8(unsigned char val)
   4.139 +{
   4.140 +	char buf[2];
   4.141 +	u32_to_hex_u8(val, buf);
   4.142 +	xendbg_send(buf, 2);
   4.143 +}
   4.144 +
   4.145 +static u8
   4.146 +xendbg_reply_csum;
   4.147 +
   4.148 +static void
   4.149 +xendbg_start_reply(void)
   4.150 +{
   4.151 +	xendbg_reply_csum = 0;
   4.152 +	xendbg_send("$", 1);
   4.153 +}
   4.154 +
   4.155 +static void
   4.156 +xendbg_sendrep_data(const unsigned char *data, unsigned long len)
   4.157 +{
   4.158 +	int x;
   4.159 +
   4.160 +	for (x = 0; x < len; x++) {
   4.161 +		xendbg_put_char(data[x]);
   4.162 +		xendbg_reply_csum += data[x];
   4.163 +	}
   4.164 +}
   4.165 +
   4.166 +/* Return 0 if the reply was successfully received, !0 otherwise. */
   4.167 +static int
   4.168 +xendbg_finish_reply(void)
   4.169 +{
   4.170 +	char ch;
   4.171 +
   4.172 +	xendbg_send("#", 1);
   4.173 +	xendbg_send_hex_u8(xendbg_reply_csum);
   4.174 +	ch = xendbg_get_char();
   4.175 +	if (ch == '+')
   4.176 +		return 0;
   4.177 +	else
   4.178 +		return 1;
   4.179 +}
   4.180 +
   4.181 +static void
   4.182 +xendbg_sendrep_hex_u8(unsigned val)
   4.183 +{
   4.184 +	char buf[2];
   4.185 +	u32_to_hex_u8(val, buf);
   4.186 +	xendbg_sendrep_data(buf, 2);
   4.187 +}
   4.188 +
   4.189 +static void
   4.190 +xendbg_sendrep_hex_u32(unsigned val)
   4.191 +{
   4.192 +	char buf[8];
   4.193 +	u32_to_hex_u32(val, buf);
   4.194 +	xendbg_sendrep_data(buf, 8);
   4.195 +}
   4.196 +
   4.197 +static void
   4.198 +xendbg_sendrep_hex_u32_le(unsigned val)
   4.199 +{
   4.200 +	val = (((val >> 0) & 0xff) << 24) |
   4.201 +		(((val >> 8) & 0xff) << 16) |
   4.202 +		(((val >> 16) & 0xff) << 8) |
   4.203 +		(((val >> 24) & 0xff) << 0);
   4.204 +	xendbg_sendrep_hex_u32(val);
   4.205 +}
   4.206 +
   4.207 +static int
   4.208 +handle_memory_read_command(unsigned long addr, unsigned long length)
   4.209 +{
   4.210 +	int x;
   4.211 +	unsigned char val;
   4.212 +	int r;
   4.213 +	unsigned old_s_limit;
   4.214 +
   4.215 +	dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
   4.216 +	       length);
   4.217 +	old_s_limit = current->addr_limit.seg;
   4.218 +	current->addr_limit.seg = ~0;
   4.219 +	xendbg_start_reply();
   4.220 +	for (x = 0; x < length; x++) {
   4.221 +		r = copy_from_user(&val, (void *)(addr + x), 1);
   4.222 +		if (r != 0) {
   4.223 +			dbg_printk("Error reading from %lx.\n", addr + x);
   4.224 +			break;
   4.225 +		}
   4.226 +		xendbg_sendrep_hex_u8(val);
   4.227 +	}
   4.228 +	if (x == 0)
   4.229 +		xendbg_sendrep_data("E05", 3);
   4.230 +	dbg_printk("Read done.\n");
   4.231 +	current->addr_limit.seg = old_s_limit;
   4.232 +	return xendbg_finish_reply();
   4.233 +}
   4.234 +
   4.235 +static int
   4.236 +xendbg_send_reply(const char *buf)
   4.237 +{
   4.238 +	xendbg_start_reply();
   4.239 +	xendbg_sendrep_data(buf, strlen(buf));
   4.240 +	return xendbg_finish_reply();
   4.241 +}
   4.242 +
   4.243 +static int
   4.244 +handle_register_read_command(struct pt_regs *regs)
   4.245 +{
   4.246 +	xendbg_start_reply();
   4.247 +	xendbg_sendrep_hex_u32_le(regs->eax);
   4.248 +	xendbg_sendrep_hex_u32_le(regs->ecx);
   4.249 +	xendbg_sendrep_hex_u32_le(regs->edx);
   4.250 +	xendbg_sendrep_hex_u32_le(regs->ebx);
   4.251 +	xendbg_sendrep_hex_u32_le(regs->esp);
   4.252 +	xendbg_sendrep_hex_u32_le(regs->ebp);
   4.253 +	xendbg_sendrep_hex_u32_le(regs->esi);
   4.254 +	xendbg_sendrep_hex_u32_le(regs->edi);
   4.255 +	xendbg_sendrep_hex_u32_le(regs->eip);
   4.256 +	xendbg_sendrep_hex_u32_le(regs->eflags);
   4.257 +	xendbg_sendrep_hex_u32_le(regs->xcs);
   4.258 +	xendbg_sendrep_hex_u32_le(regs->xss);
   4.259 +	xendbg_sendrep_hex_u32_le(regs->xes);
   4.260 +	xendbg_sendrep_hex_u32_le(regs->xfs);
   4.261 +	xendbg_sendrep_hex_u32_le(regs->xgs);
   4.262 +	return xendbg_finish_reply();
   4.263 +}
   4.264 +
   4.265 +static unsigned long
   4.266 +hex_to_int(const char *start, const char **end)
   4.267 +{
   4.268 +	return simple_strtol(start, (char **)end, 16);
   4.269 +}
   4.270 +
   4.271 +static int
   4.272 +process_command(const char *received_packet, struct pt_regs *regs)
   4.273 +{
   4.274 +	const char *ptr;
   4.275 +	unsigned long addr, length;
   4.276 +	int retry;
   4.277 +	int counter;
   4.278 +	int resume = 0;
   4.279 +
   4.280 +	/* Repeat until gdb acks the reply */
   4.281 +	counter = 0;
   4.282 +	do {
   4.283 +		switch (received_packet[0]) {
   4.284 +		case 'g': /* Read registers */
   4.285 +			retry = handle_register_read_command(regs);
   4.286 +			break;
   4.287 +		case 'm': /* Read memory */
   4.288 +			addr = hex_to_int(received_packet + 1, &ptr);
   4.289 +			if (ptr == received_packet + 1 ||
   4.290 +			    ptr[0] != ',') {
   4.291 +				xendbg_send_reply("E03");
   4.292 +				return 0;
   4.293 +			}
   4.294 +			length = hex_to_int(ptr + 1, &ptr);
   4.295 +			if (ptr[0] != 0) {
   4.296 +				xendbg_send_reply("E04");
   4.297 +				return 0;
   4.298 +			}
   4.299 +			retry =
   4.300 +				handle_memory_read_command(addr,
   4.301 +							   length);
   4.302 +			break;
   4.303 +		case 'G': /* Write registers */
   4.304 +		case 'M': /* Write memory */
   4.305 +			retry = xendbg_send_reply("E02");
   4.306 +			break;
   4.307 +		case 'D':
   4.308 +			resume = 1;
   4.309 +			retry = xendbg_send_reply("");
   4.310 +			break;
   4.311 +		case 'c': /* Resume at current address */
   4.312 +		case 's': /* Single step */
   4.313 +		case '?':
   4.314 +			retry = xendbg_send_reply("S01");
   4.315 +			break;
   4.316 +		default:
   4.317 +			retry = xendbg_send_reply("");
   4.318 +			break;
   4.319 +		}
   4.320 +		counter++;
   4.321 +	} while (retry == 1 && counter < 10);
   4.322 +	if (retry) {
   4.323 +		dbg_printk("WARNING: gdb disappeared when we were trying to send it a reply.\n");
   4.324 +		return 1;
   4.325 +	}
   4.326 +	return resume;
   4.327 +}
   4.328 +
   4.329 +void
   4.330 +__trap_to_xendbg(struct pt_regs *regs)
   4.331 +{
   4.332 +	int resume = 0;
   4.333 +	int r;
   4.334 +	static int xendbg_running;
   4.335 +	static char recv_buf[4096];
   4.336 +
   4.337 +	if (xendbg_serhnd < 0) {
   4.338 +		dbg_printk("Debugger not ready yet.\n");
   4.339 +		return;
   4.340 +	}
   4.341 +	/* We rely on our caller to ensure we're only on one processor
   4.342 +	 * at a time... We should probably panic here, but given that
   4.343 +	 * we're a debugger we should probably be a little tolerant of
   4.344 +	 * things going wrong. */
   4.345 +	if (xendbg_running) {
   4.346 +		dbg_printk("WARNING WARNING WARNING: Avoiding recursive xendbg.\n");
   4.347 +		return;
   4.348 +	}
   4.349 +	xendbg_running = 1;
   4.350 +	/* trap_to_xendbg gets esp slightly wrong.  Correct for this. */
   4.351 +	regs->esp += 8;
   4.352 +
   4.353 +	dbg_printk("Waiting for GDB to attach to XenDBG\n");
   4.354 +	/* Urgg... hope this is right... */
   4.355 +	while (resume == 0) {
   4.356 +		r = receive_command(recv_buf);
   4.357 +		if (r < 0) {
   4.358 +			dbg_printk("GDB disappeared, trying to resume Xen...\n");
   4.359 +			resume = 1;
   4.360 +		} else
   4.361 +			resume = process_command(recv_buf, regs);
   4.362 +	}
   4.363 +	xendbg_running = 0;
   4.364 +}
   4.365 +
   4.366 +void
   4.367 +initialize_xendbg(void)
   4.368 +{
   4.369 +	extern char opt_xendbg[];
   4.370 +
   4.371 +	if (!strcmp(opt_xendbg, "none"))
   4.372 +		return;
   4.373 +	xendbg_serhnd = parse_serial_handle(opt_xendbg);
   4.374 +	if (xendbg_serhnd == -1)
   4.375 +		panic("Can't parse %s as XDB serial info.\n", opt_xendbg);
   4.376 +
   4.377 +	/* Acknowledge any spurious GDB packets. */
   4.378 +	xendbg_put_char('+');
   4.379 +
   4.380 +	printk("Xendbg initialised.\n");
   4.381 +}
     5.1 --- a/xen/common/domain.c	Thu Jul 15 15:54:53 2004 +0000
     5.2 +++ b/xen/common/domain.c	Wed Jul 28 15:08:31 2004 +0000
     5.3 @@ -163,6 +163,8 @@ void domain_crash(void)
     5.4      BUG();
     5.5  }
     5.6  
     5.7 +extern void trap_to_xendbg(void);
     5.8 +
     5.9  void domain_shutdown(u8 reason)
    5.10  {
    5.11      struct domain *d;
    5.12 @@ -172,6 +174,8 @@ void domain_shutdown(u8 reason)
    5.13          extern void machine_restart(char *);
    5.14          extern void machine_halt(void);
    5.15  
    5.16 +	trap_to_xendbg();
    5.17 +
    5.18          if ( reason == 0 ) 
    5.19          {
    5.20              printk("Domain 0 halted: Our work here is done.\n");
     6.1 --- a/xen/common/kernel.c	Thu Jul 15 15:54:53 2004 +0000
     6.2 +++ b/xen/common/kernel.c	Wed Jul 28 15:08:31 2004 +0000
     6.3 @@ -64,6 +64,8 @@ int opt_ignorebiostables=0;
     6.4  int opt_watchdog=0;
     6.5  /* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */
     6.6  unsigned char opt_pdb[10] = "none";
     6.7 +/* opt_pdb: Name of serial port for Xen debugger (and enable xendbg) */
     6.8 +unsigned char opt_xendbg[10] = "none";
     6.9  /* opt_tbuf_size: trace buffer size (in pages) */
    6.10  unsigned int opt_tbuf_size = 10;
    6.11  /* opt_sched: scheduler - default to Borrowed Virtual Time */
    6.12 @@ -98,6 +100,7 @@ static struct {
    6.13      { "ignorebiostables",  OPT_BOOL, &opt_ignorebiostables },
    6.14      { "watchdog",          OPT_BOOL, &opt_watchdog },
    6.15      { "pdb",               OPT_STR,  &opt_pdb },
    6.16 +    { "xendbg",            OPT_STR,  &opt_xendbg },
    6.17      { "tbuf_size",         OPT_UINT, &opt_tbuf_size },
    6.18      { "sched",             OPT_STR,  &opt_sched },
    6.19      { "physdev_dom0_hide", OPT_STR,  &opt_physdev_dom0_hide },
    6.20 @@ -108,6 +111,9 @@ static struct {
    6.21  };
    6.22  
    6.23  
    6.24 +void initialize_xendbg(void);
    6.25 +void trap_to_xendbg(void);
    6.26 +
    6.27  void cmain(multiboot_info_t *mbi)
    6.28  {
    6.29      struct domain *new_dom;
    6.30 @@ -163,6 +169,8 @@ void cmain(multiboot_info_t *mbi)
    6.31  
    6.32      init_console();
    6.33  
    6.34 +    initialize_xendbg();
    6.35 +
    6.36      /* HELLO WORLD --- start-of-day banner text. */
    6.37      printk(XEN_BANNER);
    6.38      printk(" http://www.cl.cam.ac.uk/netos/xen\n");
    6.39 @@ -291,6 +299,10 @@ void cmain(multiboot_info_t *mbi)
    6.40  
    6.41      shadow_mode_init();
    6.42  
    6.43 +    printk("Trapping to debugger.\n");
    6.44 +    trap_to_xendbg();
    6.45 +    printk("Trapped to debugger and came back.\n");
    6.46 +
    6.47      /*
    6.48       * We're going to setup domain0 using the module(s) that we stashed safely
    6.49       * above our heap. The second module, if present, is an initrd ramdisk.
     7.1 --- a/xen/common/keyhandler.c	Thu Jul 15 15:54:53 2004 +0000
     7.2 +++ b/xen/common/keyhandler.c	Wed Jul 28 15:08:31 2004 +0000
     7.3 @@ -115,6 +115,11 @@ extern void perfc_reset(unsigned char ke
     7.4                          struct pt_regs *regs);
     7.5  #endif
     7.6  
     7.7 +void do_panic_key(unsigned char key, void *dev_id, struct pt_regs *regs)
     7.8 +{
     7.9 +    panic("Panic requested from console");
    7.10 +}
    7.11 +
    7.12  void initialize_keytable(void)
    7.13  {
    7.14      add_key_handler('d', dump_registers, "dump registers"); 
    7.15 @@ -128,4 +133,5 @@ void initialize_keytable(void)
    7.16      add_key_handler('p', perfc_printall, "print performance counters"); 
    7.17      add_key_handler('P', perfc_reset,    "reset performance counters"); 
    7.18  #endif
    7.19 +    add_key_handler('%', do_panic_key,   "Panic Xen");
    7.20  }
     8.1 --- a/xen/drivers/char/console.c	Thu Jul 15 15:54:53 2004 +0000
     8.2 +++ b/xen/drivers/char/console.c	Wed Jul 28 15:08:31 2004 +0000
     8.3 @@ -440,6 +440,8 @@ void console_endboot(int disable_vga)
     8.4   * **************************************************************
     8.5   */
     8.6  
     8.7 +extern void trap_to_xendbg(void);
     8.8 +
     8.9  void panic(const char *fmt, ...)
    8.10  {
    8.11      va_list args;
    8.12 @@ -450,7 +452,9 @@ void panic(const char *fmt, ...)
    8.13      va_start(args, fmt);
    8.14      (void)vsnprintf(buf, sizeof(buf), fmt, args);
    8.15      va_end(args);
    8.16 -    
    8.17 +
    8.18 +    trap_to_xendbg();
    8.19 +
    8.20      /* Spit out multiline message in one go. */
    8.21      spin_lock_irqsave(&console_lock, flags);
    8.22      __putstr("\n****************************************\n");
     9.1 --- a/xen/drivers/char/serial.c	Thu Jul 15 15:54:53 2004 +0000
     9.2 +++ b/xen/drivers/char/serial.c	Wed Jul 28 15:08:31 2004 +0000
     9.3 @@ -420,6 +420,30 @@ static int byte_matches(int handle, unsi
     9.4      return 0;
     9.5  }
     9.6  
     9.7 +unsigned char __serial_getc(int handle)
     9.8 +{
     9.9 +    uart_t *uart = &com[handle & SERHND_IDX];
    9.10 +    unsigned char c;
    9.11 +
    9.12 +    /* disable_irq() may have raced execution of uart_rx(). */
    9.13 +    while ( uart->rxbufp != uart->rxbufc )
    9.14 +    {
    9.15 +        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
    9.16 +        if ( byte_matches(handle, &c) )
    9.17 +	  return c;
    9.18 +    }
    9.19 +
    9.20 +    /* We now wait for the UART to receive a suitable character. */
    9.21 +    do {
    9.22 +        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
    9.23 +            barrier();
    9.24 +        c = inb(uart->io_base + RBR);
    9.25 +    }
    9.26 +    while ( !byte_matches(handle, &c) );
    9.27 +
    9.28 +    return c;
    9.29 +}
    9.30 +
    9.31  unsigned char serial_getc(int handle)
    9.32  {
    9.33      uart_t *uart = &com[handle & SERHND_IDX];
    9.34 @@ -434,26 +458,11 @@ unsigned char serial_getc(int handle)
    9.35          if ( byte_matches(handle, &c) )
    9.36              goto out;
    9.37      }
    9.38 -    
    9.39 +
    9.40      disable_irq(uart->irq);
    9.41 -    
    9.42 -    /* disable_irq() may have raced execution of uart_rx(). */
    9.43 -    while ( uart->rxbufp != uart->rxbufc )
    9.44 -    {
    9.45 -        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
    9.46 -        if ( byte_matches(handle, &c) )
    9.47 -            goto enable_and_out;
    9.48 -    }
    9.49  
    9.50 -    /* We now wait for the UART to receive a suitable character. */
    9.51 -    do {
    9.52 -        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
    9.53 -            barrier();
    9.54 -        c = inb(uart->io_base + RBR);
    9.55 -    }
    9.56 -    while ( !byte_matches(handle, &c) );
    9.57 -    
    9.58 - enable_and_out:
    9.59 +    c = __serial_getc(handle);
    9.60 +
    9.61      enable_irq(uart->irq);
    9.62   out:
    9.63      spin_unlock_irqrestore(&uart->lock, flags);