1 /* taken from arch/powerpc/kernel/ppc-stub.c */
3 /****************************************************************************
5 THIS SOFTWARE IS NOT COPYRIGHTED
7 HP offers the following for use in the public domain. HP makes no
8 warranty with regard to the software or its performance and the
9 user accepts the software "AS IS" with all faults.
11 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
12 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 ****************************************************************************/
17 /****************************************************************************
18 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
20 * Module name: remcom.c $
22 * Date: 91/03/09 12:29:49 $
23 * Contributor: Lake Stevens Instrument Division$
25 * Description: low level support for gdb debugger. $
27 * Considerations: only works on target hardware $
29 * Written by: Glenn Engel $
30 * ModuleState: Experimental $
34 * Modified for SPARC by Stu Grossman, Cygnus Support.
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
38 * To enable debugger support, two things need to happen. One, a
39 * call to set_debug_traps() is necessary in order to allow any breakpoints
40 * or error conditions to be properly intercepted and reported to gdb.
41 * Two, a breakpoint needs to be generated to begin communication. This
42 * is most easily accomplished by a call to breakpoint(). Breakpoint()
43 * simulates a breakpoint by executing a trap #1.
47 * The following gdb commands are supported:
49 * command function Return value
51 * g return the value of the CPU registers hex data or ENN
52 * G set the value of the CPU registers OK or ENN
53 * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
55 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
56 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
58 * c Resume at current address SNN ( signal NN)
59 * cAA..AA Continue at address AA..AA SNN
61 * s Step one instruction SNN
62 * sAA..AA Step one instruction from AA..AA SNN
66 * ? What was the last sigval ? SNN (signal NN)
68 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
71 * All commands and responses are sent with a packet which includes a
72 * checksum. A packet consists of
74 * $<packet info>#<checksum>.
77 * <packet info> :: <characters representing the command or response>
78 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
80 * When a packet is received, it is first acknowledged with either '+' or '-'.
81 * '+' indicates a successful transfer. '-' indicates a failed transfer.
86 * $m0,10#2a +$00010203040506070809101112131415#42
88 ****************************************************************************/
91 #include <asm/ptrace.h>
99 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
102 static char remcomInBuffer[BUFMAX];
103 static char remcomOutBuffer[BUFMAX];
104 static char remcomRegBuffer[BUFMAX];
106 static int initialized = 0;
107 static int kgdb_active;
108 static struct pt_regs entry_regs;
109 static long error_jmp_buf[BUFMAX/2];
110 static int longjmp_on_fault = 0;
112 static int kdebug = 1;
115 static const char hexchars[]="0123456789abcdef";
117 /* Convert ch from a hex digit to an int */
119 hex(unsigned char ch)
121 if (ch >= 'a' && ch <= 'f')
123 if (ch >= '0' && ch <= '9')
125 if (ch >= 'A' && ch <= 'F')
130 /* Convert the memory pointed to by mem into hex, placing result in buf.
131 * Return a pointer to the last char put in buf (null).
133 static unsigned char *
134 mem2hex(char *mem, char *buf, int count)
140 * We use the upper half of buf as an intermediate buffer for the
141 * raw memory copy. Hex conversion will work against this one.
144 longjmp_on_fault = 1;
146 memcpy(tmp, mem, count);
148 while (count-- > 0) {
150 *buf++ = hexchars[ch >> 4];
151 *buf++ = hexchars[ch & 0xf];
154 longjmp_on_fault = 0;
155 return (unsigned char *)buf;
158 /* convert the hex array pointed to by buf into binary to be placed in mem
159 * return a pointer to the character AFTER the last byte fetched from buf.
162 hex2mem(char *buf, char *mem, int count)
165 char *tmp_raw, *tmp_hex;
168 * We use the upper half of buf as an intermediate buffer for the
169 * raw memory that is converted from hex.
171 tmp_raw = buf + count * 2;
172 tmp_hex = tmp_raw - 1;
174 longjmp_on_fault = 1;
175 while (tmp_hex >= buf) {
177 hexValue = hex(*tmp_hex--);
179 kgdb_error(KGDBERR_NOTHEXDIG);
181 hexValue = hex(*tmp_hex--);
183 kgdb_error(KGDBERR_NOTHEXDIG);
184 *tmp_raw |= hexValue << 4;
188 memcpy(mem, tmp_raw, count);
190 kgdb_flush_cache_range((void *)mem, (void *)(mem+count));
191 longjmp_on_fault = 0;
197 * While we find nice hex chars, build an int.
198 * Return number of chars processed.
201 hexToInt(char **ptr, int *intValue)
208 longjmp_on_fault = 1;
210 hexValue = hex(**ptr);
214 *intValue = (*intValue << 4) | hexValue;
219 longjmp_on_fault = 0;
224 /* scan for the sequence $<data>#<checksum> */
226 getpacket(char *buffer)
228 unsigned char checksum;
229 unsigned char xmitcsum;
235 /* wait around for the start character, ignore all other
237 while ((ch = (getDebugChar() & 0x7f)) != '$') {
250 /* now, read until a # or end of buffer is found */
251 while (count < BUFMAX) {
252 ch = getDebugChar() & 0x7f;
255 checksum = checksum + ch;
266 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
267 xmitcsum |= hex(getDebugChar() & 0x7f);
268 if (checksum != xmitcsum)
269 putDebugChar('-'); /* failed checksum */
271 putDebugChar('+'); /* successful transfer */
272 /* if a sequence char is present, reply the ID */
273 if (buffer[2] == ':') {
274 putDebugChar(buffer[0]);
275 putDebugChar(buffer[1]);
276 /* remove sequence chars from buffer */
277 count = strlen(buffer);
278 for (i=3; i <= count; i++)
279 buffer[i-3] = buffer[i];
283 } while (checksum != xmitcsum);
286 /* send the packet in buffer. */
288 putpacket(unsigned char *buffer)
290 unsigned char checksum;
292 unsigned char ch, recv;
294 /* $<packet info>#<checksum>. */
300 while ((ch = buffer[count])) {
307 putDebugChar(hexchars[checksum >> 4]);
308 putDebugChar(hexchars[checksum & 0xf]);
309 recv = getDebugChar();
310 } while ((recv & 0x7f) != '+');
314 * This function does all command processing for interfacing to gdb.
317 handle_exception (struct pt_regs *regs)
326 printf("kgdb: exception before kgdb is initialized! huh?\n");
330 /* probably should check which exception occurred as well */
331 if (longjmp_on_fault) {
332 longjmp_on_fault = 0;
333 kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT);
334 panic("kgdb longjump failed!\n");
338 printf("kgdb: unexpected exception from within kgdb\n");
343 kgdb_interruptible(0);
345 printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
347 if (kgdb_setjmp(error_jmp_buf) != 0)
348 panic("kgdb: error or fault in entry init!\n");
350 kgdb_enter(regs, &kd);
354 ptr = remcomOutBuffer;
358 *ptr++ = hexchars[kd.sigval >> 4];
359 *ptr++ = hexchars[kd.sigval & 0xf];
361 for (i = 0; i < kd.nregs; i++) {
362 kgdb_reg *rp = &kd.regs[i];
364 *ptr++ = hexchars[rp->num >> 4];
365 *ptr++ = hexchars[rp->num & 0xf];
367 ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
375 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
378 putpacket((unsigned char *)&remcomOutBuffer);
383 remcomOutBuffer[0] = 0;
385 getpacket(remcomInBuffer);
386 ptr = &remcomInBuffer[1];
390 printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer);
393 errnum = kgdb_setjmp(error_jmp_buf);
395 if (errnum == 0) switch (remcomInBuffer[0]) {
397 case '?': /* report most recent signal */
398 remcomOutBuffer[0] = 'S';
399 remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
400 remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
401 remcomOutBuffer[3] = 0;
406 /* toggle debug flag */
411 case 'g': /* return the value of the CPU registers. */
412 length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
413 mem2hex(remcomRegBuffer, remcomOutBuffer, length);
416 case 'G': /* set the value of the CPU registers */
417 length = strlen(ptr);
418 if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
419 hex2mem(ptr, remcomRegBuffer, length/2);
420 kgdb_putregs(regs, remcomRegBuffer, length/2);
421 strcpy(remcomOutBuffer,"OK");
424 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
425 /* Try to read %x,%x. */
427 if (hexToInt(&ptr, &addr)
429 && hexToInt(&ptr, &length)) {
430 mem2hex((char *)addr, remcomOutBuffer, length);
432 kgdb_error(KGDBERR_BADPARAMS);
436 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
437 /* Try to read '%x,%x:'. */
439 if (hexToInt(&ptr, &addr)
441 && hexToInt(&ptr, &length)
443 hex2mem(ptr, (char *)addr, length);
444 strcpy(remcomOutBuffer, "OK");
446 kgdb_error(KGDBERR_BADPARAMS);
451 case 'k': /* kill the program, actually return to monitor */
452 kd.extype = KGDBEXIT_KILL;
456 case 'C': /* CSS continue with signal SS */
457 *ptr = '\0'; /* ignore the signal number for now */
460 case 'c': /* cAA..AA Continue; address AA..AA optional */
461 /* try to read optional parameter, pc unchanged if no parm */
462 kd.extype = KGDBEXIT_CONTINUE;
464 if (hexToInt(&ptr, &addr)) {
466 kd.extype |= KGDBEXIT_WITHADDR;
471 case 'S': /* SSS single step with signal SS */
472 *ptr = '\0'; /* ignore the signal number for now */
476 kd.extype = KGDBEXIT_SINGLE;
478 if (hexToInt(&ptr, &addr)) {
480 kd.extype |= KGDBEXIT_WITHADDR;
484 /* Need to flush the instruction cache here, as we may have deposited a
485 * breakpoint, and the icache probably has no way of knowing that a data ref to
486 * some location may have changed something that is in the instruction cache.
488 kgdb_flush_cache_all();
489 kgdb_exit(regs, &kd);
491 kgdb_interruptible(1);
494 case 'r': /* Reset (if user process..exit ???)*/
495 panic("kgdb reset.");
498 case 'P': /* Pr=v set reg r to value v (r and v are hex) */
499 if (hexToInt(&ptr, &addr)
501 && ((length = strlen(ptr)) & 1) == 0) {
502 hex2mem(ptr, remcomRegBuffer, length/2);
503 kgdb_putreg(regs, addr,
504 remcomRegBuffer, length/2);
505 strcpy(remcomOutBuffer,"OK");
507 kgdb_error(KGDBERR_BADPARAMS);
513 sprintf(remcomOutBuffer, "E%02d", errnum);
517 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
520 /* reply to the request */
521 putpacket((unsigned char *)&remcomOutBuffer);
527 * kgdb_init must be called *after* the
528 * monitor is relocated into ram
534 debugger_exception_handler = handle_exception;
537 putDebugStr("kgdb ready\n");
542 kgdb_error(int errnum)
544 longjmp_on_fault = 0;
545 kgdb_longjmp(error_jmp_buf, errnum);
546 panic("kgdb_error: longjmp failed!\n");
549 /* Output string in GDB O-packet format if GDB has connected. If nothing
550 output, returns 0 (caller must then handle output). */
552 kgdb_output_string (const char* s, unsigned int count)
556 count = (count <= (sizeof(buffer) / 2 - 2))
557 ? count : (sizeof(buffer) / 2 - 2);
560 mem2hex ((char *)s, &buffer[1], count);
561 putpacket((unsigned char *)&buffer);
570 printf("breakpoint() called b4 kgdb init\n");
574 kgdb_breakpoint(0, 0);
578 do_kgdb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
580 printf("Entering KGDB mode via exception handler...\n\n");
581 kgdb_breakpoint(argc - 1, argv + 1);
582 printf("\nReturned from KGDB mode\n");
587 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb,
588 "enter gdb remote debug mode",
589 "[arg0 arg1 .. argN]\n"
590 " - executes a breakpoint so that kgdb mode is\n"
591 " entered via the exception handler. To return\n"
592 " to the monitor, the remote gdb debugger must\n"
593 " execute a \"continue\" or \"quit\" command.\n"
595 " if a program is loaded by the remote gdb, any args\n"
596 " passed to the kgdb command are given to the loaded\n"
597 " program if it is executed (see the \"hello_world\"\n"
598 " example program in the U-Boot examples directory)."