2 * arch/s390/kernel/gdb-stub.c
5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
8 * Originally written by Glenn Engel, Lake Stevens Instrument Division
10 * Contributed by HP Systems
12 * Modified for SPARC by Stu Grossman, Cygnus Support.
14 * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
15 * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
17 * Copyright (C) 1995 Andreas Busse
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.
29 * The following gdb commands are supported:
31 * command function Return value
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
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
39 * c Resume at current address SNN ( signal NN)
40 * cAA..AA Continue at address AA..AA SNN
42 * s Step one instruction SNN
43 * sAA..AA Step one instruction from AA..AA SNN
47 * ? What was the last sigval ? SNN (signal NN)
50 * All commands and responses are sent with a packet which includes a
51 * checksum. A packet consists of
53 * $<packet info>#<checksum>.
56 * <packet info> :: <characters representing the command or response>
57 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
59 * When a packet is received, it is first acknowledged with either '+' or '-'.
60 * '+' indicates a successful transfer. '-' indicates a failed transfer.
65 * $m0,10#2a +$00010203040506070809101112131415#42
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>
75 #include <asm/pgtable.h>
76 #include <asm/system.h>
80 * external low-level support routines
83 extern int putDebugChar(char c); /* write a single character */
84 extern char getDebugChar(void); /* read and return a single char */
85 extern void fltr_set_mem_err(void);
86 extern void trap_low(void);
89 * breakpoint and test functions
91 extern void breakpoint(void);
92 extern void breakinst(void);
98 static void getpacket(char *buffer);
99 static void putpacket(char *buffer);
100 static int hex(unsigned char ch);
101 static int hexToInt(char **ptr, int *intValue);
102 static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
106 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
107 * at least NUMREGBYTES*2 are needed for register packets
111 static char input_buffer[BUFMAX];
112 static char output_buffer[BUFMAX];
113 int gdb_stub_initialised = FALSE;
114 static const char hexchars[]="0123456789abcdef";
118 * Convert ch from a hex digit to an int
120 static int hex(unsigned char ch)
122 if (ch >= 'a' && ch <= 'f')
124 if (ch >= '0' && ch <= '9')
126 if (ch >= 'A' && ch <= 'F')
132 * scan for the sequence $<data>#<checksum>
134 static void getpacket(char *buffer)
136 unsigned char checksum;
137 unsigned char xmitcsum;
144 * wait around for the start character,
145 * ignore all other characters
147 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
154 * now, read until a # or end of buffer is found
156 while (count < BUFMAX) {
157 ch = getDebugChar() & 0x7f;
160 checksum = checksum + ch;
171 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
172 xmitcsum |= hex(getDebugChar() & 0x7f);
174 if (checksum != xmitcsum)
175 putDebugChar('-'); /* failed checksum */
177 putDebugChar('+'); /* successful transfer */
180 * if a sequence char is present,
181 * reply the sequence ID
183 if (buffer[2] == ':') {
184 putDebugChar(buffer[0]);
185 putDebugChar(buffer[1]);
188 * remove sequence chars from buffer
190 count = strlen(buffer);
191 for (i=3; i <= count; i++)
192 buffer[i-3] = buffer[i];
197 while (checksum != xmitcsum);
201 * send the packet in buffer.
203 static void putpacket(char *buffer)
205 unsigned char checksum;
210 * $<packet info>#<checksum>.
218 while ((ch = buffer[count]) != 0) {
219 if (!(putDebugChar(ch)))
226 putDebugChar(hexchars[checksum >> 4]);
227 putDebugChar(hexchars[checksum & 0xf]);
230 while ((getDebugChar() & 0x7f) != '+');
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,
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.
242 static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
246 /* set_mem_fault_trap(may_fault); */
248 while (count-- > 0) {
252 *buf++ = hexchars[ch >> 4];
253 *buf++ = hexchars[ch & 0xf];
258 /* set_mem_fault_trap(0); */
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
267 static char *hex2mem(char *buf, char *mem, int count, int may_fault)
272 /* set_mem_fault_trap(may_fault); */
274 for (i=0; i<count; i++)
276 ch = hex(*buf++) << 4;
283 /* set_mem_fault_trap(0); */
291 * Set up exception handlers for tracing and breakpoints
293 void set_debug_traps(void)
295 // unsigned long flags;
298 // save_and_cli(flags);
300 * In case GDB is started before us, ack any packets
301 * (presumably "$?#xx") sitting there.
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 */
309 gdb_stub_initialised = TRUE;
310 // restore_flags(flags);
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.
320 extern void fltr_set_mem_err(void)
322 /* FIXME: Needs to be written... */
327 * While we find nice hex chars, build an int.
328 * Return number of chars processed.
330 static int hexToInt(char **ptr, int *intValue)
339 hexValue = hex(**ptr);
343 *intValue = (*intValue << 4) | hexValue;
352 void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs)
354 s390_fp_regs *fpregs=®s->fp_regs;
355 int has_ieee=save_fp_regs1(fpregs);
364 memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
368 void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
370 restore_fp_regs1(®s->fp_regs);
373 void gdb_stub_send_signal(int sigval)
379 * Send trap type (converted to signal)
382 *ptr++ = hexchars[sigval >> 4];
383 *ptr++ = hexchars[sigval & 0xf];
385 putpacket(output_buffer); /* send it off... */
389 * This function does all command processing for interfacing to gdb. It
390 * returns 1 if you should skip the instruction at the trap address, 0
393 void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
395 int trap; /* Trap type */
399 unsigned long *stack;
403 * reply to host that an exception has occurred
408 * Wait for input from remote GDB
411 output_buffer[0] = 0;
412 getpacket(input_buffer);
414 switch (input_buffer[0])
421 /* toggle debug flag */
425 * Return the value of the CPU registers
428 gdb_stub_get_non_pt_regs(regs);
430 ptr= mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE);
431 ptr= mem2hex((char *)®s->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
432 ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs));
436 * set the value of the CPU registers - return OK
437 * FIXME: Needs to be written
441 hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE);
442 ptr+=sizeof(s390_regs_common)*2;
443 hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
444 ptr+=NUM_CRS*CR_SIZE*2;
445 hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE);
446 gdb_stub_set_non_pt_regs(regs);
447 strcpy(output_buffer,"OK");
451 * mAA..AA,LLLL Read LLLL bytes at address AA..AA
454 ptr = &input_buffer[1];
456 if (hexToInt(&ptr, &addr)
458 && hexToInt(&ptr, &length)) {
459 if (mem2hex((char *)addr, output_buffer, length, 1))
461 strcpy (output_buffer, "E03");
463 strcpy(output_buffer,"E01");
467 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
470 ptr = &input_buffer[1];
472 if (hexToInt(&ptr, &addr)
474 && hexToInt(&ptr, &length)
476 if (hex2mem(ptr, (char *)addr, length, 1))
477 strcpy(output_buffer, "OK");
479 strcpy(output_buffer, "E03");
482 strcpy(output_buffer, "E02");
486 * cAA..AA Continue at address AA..AA(optional)
489 /* try to read optional parameter, pc unchanged if no parm */
491 ptr = &input_buffer[1];
492 if (hexToInt(&ptr, &addr))
493 regs->cp0_epc = addr;
496 * Need to flush the instruction cache here, as we may
497 * have deposited a breakpoint, and the icache probably
498 * has no way of knowing that a data ref to some location
499 * may have changed something that is in the instruction
501 * NB: We flush both caches, just to be sure...
514 break; /* do nothing */
518 * Reset the whole machine (FIXME: system dependent)
525 * Step to next instruction
529 * There is no single step insn in the MIPS ISA, so we
530 * use breakpoints and continue, instead.
543 * reply to the request
546 putpacket(output_buffer);
552 * This function will generate a breakpoint exception. It is used at the
553 * beginning of a program to sync up with a debugger and can be used
554 * otherwise as a quick means to stop program execution and "break" into
557 void breakpoint(void)
559 if (!gdb_stub_initialised)
561 __asm__ __volatile__(
563 "breakinst:\t.word %0\n\t"
565 : "i" (S390_BREAKPOINT_U16)