ia64/xen-unstable

annotate xen/common/gdbstub.c @ 9117:ec7802acc8c9

Fix up some issues I found when porting PPC to the new common gdb stub code:
- cosmetic changes in the messages printed
- 'flags' must always be unsigned long.
- explicitly calling initialize_gdb() is not difficult. For x86 and ia64 I
placed this call immediately before do_initcalls(), since that's where it's
being called from now so we know it's safe. Architecture people can move it
earlier as appropriate.
- I don't understand all these ASSERT(!local_irq_is_enabled()) statements,
sometimes bracketing a single call like receive_command(). How exactly would
receive_command() manage to re-enable irqs? Also, a failing ASSERT would just
call into the stub again anways...
- initialize_gdb() was overcomplicated. serial_parse_handle() already handles
the parsing for us, and there's no need to panic there.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Mar 03 10:53:58 2006 +0100 (2006-03-03)
parents 1b839e1b1de1
children 57a905038907
rev   line source
kaf24@8607 1 /*
kaf24@8607 2 * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
kaf24@8607 3 * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp>
kaf24@8607 4 * VA Linux Systems Japan. K.K.
kaf24@8607 5 *
kaf24@8607 6 * gdbstub arch neutral part
kaf24@8607 7 * Based on x86 cdb (xen/arch/x86/cdb.c) and ppc gdbstub(xen/common/gdbstub.c)
kaf24@8607 8 * But extensively modified.
kaf24@8607 9 *
kaf24@8607 10 * This program is free software; you can redistribute it and/or modify
kaf24@8607 11 * it under the terms of the GNU General Public License as published by
kaf24@8607 12 * the Free Software Foundation; either version 2 of the License, or
kaf24@8607 13 * (at your option) any later version.
kaf24@8607 14 *
kaf24@8607 15 * This program is distributed in the hope that it will be useful,
kaf24@8607 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@8607 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@8607 18 * GNU General Public License for more details.
kaf24@8607 19 *
kaf24@8607 20 * You should have received a copy of the GNU General Public License
kaf24@8607 21 * along with this program; if not, write to the Free Software
kaf24@8607 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@8607 23 */
kaf24@8607 24
kaf24@8607 25 /*
kaf24@8607 26 * gdbstub: implements the architecture independant parts of the
kaf24@8607 27 * gdb remote protocol.
kaf24@8607 28 */
kaf24@8607 29
kaf24@8607 30 /* We try to avoid assuming much about what the rest of the system is
kaf24@8607 31 doing. In particular, dynamic memory allocation is out of the
kaf24@8607 32 question. */
kaf24@8607 33
kaf24@8607 34 /* Resuming after we've stopped used to work, but more through luck
kaf24@8607 35 than any actual intention. It doesn't at the moment. */
kaf24@8607 36
kaf24@8607 37 #include <xen/lib.h>
kaf24@8607 38 #include <asm/uaccess.h>
kaf24@8607 39 #include <xen/spinlock.h>
kaf24@8607 40 #include <xen/serial.h>
kaf24@8607 41 #include <xen/irq.h>
kaf24@8607 42 #include <asm/debugger.h>
kaf24@8607 43 #include <xen/init.h>
kaf24@8607 44 #include <xen/smp.h>
kaf24@8607 45 #include <xen/console.h>
kaf24@8607 46
kaf24@8607 47 /* Printk isn't particularly safe just after we've trapped to the
kaf24@8607 48 debugger. so avoid it. */
kaf24@8607 49 #define dbg_printk(...)
kaf24@8607 50 /*#define dbg_printk(...) printk(__VA_ARGS__)*/
kaf24@8607 51
kaf24@8607 52 #define GDB_RETRY_MAX 10
kaf24@8607 53
kaf24@8607 54 static char opt_gdb[30] = "none";
kaf24@8607 55 string_param("gdb", opt_gdb);
kaf24@8607 56
kaf24@8607 57 /* value <-> char (de)serialzers */
kaf24@8607 58 char
kaf24@8607 59 hex2char(unsigned long x)
kaf24@8607 60 {
kaf24@8607 61 const char array[] = "0123456789abcdef";
kaf24@8607 62
kaf24@8607 63 return array[x & 15];
kaf24@8607 64 }
kaf24@8607 65
kaf24@8607 66 int
kaf24@8607 67 char2hex(unsigned char c)
kaf24@8607 68 {
kaf24@8607 69 if ( (c >= '0') && (c <= '9') )
kaf24@8607 70 return c - '0';
kaf24@8607 71 else if ( (c >= 'a') && (c <= 'f') )
kaf24@8607 72 return c - 'a' + 10;
kaf24@8607 73 else if ( (c >= 'A') && (c <= 'F') )
kaf24@8607 74 return c - 'A' + 10;
kaf24@8607 75 else
kaf24@8607 76 BUG();
kaf24@8607 77 return -1;
kaf24@8607 78 }
kaf24@8607 79
kaf24@8607 80 char
kaf24@8607 81 str2hex(const char *str)
kaf24@8607 82 {
kaf24@8607 83 return (char2hex(str[0]) << 4) | char2hex(str[1]);
kaf24@8607 84 }
kaf24@8607 85
kaf24@8607 86 unsigned long
kaf24@8607 87 str2ulong(const char *str, unsigned long bytes)
kaf24@8607 88 {
kaf24@8607 89 unsigned long x = 0;
kaf24@8607 90 unsigned long i = 0;
kaf24@8607 91
kaf24@8607 92 while ( *str && (i < (bytes * 2)) )
kaf24@8607 93 {
kaf24@8607 94 x <<= 4;
kaf24@8607 95 x += char2hex(*str);
kaf24@8607 96 ++str;
kaf24@8607 97 ++i;
kaf24@8607 98 }
kaf24@8607 99
kaf24@8607 100 return x;
kaf24@8607 101 }
kaf24@8607 102
kaf24@8607 103 /* gdb io wrappers */
kaf24@8607 104 static signed long
kaf24@8607 105 gdb_io_write(const char *buf, unsigned long len, struct gdb_context *ctx)
kaf24@8607 106 {
kaf24@8607 107 int i;
kaf24@8607 108 for ( i = 0; i < len; i++ )
kaf24@8607 109 serial_putc(ctx->serhnd, buf[i]);
kaf24@8607 110 return i;
kaf24@8607 111 }
kaf24@8607 112
kaf24@8607 113 static int
kaf24@8607 114 gdb_io_write_char(u8 data, struct gdb_context *ctx)
kaf24@8607 115 {
kaf24@8607 116 return gdb_io_write((char*)&data, 1, ctx);
kaf24@8607 117 }
kaf24@8607 118
kaf24@8607 119 static unsigned char
kaf24@8607 120 gdb_io_read(struct gdb_context *ctx)
kaf24@8607 121 {
kaf24@8607 122 return serial_getc(ctx->serhnd);
kaf24@8607 123 }
kaf24@8607 124
kaf24@8607 125 /* Receive a command. Returns -1 on csum error, 0 otherwise. */
kaf24@8607 126 /* Does not acknowledge. */
kaf24@8607 127 static int
kaf24@8607 128 attempt_receive_packet(struct gdb_context *ctx)
kaf24@8607 129 {
kaf24@8607 130 u8 csum;
kaf24@8607 131 u8 received_csum;
kaf24@8607 132 u8 ch;
kaf24@8607 133
kaf24@8607 134 /* Skip over everything up to the first '$' */
kaf24@8607 135 while ( (ch = gdb_io_read(ctx)) != '$' )
kaf24@8607 136 continue;
kaf24@8607 137
kaf24@8607 138 csum = 0;
kaf24@8607 139 for ( ctx->in_bytes = 0;
kaf24@8607 140 ctx->in_bytes < sizeof(ctx->in_buf);
kaf24@8607 141 ctx->in_bytes++ )
kaf24@8607 142 {
kaf24@8607 143 ch = gdb_io_read(ctx);
kaf24@8607 144 if ( ch == '#' )
kaf24@8607 145 break;
kaf24@8607 146 ctx->in_buf[ctx->in_bytes] = ch;
kaf24@8607 147 csum += ch;
kaf24@8607 148 }
kaf24@8607 149
kaf24@8607 150 if ( ctx->in_bytes == sizeof(ctx->in_buf) )
kaf24@8607 151 {
kaf24@8607 152 dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
kaf24@8607 153 return -1;
kaf24@8607 154 }
kaf24@8607 155
kaf24@8607 156 ctx->in_buf[ctx->in_bytes] = '\0';
kaf24@8607 157 received_csum = char2hex(gdb_io_read(ctx)) * 16 +
kaf24@8607 158 char2hex(gdb_io_read(ctx));
kaf24@8607 159
kaf24@8607 160 return (received_csum == csum) ? 0 : -1;
kaf24@8607 161 }
kaf24@8607 162
kaf24@8607 163 /* Receive a command, discarding up to ten packets with csum
kaf24@8607 164 * errors. Acknowledges all received packets. */
kaf24@8607 165 static int
kaf24@8607 166 receive_command(struct gdb_context *ctx)
kaf24@8607 167 {
kaf24@8607 168 int r, count = 0;
kaf24@8607 169
kaf24@8607 170 count = 0;
kaf24@8607 171 do {
kaf24@8607 172 r = attempt_receive_packet(ctx);
kaf24@8607 173 gdb_io_write_char((r < 0) ? '-' : '+', ctx);
kaf24@8607 174 count++;
kaf24@8607 175 } while ( (r < 0) && (count < GDB_RETRY_MAX) );
kaf24@8607 176
kaf24@8607 177 return r;
kaf24@8607 178 }
kaf24@8607 179
kaf24@8607 180 /* routines to send reply packets */
kaf24@8607 181
kaf24@8607 182 static void
kaf24@8607 183 gdb_start_packet(struct gdb_context *ctx)
kaf24@8607 184 {
kaf24@8607 185 ctx->out_buf[0] = '$';
kaf24@8607 186 ctx->out_offset = 1;
kaf24@8607 187 ctx->out_csum = 0;
kaf24@8607 188 }
kaf24@8607 189
kaf24@8607 190 static void
kaf24@8607 191 gdb_write_to_packet_char(u8 data, struct gdb_context *ctx)
kaf24@8607 192 {
kaf24@8607 193 ctx->out_csum += data;
kaf24@8607 194 ctx->out_buf[ctx->out_offset] = data;
kaf24@8607 195 ctx->out_offset++;
kaf24@8607 196 }
kaf24@8607 197
kaf24@8607 198 void
kaf24@8607 199 gdb_write_to_packet(const char *buf, int count, struct gdb_context *ctx)
kaf24@8607 200 {
kaf24@8607 201 int x;
kaf24@8607 202 for ( x = 0; x < count; x++ )
kaf24@8607 203 gdb_write_to_packet_char(buf[x], ctx);
kaf24@8607 204 }
kaf24@8607 205
kaf24@8607 206 void
kaf24@8607 207 gdb_write_to_packet_str(const char *buf, struct gdb_context *ctx)
kaf24@8607 208 {
kaf24@8607 209 gdb_write_to_packet(buf, strlen(buf), ctx);
kaf24@8607 210 }
kaf24@8607 211
kaf24@8607 212 void
kaf24@8607 213 gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
kaf24@8607 214 {
kaf24@8607 215 char buf[sizeof(unsigned long) * 2 + 1];
kaf24@8607 216 int i = sizeof(unsigned long) * 2;
kaf24@8607 217 int width = int_size * 2;
kaf24@8607 218
kaf24@8607 219 buf[sizeof(unsigned long) * 2] = 0;
kaf24@8607 220
kaf24@8607 221 switch ( int_size )
kaf24@8607 222 {
kaf24@8607 223 case sizeof(u8):
kaf24@8607 224 case sizeof(u16):
kaf24@8607 225 case sizeof(u32):
kaf24@8607 226 case sizeof(u64):
kaf24@8607 227 break;
kaf24@8607 228 default:
kaf24@8607 229 dbg_printk("WARNING: %s x: 0x%lx int_size: %d\n",
kaf24@8607 230 __func__, x, int_size);
kaf24@8607 231 break;
kaf24@8607 232 }
kaf24@8607 233
kaf24@8607 234 do {
kaf24@8607 235 buf[--i] = hex2char(x & 15);
kaf24@8607 236 x >>= 4;
kaf24@8607 237 } while ( x );
kaf24@8607 238
kaf24@8607 239 while ( (i + width) > (sizeof(unsigned long) * 2) )
kaf24@8607 240 buf[--i] = '0';
kaf24@8607 241
kaf24@8607 242 gdb_write_to_packet(&buf[i], width, ctx);
kaf24@8607 243 }
kaf24@8607 244
kaf24@8607 245 static int
kaf24@8607 246 gdb_check_ack(struct gdb_context *ctx)
kaf24@8607 247 {
kaf24@8607 248 u8 c = gdb_io_read(ctx);
kaf24@8607 249
kaf24@8607 250 switch ( c )
kaf24@8607 251 {
kaf24@8607 252 case '+':
kaf24@8607 253 return 1;
kaf24@8607 254 case '-':
kaf24@8607 255 return 0;
kaf24@8607 256 default:
kaf24@8607 257 printk("Bad ack: %c\n", c);
kaf24@8607 258 return 0;
kaf24@8607 259 }
kaf24@8607 260 }
kaf24@8607 261
kaf24@8607 262 /* Return 0 if the reply was successfully received, !0 otherwise. */
kaf24@8607 263 void
kaf24@8607 264 gdb_send_packet(struct gdb_context *ctx)
kaf24@8607 265 {
kaf24@8607 266 char buf[3];
kaf24@8607 267 int count;
kaf24@8607 268
kaf24@8607 269 sprintf(buf, "%.02x\n", ctx->out_csum);
kaf24@8607 270
kaf24@8607 271 gdb_write_to_packet_char('#', ctx);
kaf24@8607 272 gdb_write_to_packet(buf, 2, ctx);
kaf24@8607 273
kaf24@8607 274 count = 0;
kaf24@8607 275 do {
kaf24@8607 276 gdb_io_write(ctx->out_buf, ctx->out_offset, ctx);
kaf24@8607 277 } while ( !gdb_check_ack(ctx) && (count++ < GDB_RETRY_MAX) );
kaf24@8607 278
kaf24@8607 279 if ( count == GDB_RETRY_MAX )
kaf24@8607 280 dbg_printk("WARNING: %s reached max retry %d\n",
kaf24@8607 281 __func__, GDB_RETRY_MAX);
kaf24@8607 282 }
kaf24@8607 283
kaf24@8607 284 void
kaf24@8607 285 gdb_send_reply(const char *buf, struct gdb_context *ctx)
kaf24@8607 286 {
kaf24@8607 287 gdb_start_packet(ctx);
kaf24@8607 288 gdb_write_to_packet_str(buf, ctx);
kaf24@8607 289 gdb_send_packet(ctx);
kaf24@8607 290 }
kaf24@8607 291
kaf24@8607 292 /* arch neutral command handlers */
kaf24@8607 293
kaf24@8607 294 static void
kaf24@8607 295 gdb_cmd_signum(struct gdb_context *ctx)
kaf24@8607 296 {
kaf24@8607 297 gdb_write_to_packet_char('S', ctx);
kaf24@8607 298 gdb_write_to_packet_hex(ctx->signum, sizeof(ctx->signum), ctx);
kaf24@8607 299 gdb_send_packet(ctx);
kaf24@8607 300 }
kaf24@8607 301
kaf24@8607 302 static void
kaf24@8607 303 gdb_cmd_read_mem(unsigned long addr, unsigned long length,
kaf24@8607 304 struct gdb_context *ctx)
kaf24@8607 305 {
kaf24@8607 306 int x, r;
kaf24@8607 307 unsigned char val;
kaf24@8607 308
kaf24@8607 309 dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
kaf24@8607 310 length);
kaf24@8607 311
kaf24@8607 312 for ( x = 0; x < length; x++ )
kaf24@8607 313 {
kaf24@8607 314 r = gdb_arch_copy_from_user(&val, (void *)(addr + x), 1);
kaf24@8607 315 if ( r != 0 )
kaf24@8607 316 {
kaf24@8607 317 dbg_printk("Error reading from %lx.\n", addr + x);
kaf24@8607 318 break;
kaf24@8607 319 }
kaf24@8607 320 gdb_write_to_packet_hex(val, sizeof(val), ctx);
kaf24@8607 321 }
kaf24@8607 322
kaf24@8607 323 if ( x == 0 )
kaf24@8607 324 gdb_write_to_packet_str("E05", ctx);
kaf24@8607 325
kaf24@8607 326 dbg_printk("Read done.\n");
kaf24@8607 327
kaf24@8607 328 gdb_send_packet(ctx);
kaf24@8607 329 }
kaf24@8607 330
kaf24@8607 331 static void
kaf24@8607 332 gdb_cmd_write_mem(unsigned long addr, unsigned long length,
kaf24@8607 333 const char *buf, struct gdb_context *ctx)
kaf24@8607 334 {
kaf24@8607 335 int x, r;
kaf24@8607 336 unsigned char val;
kaf24@8607 337
kaf24@8607 338 dbg_printk("Memory write starting at %lx, length %lx.\n", addr, length);
kaf24@8607 339
kaf24@8607 340 for ( x = 0; x < length; x++, addr++, buf += 2 )
kaf24@8607 341 {
kaf24@8607 342 val = str2ulong(buf, sizeof(val));
kaf24@8607 343 r = gdb_arch_copy_to_user((void*)addr, (void*)&val, 1);
kaf24@8607 344 if ( r != 0 )
kaf24@8607 345 {
kaf24@8607 346 dbg_printk("Error writing to %lx.\n", addr);
kaf24@8607 347 break;
kaf24@8607 348 }
kaf24@8607 349 }
kaf24@8607 350
kaf24@8607 351 gdb_write_to_packet_str((x != length) ? "OK" : "E11", ctx);
kaf24@8607 352
kaf24@8607 353 dbg_printk("Write done.\n");
kaf24@8607 354
kaf24@8607 355 gdb_send_packet(ctx);
kaf24@8607 356 }
kaf24@8607 357
kaf24@8607 358 /* command dispatcher */
kaf24@8607 359 static int
kaf24@8607 360 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
kaf24@8607 361 {
kaf24@8607 362 char *ptr;
kaf24@8607 363 unsigned long addr, length;
kaf24@8607 364 int resume = 0;
kaf24@8607 365
kaf24@8607 366 /* XXX check ctx->in_bytes >= 2 or similar. */
kaf24@8607 367
kaf24@8607 368 gdb_start_packet(ctx);
kaf24@8607 369 switch ( ctx->in_buf[0] )
kaf24@8607 370 {
kaf24@8607 371 case '?': /* query signal number */
kaf24@8607 372 gdb_cmd_signum(ctx);
kaf24@8607 373 break;
kaf24@8607 374 case 'H': /* thread operations */
kaf24@8607 375 gdb_send_reply("OK", ctx);
kaf24@8607 376 break;
kaf24@8607 377 case 'g': /* Read registers */
kaf24@8607 378 gdb_arch_read_reg_array(regs, ctx);
kaf24@8607 379 break;
kaf24@8607 380 case 'G': /* Write registers */
kaf24@8607 381 gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx);
kaf24@8607 382 break;
kaf24@8607 383 case 'm': /* Read memory */
kaf24@8607 384 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 385 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8607 386 {
kaf24@8607 387 gdb_send_reply("E03", ctx);
kaf24@8607 388 return 0;
kaf24@8607 389 }
kaf24@8607 390 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@8607 391 if ( ptr[0] != 0 )
kaf24@8607 392 {
kaf24@8607 393 gdb_send_reply("E04", ctx);
kaf24@8607 394 return 0;
kaf24@8607 395 }
kaf24@8607 396 gdb_cmd_read_mem(addr, length, ctx);
kaf24@8607 397 break;
kaf24@8607 398 case 'M': /* Write memory */
kaf24@8607 399 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 400 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ':') )
kaf24@8607 401 {
kaf24@8607 402 gdb_send_reply("E03", ctx);
kaf24@8607 403 return 0;
kaf24@8607 404 }
kaf24@8607 405 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@8607 406 gdb_cmd_write_mem(addr, length, ptr, ctx);
kaf24@8607 407 break;
kaf24@8607 408 case 'p': /* read register */
kaf24@8607 409 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 410 if ( ptr == (ctx->in_buf + 1) )
kaf24@8607 411 {
kaf24@8607 412 gdb_send_reply("E03", ctx);
kaf24@8607 413 return 0;
kaf24@8607 414 }
kaf24@8607 415 if ( ptr[0] != 0 )
kaf24@8607 416 {
kaf24@8607 417 gdb_send_reply("E04", ctx);
kaf24@8607 418 return 0;
kaf24@8607 419 }
kaf24@8607 420 gdb_arch_read_reg(addr, regs, ctx);
kaf24@8607 421 break;
kaf24@8607 422 case 'Z': /* We need to claim to support these or gdb
kaf24@8607 423 won't let you continue the process. */
kaf24@8607 424 case 'z':
kaf24@8607 425 gdb_send_reply("OK", ctx);
kaf24@8607 426 break;
kaf24@8607 427
kaf24@8607 428 case 'D':
kaf24@8607 429 ctx->currently_attached = 0;
kaf24@8607 430 gdb_send_reply("OK", ctx);
kaf24@8607 431 /* fall through */
kaf24@8607 432 case 'k':
kaf24@8607 433 ctx->connected = 0;
kaf24@8607 434 /* fall through */
kaf24@8607 435 case 's': /* Single step */
kaf24@8607 436 case 'c': /* Resume at current address */
kaf24@8607 437 {
kaf24@8607 438 unsigned long addr = ~((unsigned long)0);
kaf24@8607 439 unsigned long type = GDB_CONTINUE;
kaf24@8607 440 if ( ctx->in_buf[0] == 's' )
kaf24@8607 441 type = GDB_STEP;
kaf24@8607 442 if ( ((ctx->in_buf[0] == 's') || (ctx->in_buf[0] == 'c')) &&
kaf24@8607 443 ctx->in_buf[1] )
kaf24@8607 444 addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long));
kaf24@8607 445 if ( ctx->in_buf[0] != 'D' )
kaf24@8607 446 ctx->currently_attached = 1;
kaf24@8607 447 resume = 1;
kaf24@8607 448 gdb_arch_resume(regs, addr, type, ctx);
kaf24@8607 449 break;
kaf24@8607 450 }
kaf24@8607 451
kaf24@8607 452 default:
kaf24@8607 453 gdb_send_reply("", ctx);
kaf24@8607 454 break;
kaf24@8607 455 }
kaf24@8607 456 return resume;
kaf24@8607 457 }
kaf24@8607 458
kaf24@8607 459 static struct gdb_context
kaf24@8607 460 __gdb_ctx = {
kaf24@8607 461 .serhnd = -1,
kaf24@8607 462 .currently_attached = 0,
kaf24@8607 463 .running = ATOMIC_INIT(1),
kaf24@8607 464 .connected = 0,
kaf24@8607 465 .signum = 1,
kaf24@8607 466 .in_bytes = 0,
kaf24@8607 467 .out_offset = 0,
kaf24@8607 468 .out_csum = 0,
kaf24@8607 469 };
kaf24@8607 470 static struct gdb_context *gdb_ctx = &__gdb_ctx;
kaf24@8607 471
kaf24@8607 472 /* trap handler: main entry point */
kaf24@8607 473 int
kaf24@8607 474 __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
kaf24@8607 475 {
kaf24@8607 476 int resume = 0;
kaf24@8607 477 int r;
kaf24@9117 478 unsigned long flags;
kaf24@8607 479
kaf24@8607 480 if ( gdb_ctx->serhnd < 0 )
kaf24@8607 481 {
kaf24@8607 482 dbg_printk("Debugger not ready yet.\n");
kaf24@8607 483 return 0;
kaf24@8607 484 }
kaf24@8607 485
kaf24@8607 486 /* We rely on our caller to ensure we're only on one processor
kaf24@8607 487 * at a time... We should probably panic here, but given that
kaf24@8607 488 * we're a debugger we should probably be a little tolerant of
kaf24@8607 489 * things going wrong. */
kaf24@8607 490 /* We don't want to use a spin lock here, because we're doing
kaf24@8607 491 two distinct things:
kaf24@8607 492
kaf24@8607 493 1 -- we don't want to run on more than one processor at a time,
kaf24@8607 494 and
kaf24@8607 495 2 -- we want to do something sensible if we re-enter ourselves.
kaf24@8607 496
kaf24@8607 497 Spin locks are good for 1, but useless for 2. */
kaf24@8607 498 if ( !atomic_dec_and_test(&gdb_ctx->running) )
kaf24@8607 499 {
kaf24@8607 500 printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n");
kaf24@8607 501 atomic_inc(&gdb_ctx->running);
kaf24@8607 502 return 0;
kaf24@8607 503 }
kaf24@8607 504
kaf24@8607 505 if ( !gdb_ctx->connected )
kaf24@8607 506 {
kaf24@9117 507 printk("GDB connection activated.\n");
kaf24@8607 508 gdb_arch_print_state(regs);
kaf24@8607 509 gdb_ctx->connected = 1;
kaf24@8607 510 }
kaf24@8607 511
kaf24@8607 512 smp_send_stop();
kaf24@8607 513
kaf24@8607 514 /* Try to make things a little more stable by disabling
kaf24@8607 515 interrupts while we're here. */
kaf24@8607 516 local_irq_save(flags);
kaf24@8607 517
kaf24@8607 518 watchdog_disable();
kaf24@8607 519 console_start_sync();
kaf24@8607 520
kaf24@8607 521 /* Shouldn't really do this, but otherwise we stop for no
kaf24@8607 522 obvious reason, which is Bad */
kaf24@9117 523 printk("Waiting for GDB to attach...\n");
kaf24@8607 524
kaf24@8607 525 gdb_arch_enter(regs);
kaf24@8607 526 gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
kaf24@8607 527 /* If gdb is already attached, tell it we've stopped again. */
kaf24@8607 528 if ( gdb_ctx->currently_attached )
kaf24@8607 529 {
kaf24@8607 530 gdb_start_packet(gdb_ctx);
kaf24@8607 531 gdb_cmd_signum(gdb_ctx);
kaf24@8607 532 }
kaf24@8607 533
kaf24@8607 534 while ( resume == 0 )
kaf24@8607 535 {
kaf24@8607 536 r = receive_command(gdb_ctx);
kaf24@8607 537 if ( r < 0 )
kaf24@8607 538 {
kaf24@8607 539 dbg_printk("GDB disappeared, trying to resume Xen...\n");
kaf24@8607 540 resume = 1;
kaf24@8607 541 }
kaf24@8607 542 else
kaf24@8607 543 {
kaf24@8607 544 resume = process_command(regs, gdb_ctx);
kaf24@8607 545 }
kaf24@8607 546 }
kaf24@8607 547
kaf24@8607 548 gdb_arch_exit(regs);
kaf24@8607 549 console_end_sync();
kaf24@8607 550 watchdog_enable();
kaf24@8607 551 atomic_inc(&gdb_ctx->running);
kaf24@8607 552
kaf24@8607 553 local_irq_restore(flags);
kaf24@8607 554
kaf24@8607 555 return 0;
kaf24@8607 556 }
kaf24@8607 557
kaf24@9117 558 void
kaf24@9117 559 initialise_gdb(void)
kaf24@8607 560 {
kaf24@8607 561 gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
kaf24@9117 562 if ( gdb_ctx->serhnd != -1 )
kaf24@9117 563 printk("GDB stub initialised.\n");
kaf24@8607 564 }
kaf24@8607 565
kaf24@8607 566 /*
kaf24@8607 567 * Local variables:
kaf24@8607 568 * mode: C
kaf24@8607 569 * c-set-style: "BSD"
kaf24@8607 570 * c-basic-offset: 4
kaf24@8607 571 * tab-width: 4
kaf24@8607 572 * End:
kaf24@8607 573 */