1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
81
82
83extern int putDebugChar(char c);
84extern char getDebugChar(void);
85extern void fltr_set_mem_err(void);
86extern void trap_low(void);
87
88
89
90
91extern void breakpoint(void);
92extern void breakinst(void);
93
94
95
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
107
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
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
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
145
146
147 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
148
149 checksum = 0;
150 xmitcsum = -1;
151 count = 0;
152
153
154
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('-');
176 else {
177 putDebugChar('+');
178
179
180
181
182
183 if (buffer[2] == ':') {
184 putDebugChar(buffer[0]);
185 putDebugChar(buffer[1]);
186
187
188
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
202
203static void putpacket(char *buffer)
204{
205 unsigned char checksum;
206 int count;
207 unsigned char ch;
208
209
210
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
237
238
239
240
241
242static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
243{
244 unsigned char ch;
245
246
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
259
260 return buf;
261}
262
263
264
265
266
267static char *hex2mem(char *buf, char *mem, int count, int may_fault)
268{
269 int i;
270 unsigned char ch;
271
272
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
284
285 return mem;
286}
287
288
289
290
291
292
293void set_debug_traps(void)
294{
295
296 unsigned char c;
297
298
299
300
301
302
303 while((c = getDebugChar()) != '$');
304 while((c = getDebugChar()) != '#');
305 c = getDebugChar();
306 c = getDebugChar();
307 putDebugChar('+');
308
309 gdb_stub_initialised = TRUE;
310
311}
312
313
314
315
316
317
318
319
320extern void fltr_set_mem_err(void)
321{
322
323}
324
325
326
327
328
329
330static 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
352void 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
368void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
369{
370 restore_fp_regs1(®s->fp_regs);
371}
372
373void gdb_stub_send_signal(int sigval)
374{
375 char *ptr;
376 ptr = output_buffer;
377
378
379
380
381 *ptr++ = 'S';
382 *ptr++ = hexchars[sigval >> 4];
383 *ptr++ = hexchars[sigval & 0xf];
384 *ptr++ = 0;
385 putpacket(output_buffer);
386}
387
388
389
390
391
392
393void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
394{
395 int trap;
396 int addr;
397 int length;
398 char *ptr;
399 unsigned long *stack;
400
401
402
403
404
405 send_signal(sigval);
406
407
408
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
422 break;
423
424
425
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
437
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
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
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
487
488 case 'c':
489
490
491 ptr = &input_buffer[1];
492 if (hexToInt(&ptr, &addr))
493 regs->cp0_epc = addr;
494
495
496
497
498
499
500
501
502
503
504 flush_cache_all();
505 return;
506
507 break;
508
509
510
511
512
513 case 'k' :
514 break;
515
516
517
518
519
520 case 'r':
521 break;
522
523
524
525
526
527 case 's':
528
529
530
531
532 single_step(regs);
533 flush_cache_all();
534 return;
535
536
537 }
538 break;
539
540 }
541
542
543
544
545
546 putpacket(output_buffer);
547
548 }
549}
550
551
552
553
554
555
556
557void 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