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
70 #include <asm/gdb-stub.h>
71 #include <linux/string.h>
72 #include <linux/kernel.h>
73 #include <linux/signal.h>
74 #include <linux/sched.h>
76 #include <asm/pgtable.h>
77 #include <asm/system.h>
78 #include <linux/stddef.h>
80 #define S390_REGS_COMMON_SIZE offsetof(struct gdb_pt_regs,orig_gpr2)
83 * external low-level support routines
87 extern void fltr_set_mem_err(void);
88 extern void trap_low(void);
91 * breakpoint and test functions
93 extern void breakpoint(void);
94 extern void breakinst(void);
100 static void getpacket(char *buffer);
101 static void putpacket(char *buffer);
102 static int hex(unsigned char ch);
103 static int hexToInt(char **ptr, int *intValue);
104 static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
108 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
109 * at least NUMREGBYTES*2 are needed for register packets
113 static char input_buffer[BUFMAX];
114 static char output_buffer[BUFMAX];
115 int gdb_stub_initialised = FALSE;
116 static const char hexchars[]="0123456789abcdef";
120 * Convert ch from a hex digit to an int
122 static int hex(unsigned char ch)
124 if (ch >= 'a' && ch <= 'f')
126 if (ch >= '0' && ch <= '9')
128 if (ch >= 'A' && ch <= 'F')
134 * scan for the sequence $<data>#<checksum>
136 static void getpacket(char *buffer)
138 unsigned char checksum;
139 unsigned char xmitcsum;
146 * wait around for the start character,
147 * ignore all other characters
149 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
156 * now, read until a # or end of buffer is found
158 while (count < BUFMAX) {
159 ch = getDebugChar() & 0x7f;
162 checksum = checksum + ch;
173 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
174 xmitcsum |= hex(getDebugChar() & 0x7f);
176 if (checksum != xmitcsum)
177 putDebugChar('-'); /* failed checksum */
179 putDebugChar('+'); /* successful transfer */
182 * if a sequence char is present,
183 * reply the sequence ID
185 if (buffer[2] == ':') {
186 putDebugChar(buffer[0]);
187 putDebugChar(buffer[1]);
190 * remove sequence chars from buffer
192 count = strlen(buffer);
193 for (i=3; i <= count; i++)
194 buffer[i-3] = buffer[i];
199 while (checksum != xmitcsum);
203 * send the packet in buffer.
205 static void putpacket(char *buffer)
207 unsigned char checksum;
212 * $<packet info>#<checksum>.
220 while ((ch = buffer[count]) != 0) {
221 if (!(putDebugChar(ch)))
228 putDebugChar(hexchars[checksum >> 4]);
229 putDebugChar(hexchars[checksum & 0xf]);
232 while ((getDebugChar() & 0x7f) != '+');
238 * Convert the memory pointed to by mem into hex, placing result in buf.
239 * Return a pointer to the last char put in buf (null), in case of mem fault,
241 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
242 * a 0, else treat a fault like any other fault in the stub.
244 static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
248 /* set_mem_fault_trap(may_fault); */
250 while (count-- > 0) {
256 *buf++ = hexchars[ch >> 4];
257 *buf++ = hexchars[ch & 0xf];
262 /* set_mem_fault_trap(0); */
268 * convert the hex array pointed to by buf into binary to be placed in mem
269 * return a pointer to the character AFTER the last byte written
271 static char *hex2mem(char *buf, char *mem, int count, int may_fault)
276 /* set_mem_fault_trap(may_fault); */
278 for (i=0; i<count; i++)
280 ch = hex(*buf++) << 4;
289 /* set_mem_fault_trap(0); */
297 * Set up exception handlers for tracing and breakpoints
299 void set_debug_traps(void)
301 // unsigned long flags;
304 // save_and_cli(flags);
306 * In case GDB is started before us, ack any packets
307 * (presumably "$?#xx") sitting there.
309 while((c = getDebugChar()) != '$');
310 while((c = getDebugChar()) != '#');
311 c = getDebugChar(); /* eat first csum byte */
312 c = getDebugChar(); /* eat second csum byte */
313 putDebugChar('+'); /* ack it */
315 gdb_stub_initialised = TRUE;
316 // restore_flags(flags);
321 * Trap handler for memory errors. This just sets mem_err to be non-zero. It
322 * assumes that %l1 is non-zero. This should be safe, as it is doubtful that
323 * 0 would ever contain code that could mem fault. This routine will skip
324 * past the faulting instruction after setting mem_err.
326 extern void fltr_set_mem_err(void)
328 /* FIXME: Needs to be written... */
333 * While we find nice hex chars, build an int.
334 * Return number of chars processed.
336 static int hexToInt(char **ptr, int *intValue)
345 hexValue = hex(**ptr);
349 *intValue = (*intValue << 4) | hexValue;
358 void gdb_stub_get_non_pt_regs(struct gdb_pt_regs *regs)
360 s390_fp_regs *fpregs=®s->fp_regs;
361 int has_ieee=save_fp_regs1(fpregs);
370 memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
374 void gdb_stub_set_non_pt_regs(struct gdb_pt_regs *regs)
376 restore_fp_regs1(®s->fp_regs);
379 void gdb_stub_send_signal(int sigval)
385 * Send trap type (converted to signal)
388 *ptr++ = hexchars[sigval >> 4];
389 *ptr++ = hexchars[sigval & 0xf];
391 putpacket(output_buffer); /* send it off... */
395 * This function does all command processing for interfacing to gdb. It
396 * returns 1 if you should skip the instruction at the trap address, 0
399 void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval)
401 int trap; /* Trap type */
405 unsigned long *stack;
409 * reply to host that an exception has occurred
415 * Wait for input from remote GDB
419 output_buffer[0] = 0;
420 getpacket(input_buffer);
422 switch (input_buffer[0])
431 /* toggle debug flag */
435 * Return the value of the CPU registers
438 gdb_stub_get_non_pt_regs(regs);
440 ptr= mem2hex((char *)regs,ptr,S390_REGS_COMMON_SIZE,FALSE);
441 ptr= mem2hex((char *)®s->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
442 ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs),FALSE);
446 * set the value of the CPU registers - return OK
447 * FIXME: Needs to be written
451 hex2mem (ptr, (char *)regs,S390_REGS_COMMON_SIZE, FALSE);
452 ptr+=S390_REGS_COMMON_SIZE*2;
453 hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
454 ptr+=NUM_CRS*CR_SIZE*2;
455 hex2mem (ptr, (char *)®s->fp_regs,sizeof(s390_fp_regs), FALSE);
456 gdb_stub_set_non_pt_regs(regs);
457 strcpy(output_buffer,"OK");
461 * mAA..AA,LLLL Read LLLL bytes at address AA..AA
464 ptr = &input_buffer[1];
466 if (hexToInt(&ptr, &addr)
468 && hexToInt(&ptr, &length)) {
469 if (mem2hex((char *)addr, output_buffer, length, 1))
471 strcpy (output_buffer, "E03");
473 strcpy(output_buffer,"E01");
477 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
480 ptr = &input_buffer[1];
482 if (hexToInt(&ptr, &addr)
484 && hexToInt(&ptr, &length)
487 if (hex2mem(ptr, (char *)addr, length, 1))
488 strcpy(output_buffer, "OK");
490 strcpy(output_buffer, "E03");
493 strcpy(output_buffer, "E02");
497 * cAA..AA Continue at address AA..AA(optional)
500 /* try to read optional parameter, pc unchanged if no parm */
502 ptr = &input_buffer[1];
503 if (hexToInt(&ptr, &addr))
504 regs->psw.addr = addr;
506 * Need to flush the instruction cache here, as we may
507 * have deposited a breakpoint, and the icache probably
508 * has no way of knowing that a data ref to some location
509 * may have changed something that is in the instruction
511 * NB: We flush both caches, just to be sure...
524 break; /* do nothing */
528 * Reset the whole machine (FIXME: system dependent)
535 * Step to next instruction
539 * There is no single step insn in the MIPS ISA, so we
540 * use breakpoints and continue, instead.
553 * reply to the request
556 putpacket(output_buffer);
562 * This function will generate a breakpoint exception. It is used at the
563 * beginning of a program to sync up with a debugger and can be used
564 * otherwise as a quick means to stop program execution and "break" into
567 void breakpoint(void)
569 if (!gdb_stub_initialised)
571 asm volatile (".globl breakinst\n"
572 "breakinst:\t.word %0"
573 : : "i" (S390_BREAKPOINT_U16) );