1/* 2 * arch/s390/kernel/gdb-stub.c 3 * 4 * S390 version 5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), 7 * 8 * Originally written by Glenn Engel, Lake Stevens Instrument Division 9 * 10 * Contributed by HP Systems 11 * 12 * Modified for SPARC by Stu Grossman, Cygnus Support. 13 * 14 * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse 15 * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> 16 * 17 * Copyright (C) 1995 Andreas Busse 18 */ 19 20/* 21 * To enable debugger support, two things need to happen. One, a 22 * call to set_debug_traps() is necessary in order to allow any breakpoints 23 * or error conditions to be properly intercepted and reported to gdb. 24 * Two, a breakpoint needs to be generated to begin communication. This 25 * is most easily accomplished by a call to breakpoint(). Breakpoint() 26 * simulates a breakpoint by executing a BREAK instruction. 27 * 28 * 29 * The following gdb commands are supported: 30 * 31 * command function Return value 32 * 33 * g return the value of the CPU registers hex data or ENN 34 * G set the value of the CPU registers OK or ENN 35 * 36 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN 37 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN 38 * 39 * c Resume at current address SNN ( signal NN) 40 * cAA..AA Continue at address AA..AA SNN 41 * 42 * s Step one instruction SNN 43 * sAA..AA Step one instruction from AA..AA SNN 44 * 45 * k kill 46 * 47 * ? What was the last sigval ? SNN (signal NN) 48 * 49 * 50 * All commands and responses are sent with a packet which includes a 51 * checksum. A packet consists of 52 * 53 * $<packet info>#<checksum>. 54 * 55 * where 56 * <packet info> :: <characters representing the command or response> 57 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> 58 * 59 * When a packet is received, it is first acknowledged with either '+' or '-'. 60 * '+' indicates a successful transfer. '-' indicates a failed transfer. 61 * 62 * Example: 63 * 64 * Host: Reply: 65 * $m0,10#2a +$00010203040506070809101112131415#42 66 * 67 */ 68 69#include <asm/gdb-stub.h> 70#include <linux/string.h> 71#include <linux/kernel.h> 72#include <linux/signal.h> 73#include <linux/sched.h> 74#include <linux/mm.h> 75#include <asm/pgtable.h> 76#include <asm/system.h> 77 78 79/* 80 * external low-level support routines 81 */ 82 83extern int putDebugChar(char c); /* write a single character */ 84extern char getDebugChar(void); /* read and return a single char */ 85extern void fltr_set_mem_err(void); 86extern void trap_low(void); 87 88/* 89 * breakpoint and test functions 90 */ 91extern void breakpoint(void); 92extern void breakinst(void); 93 94/* 95 * local prototypes 96 */ 97 98static void getpacket(char *buffer); 99static void putpacket(char *buffer); 100static int hex(unsigned char ch); 101static int hexToInt(char **ptr, int *intValue); 102static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); 103 104 105/* 106 * BUFMAX defines the maximum number of characters in inbound/outbound buffers 107 * at least NUMREGBYTES*2 are needed for register packets 108 */ 109#define BUFMAX 2048 110 111static char input_buffer[BUFMAX]; 112static char output_buffer[BUFMAX]; 113int gdb_stub_initialised = FALSE; 114static const char hexchars[]="0123456789abcdef"; 115 116 117/* 118 * Convert ch from a hex digit to an int 119 */ 120static int hex(unsigned char ch) 121{ 122 if (ch >= 'a' && ch <= 'f') 123 return ch-'a'+10; 124 if (ch >= '0' && ch <= '9') 125 return ch-'0'; 126 if (ch >= 'A' && ch <= 'F') 127 return ch-'A'+10; 128 return -1; 129} 130 131/* 132 * scan for the sequence $<data>#<checksum> 133 */ 134static void getpacket(char *buffer) 135{ 136 unsigned char checksum; 137 unsigned char xmitcsum; 138 int i; 139 int count; 140 unsigned char ch; 141 142 do { 143 /* 144 * wait around for the start character, 145 * ignore all other characters 146 */ 147 while ((ch = (getDebugChar() & 0x7f)) != '$') ; 148 149 checksum = 0; 150 xmitcsum = -1; 151 count = 0; 152 153 /* 154 * now, read until a # or end of buffer is found 155 */ 156 while (count < BUFMAX) { 157 ch = getDebugChar() & 0x7f; 158 if (ch == '#') 159 break; 160 checksum = checksum + ch; 161 buffer[count] = ch; 162 count = count + 1; 163 } 164 165 if (count >= BUFMAX) 166 continue; 167 168 buffer[count] = 0; 169 170 if (ch == '#') { 171 xmitcsum = hex(getDebugChar() & 0x7f) << 4; 172 xmitcsum |= hex(getDebugChar() & 0x7f); 173 174 if (checksum != xmitcsum) 175 putDebugChar('-'); /* failed checksum */ 176 else { 177 putDebugChar('+'); /* successful transfer */ 178 179 /* 180 * if a sequence char is present, 181 * reply the sequence ID 182 */ 183 if (buffer[2] == ':') { 184 putDebugChar(buffer[0]); 185 putDebugChar(buffer[1]); 186 187 /* 188 * remove sequence chars from buffer 189 */ 190 count = strlen(buffer); 191 for (i=3; i <= count; i++) 192 buffer[i-3] = buffer[i]; 193 } 194 } 195 } 196 } 197 while (checksum != xmitcsum); 198} 199 200/* 201 * send the packet in buffer. 202 */ 203static void putpacket(char *buffer) 204{ 205 unsigned char checksum; 206 int count; 207 unsigned char ch; 208 209 /* 210 * $<packet info>#<checksum>. 211 */ 212 213 do { 214 putDebugChar('$'); 215 checksum = 0; 216 count = 0; 217 218 while ((ch = buffer[count]) != 0) { 219 if (!(putDebugChar(ch))) 220 return; 221 checksum += ch; 222 count += 1; 223 } 224 225 putDebugChar('#'); 226 putDebugChar(hexchars[checksum >> 4]); 227 putDebugChar(hexchars[checksum & 0xf]); 228 229 } 230 while ((getDebugChar() & 0x7f) != '+'); 231} 232 233 234 235/* 236 * Convert the memory pointed to by mem into hex, placing result in buf. 237 * Return a pointer to the last char put in buf (null), in case of mem fault, 238 * return 0. 239 * If MAY_FAULT is non-zero, then we will handle memory faults by returning 240 * a 0, else treat a fault like any other fault in the stub. 241 */ 242static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) 243{ 244 unsigned char ch; 245 246/* set_mem_fault_trap(may_fault); */ 247 248 while (count-- > 0) { 249 ch = *(mem++); 250 if (mem_err) 251 return 0; 252 *buf++ = hexchars[ch >> 4]; 253 *buf++ = hexchars[ch & 0xf]; 254 } 255 256 *buf = 0; 257 258/* set_mem_fault_trap(0); */ 259 260 return buf; 261} 262 263/* 264 * convert the hex array pointed to by buf into binary to be placed in mem 265 * return a pointer to the character AFTER the last byte written 266 */ 267static char *hex2mem(char *buf, char *mem, int count, int may_fault) 268{ 269 int i; 270 unsigned char ch; 271 272/* set_mem_fault_trap(may_fault); */ 273 274 for (i=0; i<count; i++) 275 { 276 ch = hex(*buf++) << 4; 277 ch |= hex(*buf++); 278 *(mem++) = ch; 279 if (mem_err) 280 return 0; 281 } 282 283/* set_mem_fault_trap(0); */ 284 285 return mem; 286} 287 288 289 290/* 291 * Set up exception handlers for tracing and breakpoints 292 */ 293void set_debug_traps(void) 294{ 295// unsigned long flags; 296 unsigned char c; 297 298// save_and_cli(flags); 299 /* 300 * In case GDB is started before us, ack any packets 301 * (presumably "$?#xx") sitting there. 302 */ 303 while((c = getDebugChar()) != '$'); 304 while((c = getDebugChar()) != '#'); 305 c = getDebugChar(); /* eat first csum byte */ 306 c = getDebugChar(); /* eat second csum byte */ 307 putDebugChar('+'); /* ack it */ 308 309 gdb_stub_initialised = TRUE; 310// restore_flags(flags); 311} 312 313 314/* 315 * Trap handler for memory errors. This just sets mem_err to be non-zero. It 316 * assumes that %l1 is non-zero. This should be safe, as it is doubtful that 317 * 0 would ever contain code that could mem fault. This routine will skip 318 * past the faulting instruction after setting mem_err. 319 */ 320extern void fltr_set_mem_err(void) 321{ 322} 323 324 325/* 326 * While we find nice hex chars, build an int. 327 * Return number of chars processed. 328 */ 329static int hexToInt(char **ptr, int *intValue) 330{ 331 int numChars = 0; 332 int hexValue; 333 334 *intValue = 0; 335 336 while (**ptr) 337 { 338 hexValue = hex(**ptr); 339 if (hexValue < 0) 340 break; 341 342 *intValue = (*intValue << 4) | hexValue; 343 numChars ++; 344 345 (*ptr)++; 346 } 347 348 return (numChars); 349} 350 351void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs) 352{ 353 s390_fp_regs *fpregs=®s->fp_regs; 354 int has_ieee=save_fp_regs1(fpregs); 355 356 if(!has_ieee) 357 { 358 fpregs->fpc=0; 359 fpregs->fprs[1].d= 360 fpregs->fprs[3].d= 361 fpregs->fprs[5].d= 362 fpregs->fprs[7].d=0; 363 memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8); 364 } 365} 366 367void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs) 368{ 369 restore_fp_regs1(®s->fp_regs); 370} 371 372void gdb_stub_send_signal(int sigval) 373{ 374 char *ptr; 375 ptr = output_buffer; 376 377 /* 378 * Send trap type (converted to signal) 379 */ 380 *ptr++ = 'S'; 381 *ptr++ = hexchars[sigval >> 4]; 382 *ptr++ = hexchars[sigval & 0xf]; 383 *ptr++ = 0; 384 putpacket(output_buffer); /* send it off... */ 385} 386 387/* 388 * This function does all command processing for interfacing to gdb. It 389 * returns 1 if you should skip the instruction at the trap address, 0 390 * otherwise. 391 */ 392void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval) 393{ 394 int trap; /* Trap type */ 395 int addr; 396 int length; 397 char *ptr; 398 unsigned long *stack; 399 400 401 /* 402 * reply to host that an exception has occurred 403 */ 404 send_signal(sigval); 405 406 /* 407 * Wait for input from remote GDB 408 */ 409 while (1) { 410 output_buffer[0] = 0; 411 getpacket(input_buffer); 412 413 switch (input_buffer[0]) 414 { 415 case '?': 416 send_signal(sigval); 417 continue; 418 419 case 'd': 420 /* toggle debug flag */ 421 break; 422 423 /* 424 * Return the value of the CPU registers 425 */ 426 case 'g': 427 gdb_stub_get_non_pt_regs(regs); 428 ptr = output_buffer; 429 ptr= mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE); 430 ptr= mem2hex((char *)®s->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE); 431 ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs)); 432 break; 433 434 case 'G': 435 ptr=input_buffer; 436 hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE); 437 ptr+=sizeof(s390_regs_common)*2; 438 hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE); 439 ptr+=NUM_CRS*CR_SIZE*2; 440 hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE); 441 gdb_stub_set_non_pt_regs(regs); 442 strcpy(output_buffer,"OK"); 443 break; 444 445 /* 446 * mAA..AA,LLLL Read LLLL bytes at address AA..AA 447 */ 448 case 'm': 449 ptr = &input_buffer[1]; 450 451 if (hexToInt(&ptr, &addr) 452 && *ptr++ == ',' 453 && hexToInt(&ptr, &length)) { 454 if (mem2hex((char *)addr, output_buffer, length, 1)) 455 break; 456 strcpy (output_buffer, "E03"); 457 } else 458 strcpy(output_buffer,"E01"); 459 break; 460 461 /* 462 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK 463 */ 464 case 'M': 465 ptr = &input_buffer[1]; 466 467 if (hexToInt(&ptr, &addr) 468 && *ptr++ == ',' 469 && hexToInt(&ptr, &length) 470 && *ptr++ == ':') { 471 if (hex2mem(ptr, (char *)addr, length, 1)) 472 strcpy(output_buffer, "OK"); 473 else 474 strcpy(output_buffer, "E03"); 475 } 476 else 477 strcpy(output_buffer, "E02"); 478 break; 479 480 /* 481 * cAA..AA Continue at address AA..AA(optional) 482 */ 483 case 'c': 484 /* try to read optional parameter, pc unchanged if no parm */ 485 486 ptr = &input_buffer[1]; 487 if (hexToInt(&ptr, &addr)) 488 regs->cp0_epc = addr; 489 490 /* 491 * Need to flush the instruction cache here, as we may 492 * have deposited a breakpoint, and the icache probably 493 * has no way of knowing that a data ref to some location 494 * may have changed something that is in the instruction 495 * cache. 496 * NB: We flush both caches, just to be sure... 497 */ 498 499 flush_cache_all(); 500 return; 501 /* NOTREACHED */ 502 break; 503 504 505 /* 506 * kill the program 507 */ 508 case 'k' : 509 break; /* do nothing */ 510 511 512 case 'r': 513 break; 514 515 516 /* 517 * Step to next instruction 518 */ 519 case 's': 520 /* 521 * There is no single step insn in the MIPS ISA, so we 522 * use breakpoints and continue, instead. 523 */ 524 single_step(regs); 525 flush_cache_all(); 526 return; 527 /* NOTREACHED */ 528 529 } 530 break; 531 532 } /* switch */ 533 534 /* 535 * reply to the request 536 */ 537 538 putpacket(output_buffer); 539 540 } /* while */ 541} 542 543/* 544 * This function will generate a breakpoint exception. It is used at the 545 * beginning of a program to sync up with a debugger and can be used 546 * otherwise as a quick means to stop program execution and "break" into 547 * the debugger. 548 */ 549void breakpoint(void) 550{ 551 if (!gdb_stub_initialised) 552 return; 553 __asm__ __volatile__( 554 ".globl breakinst\n" 555 "breakinst:\t.word %0\n\t" 556 : 557 : "i" (S390_BREAKPOINT_U16) 558 : 559 ); 560} 561 562 563 564 565 566 567 568