File: /usr/src/linux/arch/s390/kernel/gdb-stub.c
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
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);
87
88 /*
89 * breakpoint and test functions
90 */
91 extern void breakpoint(void);
92 extern void breakinst(void);
93
94 /*
95 * local prototypes
96 */
97
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);
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
111 static char input_buffer[BUFMAX];
112 static char output_buffer[BUFMAX];
113 int gdb_stub_initialised = FALSE;
114 static const char hexchars[]="0123456789abcdef";
115
116
117 /*
118 * Convert ch from a hex digit to an int
119 */
120 static 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 */
134 static 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 */
203 static 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 */
242 static 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 */
267 static 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 */
293 void 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 */
320 extern void fltr_set_mem_err(void)
321 {
322 /* FIXME: Needs to be written... */
323 }
324
325
326 /*
327 * While we find nice hex chars, build an int.
328 * Return number of chars processed.
329 */
330 static int hexToInt(char **ptr, int *intValue)
331 {
332 int numChars = 0;
333 int hexValue;
334
335 *intValue = 0;
336
337 while (**ptr)
338 {
339 hexValue = hex(**ptr);
340 if (hexValue < 0)
341 break;
342
343 *intValue = (*intValue << 4) | hexValue;
344 numChars ++;
345
346 (*ptr)++;
347 }
348
349 return (numChars);
350 }
351
352 void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs)
353 {
354 s390_fp_regs *fpregs=®s->fp_regs;
355 int has_ieee=save_fp_regs1(fpregs);
356
357 if(!has_ieee)
358 {
359 fpregs->fpc=0;
360 fpregs->fprs[1].d=
361 fpregs->fprs[3].d=
362 fpregs->fprs[5].d=
363 fpregs->fprs[7].d=0;
364 memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
365 }
366 }
367
368 void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
369 {
370 restore_fp_regs1(®s->fp_regs);
371 }
372
373 void gdb_stub_send_signal(int sigval)
374 {
375 char *ptr;
376 ptr = output_buffer;
377
378 /*
379 * Send trap type (converted to signal)
380 */
381 *ptr++ = 'S';
382 *ptr++ = hexchars[sigval >> 4];
383 *ptr++ = hexchars[sigval & 0xf];
384 *ptr++ = 0;
385 putpacket(output_buffer); /* send it off... */
386 }
387
388 /*
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
391 * otherwise.
392 */
393 void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
394 {
395 int trap; /* Trap type */
396 int addr;
397 int length;
398 char *ptr;
399 unsigned long *stack;
400
401
402 /*
403 * reply to host that an exception has occurred
404 */
405 send_signal(sigval);
406
407 /*
408 * Wait for input from remote GDB
409 */
410 while (1) {
411 output_buffer[0] = 0;
412 getpacket(input_buffer);
413
414 switch (input_buffer[0])
415 {
416 case '?':
417 send_signal(sigval);
418 continue;
419
420 case 'd':
421 /* toggle debug flag */
422 break;
423
424 /*
425 * Return the value of the CPU registers
426 */
427 case 'g':
428 gdb_stub_get_non_pt_regs(regs);
429 ptr = output_buffer;
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));
433 break;
434
435 /*
436 * set the value of the CPU registers - return OK
437 * FIXME: Needs to be written
438 */
439 case 'G':
440 ptr=input_buffer;
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");
448 break;
449
450 /*
451 * mAA..AA,LLLL Read LLLL bytes at address AA..AA
452 */
453 case 'm':
454 ptr = &input_buffer[1];
455
456 if (hexToInt(&ptr, &addr)
457 && *ptr++ == ','
458 && hexToInt(&ptr, &length)) {
459 if (mem2hex((char *)addr, output_buffer, length, 1))
460 break;
461 strcpy (output_buffer, "E03");
462 } else
463 strcpy(output_buffer,"E01");
464 break;
465
466 /*
467 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
468 */
469 case 'M':
470 ptr = &input_buffer[1];
471
472 if (hexToInt(&ptr, &addr)
473 && *ptr++ == ','
474 && hexToInt(&ptr, &length)
475 && *ptr++ == ':') {
476 if (hex2mem(ptr, (char *)addr, length, 1))
477 strcpy(output_buffer, "OK");
478 else
479 strcpy(output_buffer, "E03");
480 }
481 else
482 strcpy(output_buffer, "E02");
483 break;
484
485 /*
486 * cAA..AA Continue at address AA..AA(optional)
487 */
488 case 'c':
489 /* try to read optional parameter, pc unchanged if no parm */
490
491 ptr = &input_buffer[1];
492 if (hexToInt(&ptr, &addr))
493 regs->cp0_epc = addr;
494
495 /*
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
500 * cache.
501 * NB: We flush both caches, just to be sure...
502 */
503
504 flush_cache_all();
505 return;
506 /* NOTREACHED */
507 break;
508
509
510 /*
511 * kill the program
512 */
513 case 'k' :
514 break; /* do nothing */
515
516
517 /*
518 * Reset the whole machine (FIXME: system dependent)
519 */
520 case 'r':
521 break;
522
523
524 /*
525 * Step to next instruction
526 */
527 case 's':
528 /*
529 * There is no single step insn in the MIPS ISA, so we
530 * use breakpoints and continue, instead.
531 */
532 single_step(regs);
533 flush_cache_all();
534 return;
535 /* NOTREACHED */
536
537 }
538 break;
539
540 } /* switch */
541
542 /*
543 * reply to the request
544 */
545
546 putpacket(output_buffer);
547
548 } /* while */
549 }
550
551 /*
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
555 * the debugger.
556 */
557 void breakpoint(void)
558 {
559 if (!gdb_stub_initialised)
560 return;
561 __asm__ __volatile__(
562 ".globl breakinst\n"
563 "breakinst:\t.word %0\n\t"
564 :
565 : "i" (S390_BREAKPOINT_U16)
566 :
567 );
568 }
569
570
571
572
573
574
575
576