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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97#include <linux/kernel.h>
98#include <linux/string.h>
99#include <linux/mm.h>
100#include <linux/smp.h>
101#include <linux/smp_lock.h>
102
103#include <asm/system.h>
104#include <asm/signal.h>
105#include <asm/oplib.h>
106#include <asm/head.h>
107#include <asm/traps.h>
108#include <asm/vac-ops.h>
109#include <asm/kgdb.h>
110#include <asm/pgalloc.h>
111#include <asm/pgtable.h>
112#include <asm/cacheflush.h>
113
114
115
116
117
118
119extern void putDebugChar(char);
120extern char getDebugChar(void);
121
122
123
124
125
126#define BUFMAX 2048
127
128static int initialized;
129
130static const char hexchars[]="0123456789abcdef";
131
132#define NUMREGS 72
133
134
135#define NUMREGBYTES (NUMREGS * 4)
136enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
137 O0, O1, O2, O3, O4, O5, SP, O7,
138 L0, L1, L2, L3, L4, L5, L6, L7,
139 I0, I1, I2, I3, I4, I5, FP, I7,
140
141 F0, F1, F2, F3, F4, F5, F6, F7,
142 F8, F9, F10, F11, F12, F13, F14, F15,
143 F16, F17, F18, F19, F20, F21, F22, F23,
144 F24, F25, F26, F27, F28, F29, F30, F31,
145 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
146
147
148extern void trap_low(void);
149
150unsigned long get_sun4cpte(unsigned long addr)
151{
152 unsigned long entry;
153
154 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
155 "=r" (entry) :
156 "r" (addr), "i" (ASI_PTE));
157 return entry;
158}
159
160unsigned long get_sun4csegmap(unsigned long addr)
161{
162 unsigned long entry;
163
164 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
165 "=r" (entry) :
166 "r" (addr), "i" (ASI_SEGMAP));
167 return entry;
168}
169
170#if 0
171
172static void flush_cache_all_nop(void) {}
173#endif
174
175
176struct tt_entry kgdb_savettable[256];
177typedef void (*trapfunc_t)(void);
178
179
180static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
181{
182 dest->inst_one = src->inst_one;
183 dest->inst_two = src->inst_two;
184 dest->inst_three = src->inst_three;
185 dest->inst_four = src->inst_four;
186}
187
188
189static void eh_init(void)
190{
191 int i;
192
193 for(i=0; i < 256; i++)
194 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
195}
196
197
198static void exceptionHandler(int tnum, trapfunc_t trap_entry)
199{
200 unsigned long te_addr = (unsigned long) trap_entry;
201
202
203 sparc_ttable[tnum].inst_one =
204 SPARC_BRANCH((unsigned long) te_addr,
205 (unsigned long) &sparc_ttable[tnum].inst_one);
206 sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
207 sparc_ttable[tnum].inst_three = SPARC_NOP;
208 sparc_ttable[tnum].inst_four = SPARC_NOP;
209}
210
211
212static int
213hex(unsigned char ch)
214{
215 if (ch >= 'a' && ch <= 'f')
216 return ch-'a'+10;
217 if (ch >= '0' && ch <= '9')
218 return ch-'0';
219 if (ch >= 'A' && ch <= 'F')
220 return ch-'A'+10;
221 return -1;
222}
223
224
225static void
226getpacket(char *buffer)
227{
228 unsigned char checksum;
229 unsigned char xmitcsum;
230 int i;
231 int count;
232 unsigned char ch;
233
234 do {
235
236 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
237
238 checksum = 0;
239 xmitcsum = -1;
240
241 count = 0;
242
243
244 while (count < BUFMAX) {
245 ch = getDebugChar() & 0x7f;
246 if (ch == '#')
247 break;
248 checksum = checksum + ch;
249 buffer[count] = ch;
250 count = count + 1;
251 }
252
253 if (count >= BUFMAX)
254 continue;
255
256 buffer[count] = 0;
257
258 if (ch == '#') {
259 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
260 xmitcsum |= hex(getDebugChar() & 0x7f);
261 if (checksum != xmitcsum)
262 putDebugChar('-');
263 else {
264 putDebugChar('+');
265
266 if (buffer[2] == ':') {
267 putDebugChar(buffer[0]);
268 putDebugChar(buffer[1]);
269
270 count = strlen(buffer);
271 for (i=3; i <= count; i++)
272 buffer[i-3] = buffer[i];
273 }
274 }
275 }
276 } while (checksum != xmitcsum);
277}
278
279
280
281static void
282putpacket(unsigned char *buffer)
283{
284 unsigned char checksum;
285 int count;
286 unsigned char ch, recv;
287
288
289 do {
290 putDebugChar('$');
291 checksum = 0;
292 count = 0;
293
294 while ((ch = buffer[count])) {
295 putDebugChar(ch);
296 checksum += ch;
297 count += 1;
298 }
299
300 putDebugChar('#');
301 putDebugChar(hexchars[checksum >> 4]);
302 putDebugChar(hexchars[checksum & 0xf]);
303 recv = getDebugChar();
304 } while ((recv & 0x7f) != '+');
305}
306
307static char remcomInBuffer[BUFMAX];
308static char remcomOutBuffer[BUFMAX];
309
310
311
312
313
314
315static unsigned char *
316mem2hex(char *mem, char *buf, int count)
317{
318 unsigned char ch;
319
320 while (count-- > 0) {
321
322
323
324
325
326 __asm__(
327 "\n1:\n\t"
328 "ldub [%0], %1\n\t"
329 "inc %0\n\t"
330 ".section .fixup,#alloc,#execinstr\n\t"
331 ".align 4\n"
332 "2:\n\t"
333 "retl\n\t"
334 " mov 0, %%o0\n\t"
335 ".section __ex_table, #alloc\n\t"
336 ".align 4\n\t"
337 ".word 1b, 2b\n\t"
338 ".text\n"
339 : "=r" (mem), "=r" (ch) : "0" (mem));
340 *buf++ = hexchars[ch >> 4];
341 *buf++ = hexchars[ch & 0xf];
342 }
343
344 *buf = 0;
345 return buf;
346}
347
348
349
350
351static char *
352hex2mem(char *buf, char *mem, int count)
353{
354 int i;
355 unsigned char ch;
356
357 for (i=0; i<count; i++) {
358
359 ch = hex(*buf++) << 4;
360 ch |= hex(*buf++);
361
362 __asm__(
363 "\n1:\n\t"
364 "stb %1, [%0]\n\t"
365 "inc %0\n\t"
366 ".section .fixup,#alloc,#execinstr\n\t"
367 ".align 4\n"
368 "2:\n\t"
369 "retl\n\t"
370 " mov 0, %%o0\n\t"
371 ".section __ex_table, #alloc\n\t"
372 ".align 4\n\t"
373 ".word 1b, 2b\n\t"
374 ".text\n"
375 : "=r" (mem) : "r" (ch) , "0" (mem));
376 }
377 return mem;
378}
379
380
381
382
383
384static struct hard_trap_info
385{
386 unsigned char tt;
387 unsigned char signo;
388} hard_trap_info[] = {
389 {SP_TRAP_SBPT, SIGTRAP},
390 {0, 0}
391};
392
393
394
395void
396set_debug_traps(void)
397{
398 struct hard_trap_info *ht;
399 unsigned long flags;
400
401 local_irq_save(flags);
402#if 0
403
404 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
405#endif
406
407
408 eh_init();
409
410 for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
411
412 if((ht->tt != SP_TRAP_TFLT) &&
413 (ht->tt != SP_TRAP_DFLT))
414 exceptionHandler(ht->tt, trap_low);
415 }
416
417
418
419
420
421
422
423
424#if 0
425 while((c = getDebugChar()) != '$');
426 while((c = getDebugChar()) != '#');
427 c = getDebugChar();
428 c = getDebugChar();
429 putDebugChar('+');
430#endif
431
432 initialized = 1;
433 local_irq_restore(flags);
434}
435
436
437
438static int
439computeSignal(int tt)
440{
441 struct hard_trap_info *ht;
442
443 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
444 if (ht->tt == tt)
445 return ht->signo;
446
447 return SIGHUP;
448}
449
450
451
452
453
454
455static int
456hexToInt(char **ptr, int *intValue)
457{
458 int numChars = 0;
459 int hexValue;
460
461 *intValue = 0;
462
463 while (**ptr) {
464 hexValue = hex(**ptr);
465 if (hexValue < 0)
466 break;
467
468 *intValue = (*intValue << 4) | hexValue;
469 numChars ++;
470
471 (*ptr)++;
472 }
473
474 return (numChars);
475}
476
477
478
479
480
481
482
483extern void breakinst(void);
484
485void
486handle_exception (unsigned long *registers)
487{
488 int tt;
489 int sigval;
490 int addr;
491 int length;
492 char *ptr;
493 unsigned long *sp;
494
495
496
497 asm("save %sp, -64, %sp\n\t"
498 "save %sp, -64, %sp\n\t"
499 "save %sp, -64, %sp\n\t"
500 "save %sp, -64, %sp\n\t"
501 "save %sp, -64, %sp\n\t"
502 "save %sp, -64, %sp\n\t"
503 "save %sp, -64, %sp\n\t"
504 "save %sp, -64, %sp\n\t"
505 "restore\n\t"
506 "restore\n\t"
507 "restore\n\t"
508 "restore\n\t"
509 "restore\n\t"
510 "restore\n\t"
511 "restore\n\t"
512 "restore\n\t");
513
514 lock_kernel();
515 if (registers[PC] == (unsigned long)breakinst) {
516
517 registers[PC] = registers[NPC];
518 registers[NPC] += 4;
519 }
520
521 sp = (unsigned long *)registers[SP];
522
523 tt = (registers[TBR] >> 4) & 0xff;
524
525
526 sigval = computeSignal(tt);
527 ptr = remcomOutBuffer;
528
529 *ptr++ = 'T';
530 *ptr++ = hexchars[sigval >> 4];
531 *ptr++ = hexchars[sigval & 0xf];
532
533 *ptr++ = hexchars[PC >> 4];
534 *ptr++ = hexchars[PC & 0xf];
535 *ptr++ = ':';
536 ptr = mem2hex((char *)®isters[PC], ptr, 4);
537 *ptr++ = ';';
538
539 *ptr++ = hexchars[FP >> 4];
540 *ptr++ = hexchars[FP & 0xf];
541 *ptr++ = ':';
542 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4);
543 *ptr++ = ';';
544
545 *ptr++ = hexchars[SP >> 4];
546 *ptr++ = hexchars[SP & 0xf];
547 *ptr++ = ':';
548 ptr = mem2hex((char *)&sp, ptr, 4);
549 *ptr++ = ';';
550
551 *ptr++ = hexchars[NPC >> 4];
552 *ptr++ = hexchars[NPC & 0xf];
553 *ptr++ = ':';
554 ptr = mem2hex((char *)®isters[NPC], ptr, 4);
555 *ptr++ = ';';
556
557 *ptr++ = hexchars[O7 >> 4];
558 *ptr++ = hexchars[O7 & 0xf];
559 *ptr++ = ':';
560 ptr = mem2hex((char *)®isters[O7], ptr, 4);
561 *ptr++ = ';';
562
563 *ptr++ = 0;
564
565 putpacket(remcomOutBuffer);
566
567
568
569
570
571
572
573 while (1) {
574 remcomOutBuffer[0] = 0;
575
576 getpacket(remcomInBuffer);
577 switch (remcomInBuffer[0]) {
578 case '?':
579 remcomOutBuffer[0] = 'S';
580 remcomOutBuffer[1] = hexchars[sigval >> 4];
581 remcomOutBuffer[2] = hexchars[sigval & 0xf];
582 remcomOutBuffer[3] = 0;
583 break;
584
585 case 'd':
586
587 break;
588
589 case 'g':
590 {
591 ptr = remcomOutBuffer;
592
593 ptr = mem2hex((char *)registers, ptr, 16 * 4);
594
595 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
596
597 memset(ptr, '0', 32 * 8);
598
599 mem2hex((char *)®isters[Y], (ptr + 32 * 4 * 2), (8 * 4));
600 }
601 break;
602
603 case 'G':
604 {
605 unsigned long *newsp, psr;
606
607 psr = registers[PSR];
608
609 ptr = &remcomInBuffer[1];
610
611 hex2mem(ptr, (char *)registers, 16 * 4);
612
613 hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
614
615 hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], 8 * 4);
616
617
618
619
620
621
622
623 newsp = (unsigned long *)registers[SP];
624 if (sp != newsp)
625 sp = memcpy(newsp, sp, 16 * 4);
626
627
628
629 if (psr != registers[PSR])
630 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
631
632 strcpy(remcomOutBuffer,"OK");
633 }
634 break;
635
636 case 'm':
637
638
639 ptr = &remcomInBuffer[1];
640
641 if (hexToInt(&ptr, &addr)
642 && *ptr++ == ','
643 && hexToInt(&ptr, &length)) {
644 if (mem2hex((char *)addr, remcomOutBuffer, length))
645 break;
646
647 strcpy (remcomOutBuffer, "E03");
648 } else {
649 strcpy(remcomOutBuffer,"E01");
650 }
651 break;
652
653 case 'M':
654
655
656 ptr = &remcomInBuffer[1];
657
658 if (hexToInt(&ptr, &addr)
659 && *ptr++ == ','
660 && hexToInt(&ptr, &length)
661 && *ptr++ == ':') {
662 if (hex2mem(ptr, (char *)addr, length)) {
663 strcpy(remcomOutBuffer, "OK");
664 } else {
665 strcpy(remcomOutBuffer, "E03");
666 }
667 } else {
668 strcpy(remcomOutBuffer, "E02");
669 }
670 break;
671
672 case 'c':
673
674
675 ptr = &remcomInBuffer[1];
676 if (hexToInt(&ptr, &addr)) {
677 registers[PC] = addr;
678 registers[NPC] = addr + 4;
679 }
680
681
682
683
684
685 flush_cache_all();
686 unlock_kernel();
687 return;
688
689
690 case 'k' :
691 break;
692 case 'r':
693 asm ("call 0\n\t"
694 "nop\n\t");
695 break;
696 }
697
698
699 putpacket(remcomOutBuffer);
700 }
701}
702
703
704
705
706
707
708void
709breakpoint(void)
710{
711 if (!initialized)
712 return;
713
714
715#if defined(__svr4__) || defined(__ELF__)
716 asm(".globl breakinst\n"
717 "breakinst:\n\t"
718 "ta 1\n");
719#else
720 asm(".globl _breakinst\n"
721 "_breakinst:\n\t"
722 "ta 1\n");
723#endif
724}
725