ia64/xen-unstable

annotate xen/common/gdbstub.c @ 16599:514d450ad729

Fix gdb debugging of hypervisor.

This patch:
* enables the gdbstubs to properly access hypervisor memory;
* prevents an assertion failure in __spurious_page_fault's call
to map_domain_page if such accesses fail, by testing in_irq();
* prints some additional helpful messages;
* fixes the endianness of register transfers from the gdbstubs
so that gdb is much less confused.
* fixes the documentation in docs/misc/crashdb.txt

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 12 11:27:15 2007 +0000 (2007-12-12)
parents 759d924af6d8
children 9bf8b152df9f
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 <xen/spinlock.h>
kaf24@8607 39 #include <xen/serial.h>
kaf24@8607 40 #include <xen/irq.h>
kaf24@8607 41 #include <asm/debugger.h>
kaf24@8607 42 #include <xen/init.h>
kaf24@8607 43 #include <xen/smp.h>
kaf24@8607 44 #include <xen/console.h>
hollisb@12983 45 #include <xen/errno.h>
keir@16599 46 #include <asm/byteorder.h>
kaf24@8607 47
kaf24@8607 48 /* Printk isn't particularly safe just after we've trapped to the
kaf24@8607 49 debugger. so avoid it. */
kaf24@8607 50 #define dbg_printk(...)
kaf24@8607 51 /*#define dbg_printk(...) printk(__VA_ARGS__)*/
kaf24@8607 52
kaf24@8607 53 #define GDB_RETRY_MAX 10
kaf24@8607 54
kaf24@8607 55 static char opt_gdb[30] = "none";
kaf24@8607 56 string_param("gdb", opt_gdb);
kaf24@8607 57
kaf24@11627 58 static void gdbstub_console_puts(const char *str);
kaf24@11627 59
kaf24@8607 60 /* value <-> char (de)serialzers */
kaf24@8607 61 char
kaf24@8607 62 hex2char(unsigned long x)
kaf24@8607 63 {
kaf24@8607 64 const char array[] = "0123456789abcdef";
kaf24@8607 65
kaf24@8607 66 return array[x & 15];
kaf24@8607 67 }
kaf24@8607 68
kaf24@8607 69 int
kaf24@8607 70 char2hex(unsigned char c)
kaf24@8607 71 {
kaf24@8607 72 if ( (c >= '0') && (c <= '9') )
kaf24@8607 73 return c - '0';
kaf24@8607 74 else if ( (c >= 'a') && (c <= 'f') )
kaf24@8607 75 return c - 'a' + 10;
kaf24@8607 76 else if ( (c >= 'A') && (c <= 'F') )
kaf24@8607 77 return c - 'A' + 10;
kaf24@8607 78 else
kaf24@8607 79 BUG();
kaf24@8607 80 return -1;
kaf24@8607 81 }
kaf24@8607 82
kaf24@8607 83 char
kaf24@8607 84 str2hex(const char *str)
kaf24@8607 85 {
kaf24@8607 86 return (char2hex(str[0]) << 4) | char2hex(str[1]);
kaf24@8607 87 }
kaf24@8607 88
kaf24@8607 89 unsigned long
kaf24@8607 90 str2ulong(const char *str, unsigned long bytes)
kaf24@8607 91 {
kaf24@8607 92 unsigned long x = 0;
kaf24@8607 93 unsigned long i = 0;
kaf24@8607 94
kaf24@8607 95 while ( *str && (i < (bytes * 2)) )
kaf24@8607 96 {
kaf24@8607 97 x <<= 4;
kaf24@8607 98 x += char2hex(*str);
kaf24@8607 99 ++str;
kaf24@8607 100 ++i;
kaf24@8607 101 }
kaf24@8607 102
kaf24@8607 103 return x;
kaf24@8607 104 }
kaf24@8607 105
kaf24@8607 106 /* gdb io wrappers */
kaf24@8607 107 static signed long
kaf24@8607 108 gdb_io_write(const char *buf, unsigned long len, struct gdb_context *ctx)
kaf24@8607 109 {
kaf24@8607 110 int i;
kaf24@8607 111 for ( i = 0; i < len; i++ )
kaf24@8607 112 serial_putc(ctx->serhnd, buf[i]);
kaf24@8607 113 return i;
kaf24@8607 114 }
kaf24@8607 115
kaf24@8607 116 static int
kaf24@8607 117 gdb_io_write_char(u8 data, struct gdb_context *ctx)
kaf24@8607 118 {
kaf24@8607 119 return gdb_io_write((char*)&data, 1, ctx);
kaf24@8607 120 }
kaf24@8607 121
kaf24@8607 122 static unsigned char
kaf24@8607 123 gdb_io_read(struct gdb_context *ctx)
kaf24@8607 124 {
kaf24@8607 125 return serial_getc(ctx->serhnd);
kaf24@8607 126 }
kaf24@8607 127
kaf24@8607 128 /* Receive a command. Returns -1 on csum error, 0 otherwise. */
kaf24@8607 129 /* Does not acknowledge. */
kaf24@8607 130 static int
kaf24@8607 131 attempt_receive_packet(struct gdb_context *ctx)
kaf24@8607 132 {
kaf24@8607 133 u8 csum;
kaf24@8607 134 u8 received_csum;
kaf24@8607 135 u8 ch;
kaf24@8607 136
kaf24@8607 137 /* Skip over everything up to the first '$' */
kaf24@8607 138 while ( (ch = gdb_io_read(ctx)) != '$' )
kaf24@8607 139 continue;
kaf24@8607 140
kaf24@8607 141 csum = 0;
kaf24@8607 142 for ( ctx->in_bytes = 0;
kaf24@8607 143 ctx->in_bytes < sizeof(ctx->in_buf);
kaf24@8607 144 ctx->in_bytes++ )
kaf24@8607 145 {
kaf24@8607 146 ch = gdb_io_read(ctx);
kaf24@8607 147 if ( ch == '#' )
kaf24@8607 148 break;
kaf24@8607 149 ctx->in_buf[ctx->in_bytes] = ch;
kaf24@8607 150 csum += ch;
kaf24@8607 151 }
kaf24@8607 152
kaf24@8607 153 if ( ctx->in_bytes == sizeof(ctx->in_buf) )
kaf24@8607 154 {
kaf24@8607 155 dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
kaf24@8607 156 return -1;
kaf24@8607 157 }
kaf24@8607 158
kaf24@8607 159 ctx->in_buf[ctx->in_bytes] = '\0';
kaf24@8607 160 received_csum = char2hex(gdb_io_read(ctx)) * 16 +
kaf24@8607 161 char2hex(gdb_io_read(ctx));
kaf24@8607 162
kaf24@8607 163 return (received_csum == csum) ? 0 : -1;
kaf24@8607 164 }
kaf24@8607 165
kaf24@8607 166 /* Receive a command, discarding up to ten packets with csum
kaf24@8607 167 * errors. Acknowledges all received packets. */
kaf24@8607 168 static int
kaf24@8607 169 receive_command(struct gdb_context *ctx)
kaf24@8607 170 {
kaf24@8607 171 int r, count = 0;
kaf24@8607 172
kaf24@8607 173 count = 0;
kaf24@8607 174 do {
kaf24@8607 175 r = attempt_receive_packet(ctx);
kaf24@8607 176 gdb_io_write_char((r < 0) ? '-' : '+', ctx);
kaf24@8607 177 count++;
kaf24@8607 178 } while ( (r < 0) && (count < GDB_RETRY_MAX) );
kaf24@8607 179
kaf24@8607 180 return r;
kaf24@8607 181 }
kaf24@8607 182
kaf24@8607 183 /* routines to send reply packets */
kaf24@8607 184
kaf24@8607 185 static void
kaf24@8607 186 gdb_start_packet(struct gdb_context *ctx)
kaf24@8607 187 {
kaf24@8607 188 ctx->out_buf[0] = '$';
kaf24@8607 189 ctx->out_offset = 1;
kaf24@8607 190 ctx->out_csum = 0;
kaf24@8607 191 }
kaf24@8607 192
kaf24@8607 193 static void
kaf24@8607 194 gdb_write_to_packet_char(u8 data, struct gdb_context *ctx)
kaf24@8607 195 {
kaf24@8607 196 ctx->out_csum += data;
kaf24@8607 197 ctx->out_buf[ctx->out_offset] = data;
kaf24@8607 198 ctx->out_offset++;
kaf24@8607 199 }
kaf24@8607 200
kaf24@8607 201 void
kaf24@8607 202 gdb_write_to_packet(const char *buf, int count, struct gdb_context *ctx)
kaf24@8607 203 {
kaf24@8607 204 int x;
kaf24@8607 205 for ( x = 0; x < count; x++ )
kaf24@8607 206 gdb_write_to_packet_char(buf[x], ctx);
kaf24@8607 207 }
kaf24@8607 208
kaf24@8607 209 void
kaf24@8607 210 gdb_write_to_packet_str(const char *buf, struct gdb_context *ctx)
kaf24@8607 211 {
kaf24@8607 212 gdb_write_to_packet(buf, strlen(buf), ctx);
kaf24@8607 213 }
kaf24@8607 214
kaf24@8607 215 void
kaf24@8607 216 gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
kaf24@8607 217 {
kaf24@8607 218 char buf[sizeof(unsigned long) * 2 + 1];
keir@16599 219 int i, width = int_size * 2;
kaf24@8607 220
kaf24@8607 221 buf[sizeof(unsigned long) * 2] = 0;
kaf24@8607 222
kaf24@8607 223 switch ( int_size )
kaf24@8607 224 {
kaf24@8607 225 case sizeof(u8):
kaf24@8607 226 case sizeof(u16):
kaf24@8607 227 case sizeof(u32):
kaf24@8607 228 case sizeof(u64):
kaf24@8607 229 break;
kaf24@8607 230 default:
kaf24@8607 231 dbg_printk("WARNING: %s x: 0x%lx int_size: %d\n",
kaf24@8607 232 __func__, x, int_size);
kaf24@8607 233 break;
kaf24@8607 234 }
kaf24@8607 235
keir@16599 236 #ifdef __BIG_ENDIAN
keir@16599 237 i = sizeof(unsigned long) * 2
kaf24@8607 238 do {
kaf24@8607 239 buf[--i] = hex2char(x & 15);
kaf24@8607 240 x >>= 4;
kaf24@8607 241 } while ( x );
kaf24@8607 242
kaf24@8607 243 while ( (i + width) > (sizeof(unsigned long) * 2) )
kaf24@8607 244 buf[--i] = '0';
kaf24@8607 245
kaf24@8607 246 gdb_write_to_packet(&buf[i], width, ctx);
keir@16599 247 #elif defined(__LITTLE_ENDIAN)
keir@16599 248 i = 0;
keir@16599 249 while (i < width) {
keir@16599 250 buf[i++] = hex2char(x>>4);
keir@16599 251 buf[i++] = hex2char(x);
keir@16599 252 x >>= 8;
keir@16599 253 }
keir@16599 254 gdb_write_to_packet(buf, width, ctx);
keir@16599 255 #else
keir@16599 256 # error unknown endian
keir@16599 257 #endif
kaf24@8607 258 }
kaf24@8607 259
kaf24@8607 260 static int
kaf24@8607 261 gdb_check_ack(struct gdb_context *ctx)
kaf24@8607 262 {
kaf24@8607 263 u8 c = gdb_io_read(ctx);
kaf24@8607 264
kaf24@8607 265 switch ( c )
kaf24@8607 266 {
kaf24@8607 267 case '+':
kaf24@8607 268 return 1;
kaf24@8607 269 case '-':
kaf24@8607 270 return 0;
kaf24@8607 271 default:
kaf24@8607 272 printk("Bad ack: %c\n", c);
kaf24@8607 273 return 0;
kaf24@8607 274 }
kaf24@8607 275 }
kaf24@8607 276
kaf24@8607 277 /* Return 0 if the reply was successfully received, !0 otherwise. */
kaf24@8607 278 void
kaf24@8607 279 gdb_send_packet(struct gdb_context *ctx)
kaf24@8607 280 {
kaf24@8607 281 char buf[3];
kaf24@8607 282 int count;
kaf24@8607 283
kfraser@13685 284 snprintf(buf, sizeof(buf), "%.02x\n", ctx->out_csum);
kaf24@8607 285
kaf24@8607 286 gdb_write_to_packet_char('#', ctx);
kaf24@8607 287 gdb_write_to_packet(buf, 2, ctx);
kaf24@8607 288
kaf24@8607 289 count = 0;
kaf24@8607 290 do {
kaf24@8607 291 gdb_io_write(ctx->out_buf, ctx->out_offset, ctx);
kaf24@8607 292 } while ( !gdb_check_ack(ctx) && (count++ < GDB_RETRY_MAX) );
kaf24@8607 293
kaf24@8607 294 if ( count == GDB_RETRY_MAX )
kaf24@8607 295 dbg_printk("WARNING: %s reached max retry %d\n",
kaf24@8607 296 __func__, GDB_RETRY_MAX);
kaf24@8607 297 }
kaf24@8607 298
kaf24@8607 299 void
kaf24@8607 300 gdb_send_reply(const char *buf, struct gdb_context *ctx)
kaf24@8607 301 {
kaf24@8607 302 gdb_start_packet(ctx);
kaf24@8607 303 gdb_write_to_packet_str(buf, ctx);
kaf24@8607 304 gdb_send_packet(ctx);
kaf24@8607 305 }
kaf24@8607 306
kaf24@8607 307 /* arch neutral command handlers */
kaf24@8607 308
kaf24@8607 309 static void
kaf24@8607 310 gdb_cmd_signum(struct gdb_context *ctx)
kaf24@8607 311 {
kaf24@8607 312 gdb_write_to_packet_char('S', ctx);
kaf24@8607 313 gdb_write_to_packet_hex(ctx->signum, sizeof(ctx->signum), ctx);
kaf24@8607 314 gdb_send_packet(ctx);
kaf24@8607 315 }
kaf24@8607 316
kaf24@8607 317 static void
kaf24@8607 318 gdb_cmd_read_mem(unsigned long addr, unsigned long length,
kaf24@8607 319 struct gdb_context *ctx)
kaf24@8607 320 {
kaf24@8607 321 int x, r;
kaf24@8607 322 unsigned char val;
kaf24@8607 323
kaf24@8607 324 dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
kaf24@8607 325 length);
kaf24@8607 326
kaf24@8607 327 for ( x = 0; x < length; x++ )
kaf24@8607 328 {
kaf24@8607 329 r = gdb_arch_copy_from_user(&val, (void *)(addr + x), 1);
kaf24@8607 330 if ( r != 0 )
kaf24@8607 331 {
kaf24@8607 332 dbg_printk("Error reading from %lx.\n", addr + x);
kaf24@8607 333 break;
kaf24@8607 334 }
kaf24@8607 335 gdb_write_to_packet_hex(val, sizeof(val), ctx);
kaf24@8607 336 }
kaf24@8607 337
kaf24@8607 338 if ( x == 0 )
kaf24@8607 339 gdb_write_to_packet_str("E05", ctx);
kaf24@8607 340
kaf24@8607 341 dbg_printk("Read done.\n");
kaf24@8607 342
kaf24@8607 343 gdb_send_packet(ctx);
kaf24@8607 344 }
kaf24@8607 345
kaf24@8607 346 static void
kaf24@8607 347 gdb_cmd_write_mem(unsigned long addr, unsigned long length,
kaf24@8607 348 const char *buf, struct gdb_context *ctx)
kaf24@8607 349 {
kaf24@8607 350 int x, r;
kaf24@8607 351 unsigned char val;
kaf24@8607 352
kaf24@8607 353 dbg_printk("Memory write starting at %lx, length %lx.\n", addr, length);
kaf24@8607 354
kaf24@8607 355 for ( x = 0; x < length; x++, addr++, buf += 2 )
kaf24@8607 356 {
kaf24@8607 357 val = str2ulong(buf, sizeof(val));
kaf24@8607 358 r = gdb_arch_copy_to_user((void*)addr, (void*)&val, 1);
kaf24@8607 359 if ( r != 0 )
kaf24@8607 360 {
kaf24@8607 361 dbg_printk("Error writing to %lx.\n", addr);
kaf24@8607 362 break;
kaf24@8607 363 }
kaf24@8607 364 }
kaf24@8607 365
kaf24@9179 366 if (x == length)
kaf24@9179 367 gdb_write_to_packet_str("OK", ctx);
kaf24@9179 368 else
kaf24@9179 369 gdb_write_to_packet_str("E11", ctx);
kaf24@8607 370
kaf24@8607 371 dbg_printk("Write done.\n");
kaf24@8607 372
kaf24@8607 373 gdb_send_packet(ctx);
kaf24@8607 374 }
kaf24@8607 375
kfraser@11602 376 static void
kfraser@11602 377 gdbstub_attach(struct gdb_context *ctx)
kfraser@11602 378 {
kfraser@11602 379 if ( ctx->currently_attached )
kfraser@11602 380 return;
kfraser@11602 381 ctx->currently_attached = 1;
kfraser@11602 382 ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts);
kfraser@11602 383 }
kfraser@11602 384
kfraser@11602 385 static void
kfraser@11602 386 gdbstub_detach(struct gdb_context *ctx)
kfraser@11602 387 {
kfraser@11602 388 if ( !ctx->currently_attached )
kfraser@11602 389 return;
kfraser@11602 390 ctx->currently_attached = 0;
kfraser@11602 391 console_giveback(ctx->console_steal_id);
kfraser@11602 392 }
kfraser@11602 393
kaf24@8607 394 /* command dispatcher */
kaf24@8607 395 static int
kaf24@8607 396 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
kaf24@8607 397 {
kaf24@13172 398 const char *ptr;
kaf24@8607 399 unsigned long addr, length;
kaf24@8607 400 int resume = 0;
kaf24@8607 401
kaf24@8607 402 /* XXX check ctx->in_bytes >= 2 or similar. */
kaf24@8607 403
kaf24@8607 404 gdb_start_packet(ctx);
kaf24@8607 405 switch ( ctx->in_buf[0] )
kaf24@8607 406 {
kaf24@8607 407 case '?': /* query signal number */
kaf24@8607 408 gdb_cmd_signum(ctx);
kaf24@8607 409 break;
kaf24@8607 410 case 'H': /* thread operations */
kaf24@8607 411 gdb_send_reply("OK", ctx);
kaf24@8607 412 break;
kaf24@8607 413 case 'g': /* Read registers */
kaf24@8607 414 gdb_arch_read_reg_array(regs, ctx);
kaf24@8607 415 break;
kaf24@8607 416 case 'G': /* Write registers */
kaf24@8607 417 gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx);
kaf24@8607 418 break;
kaf24@8607 419 case 'm': /* Read memory */
kaf24@8607 420 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 421 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8607 422 {
kaf24@8607 423 gdb_send_reply("E03", ctx);
kaf24@8607 424 return 0;
kaf24@8607 425 }
kaf24@8607 426 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@8607 427 if ( ptr[0] != 0 )
kaf24@8607 428 {
kaf24@8607 429 gdb_send_reply("E04", ctx);
kaf24@8607 430 return 0;
kaf24@8607 431 }
kaf24@8607 432 gdb_cmd_read_mem(addr, length, ctx);
kaf24@8607 433 break;
kaf24@8607 434 case 'M': /* Write memory */
kaf24@8607 435 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@9179 436 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8607 437 {
kaf24@8607 438 gdb_send_reply("E03", ctx);
kaf24@8607 439 return 0;
kaf24@8607 440 }
kaf24@8607 441 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@9179 442 if ( ptr[0] != ':')
kaf24@9179 443 {
kaf24@9179 444 gdb_send_reply("E04", ctx);
kaf24@9179 445 return 0;
kaf24@9179 446 }
kaf24@9179 447 gdb_cmd_write_mem(addr, length, ptr + 1, ctx);
kaf24@8607 448 break;
kaf24@8607 449 case 'p': /* read register */
kaf24@8607 450 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 451 if ( ptr == (ctx->in_buf + 1) )
kaf24@8607 452 {
kaf24@8607 453 gdb_send_reply("E03", ctx);
kaf24@8607 454 return 0;
kaf24@8607 455 }
kaf24@8607 456 if ( ptr[0] != 0 )
kaf24@8607 457 {
kaf24@8607 458 gdb_send_reply("E04", ctx);
kaf24@8607 459 return 0;
kaf24@8607 460 }
kaf24@8607 461 gdb_arch_read_reg(addr, regs, ctx);
kaf24@8607 462 break;
kaf24@8607 463 case 'D':
kfraser@11602 464 gdbstub_detach(ctx);
kaf24@8607 465 gdb_send_reply("OK", ctx);
kaf24@8607 466 /* fall through */
kaf24@8607 467 case 'k':
kaf24@8607 468 ctx->connected = 0;
kaf24@8607 469 /* fall through */
kaf24@8607 470 case 's': /* Single step */
kaf24@8607 471 case 'c': /* Resume at current address */
kaf24@8607 472 {
kaf24@8607 473 unsigned long addr = ~((unsigned long)0);
kaf24@8607 474 unsigned long type = GDB_CONTINUE;
kaf24@8607 475 if ( ctx->in_buf[0] == 's' )
kaf24@8607 476 type = GDB_STEP;
kaf24@8607 477 if ( ((ctx->in_buf[0] == 's') || (ctx->in_buf[0] == 'c')) &&
kaf24@8607 478 ctx->in_buf[1] )
kaf24@8607 479 addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long));
kaf24@8607 480 if ( ctx->in_buf[0] != 'D' )
kfraser@11602 481 gdbstub_attach(ctx);
kaf24@8607 482 resume = 1;
kaf24@8607 483 gdb_arch_resume(regs, addr, type, ctx);
kaf24@8607 484 break;
kaf24@8607 485 }
kaf24@8607 486
kaf24@8607 487 default:
kaf24@8607 488 gdb_send_reply("", ctx);
kaf24@8607 489 break;
kaf24@8607 490 }
kaf24@8607 491 return resume;
kaf24@8607 492 }
kaf24@8607 493
kaf24@8607 494 static struct gdb_context
kaf24@8607 495 __gdb_ctx = {
kfraser@11602 496 .serhnd = -1,
kfraser@11602 497 .running = ATOMIC_INIT(1),
kfraser@11602 498 .signum = 1
kaf24@8607 499 };
kaf24@8607 500 static struct gdb_context *gdb_ctx = &__gdb_ctx;
kaf24@8607 501
kfraser@11602 502 static void
kfraser@11602 503 gdbstub_console_puts(const char *str)
kfraser@11602 504 {
kfraser@11602 505 const char *p;
kfraser@11602 506
kfraser@11602 507 gdb_start_packet(gdb_ctx);
kfraser@11602 508 gdb_write_to_packet_char('O', gdb_ctx);
kfraser@11602 509
kfraser@11602 510 for ( p = str; *p != '\0'; p++ )
kfraser@11602 511 {
kfraser@11602 512 gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx );
kfraser@11602 513 gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx );
kfraser@11602 514 }
kfraser@11602 515
kfraser@11602 516 gdb_send_packet(gdb_ctx);
kfraser@11602 517 }
kfraser@11602 518
kaf24@8607 519 /* trap handler: main entry point */
kaf24@8607 520 int
kaf24@8607 521 __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
kaf24@8607 522 {
kfraser@11649 523 int rc = 0;
kaf24@9117 524 unsigned long flags;
kaf24@8607 525
kaf24@8607 526 if ( gdb_ctx->serhnd < 0 )
kaf24@8607 527 {
keir@16599 528 printk("Debugging connection not set up.\n");
kfraser@11649 529 return -EBUSY;
kaf24@8607 530 }
kaf24@8607 531
kaf24@8607 532 /* We rely on our caller to ensure we're only on one processor
kaf24@8607 533 * at a time... We should probably panic here, but given that
kaf24@8607 534 * we're a debugger we should probably be a little tolerant of
kaf24@8607 535 * things going wrong. */
kaf24@8607 536 /* We don't want to use a spin lock here, because we're doing
kaf24@8607 537 two distinct things:
kaf24@8607 538
kaf24@8607 539 1 -- we don't want to run on more than one processor at a time,
kaf24@8607 540 and
kaf24@8607 541 2 -- we want to do something sensible if we re-enter ourselves.
kaf24@8607 542
kaf24@8607 543 Spin locks are good for 1, but useless for 2. */
kaf24@8607 544 if ( !atomic_dec_and_test(&gdb_ctx->running) )
kaf24@8607 545 {
kaf24@8607 546 printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n");
kaf24@8607 547 atomic_inc(&gdb_ctx->running);
kfraser@11649 548 return -EBUSY;
kaf24@8607 549 }
kaf24@8607 550
kaf24@8607 551 if ( !gdb_ctx->connected )
kaf24@8607 552 {
kaf24@9117 553 printk("GDB connection activated.\n");
kaf24@8607 554 gdb_arch_print_state(regs);
kaf24@8607 555 gdb_ctx->connected = 1;
kaf24@8607 556 }
kaf24@8607 557
kaf24@8607 558 smp_send_stop();
kaf24@8607 559
kaf24@8607 560 /* Try to make things a little more stable by disabling
kaf24@8607 561 interrupts while we're here. */
kaf24@8607 562 local_irq_save(flags);
kaf24@8607 563
kaf24@8607 564 watchdog_disable();
kaf24@8607 565 console_start_sync();
kaf24@8607 566
kaf24@8607 567 /* Shouldn't really do this, but otherwise we stop for no
kaf24@8607 568 obvious reason, which is Bad */
kaf24@9117 569 printk("Waiting for GDB to attach...\n");
kaf24@8607 570
kaf24@8607 571 gdb_arch_enter(regs);
kaf24@8607 572 gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
kfraser@11602 573
kaf24@8607 574 /* If gdb is already attached, tell it we've stopped again. */
kaf24@8607 575 if ( gdb_ctx->currently_attached )
kaf24@8607 576 {
kaf24@8607 577 gdb_start_packet(gdb_ctx);
kaf24@8607 578 gdb_cmd_signum(gdb_ctx);
kaf24@8607 579 }
kaf24@8607 580
kfraser@11649 581 do {
kfraser@11649 582 if ( receive_command(gdb_ctx) < 0 )
kaf24@8607 583 {
kfraser@11649 584 dbg_printk("Error in GDB session...\n");
kfraser@11649 585 rc = -EIO;
kfraser@11649 586 break;
kaf24@8607 587 }
kfraser@11649 588 } while ( process_command(regs, gdb_ctx) == 0 );
kaf24@8607 589
kaf24@8607 590 gdb_arch_exit(regs);
kaf24@8607 591 console_end_sync();
kaf24@8607 592 watchdog_enable();
kaf24@8607 593 atomic_inc(&gdb_ctx->running);
kaf24@8607 594
kaf24@8607 595 local_irq_restore(flags);
kaf24@8607 596
kfraser@11649 597 return rc;
kaf24@8607 598 }
kaf24@8607 599
keir@15082 600 void __init
kaf24@9117 601 initialise_gdb(void)
kaf24@8607 602 {
kaf24@8607 603 gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
kaf24@9117 604 if ( gdb_ctx->serhnd != -1 )
kaf24@9117 605 printk("GDB stub initialised.\n");
kaf24@9437 606 serial_start_sync(gdb_ctx->serhnd);
kaf24@8607 607 }
kaf24@8607 608
kaf24@8607 609 /*
kaf24@8607 610 * Local variables:
kaf24@8607 611 * mode: C
kaf24@8607 612 * c-set-style: "BSD"
kaf24@8607 613 * c-basic-offset: 4
kaf24@8607 614 * tab-width: 4
kaf24@8607 615 * End:
kaf24@8607 616 */