1 /* $Id: sparc-stub.c,v 1.25 1999/07/23 01:56:13 davem Exp $
2 * sparc-stub.c: KGDB support for the Linux kernel.
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
11 /****************************************************************************
13 THIS SOFTWARE IS NOT COPYRIGHTED
15 HP offers the following for use in the public domain. HP makes no
16 warranty with regard to the software or its performance and the
17 user accepts the software "AS IS" with all faults.
19 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
20 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 ****************************************************************************/
25 /****************************************************************************
26 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
28 * Module name: remcom.c $
30 * Date: 91/03/09 12:29:49 $
31 * Contributor: Lake Stevens Instrument Division$
33 * Description: low level support for gdb debugger. $
35 * Considerations: only works on target hardware $
37 * Written by: Glenn Engel $
38 * ModuleState: Experimental $
42 * Modified for SPARC by Stu Grossman, Cygnus Support.
44 * This code has been extensively tested on the Fujitsu SPARClite demo board.
46 * To enable debugger support, two things need to happen. One, a
47 * call to set_debug_traps() is necessary in order to allow any breakpoints
48 * or error conditions to be properly intercepted and reported to gdb.
49 * Two, a breakpoint needs to be generated to begin communication. This
50 * is most easily accomplished by a call to breakpoint(). Breakpoint()
51 * simulates a breakpoint by executing a trap #1.
55 * The following gdb commands are supported:
57 * command function Return value
59 * g return the value of the CPU registers hex data or ENN
60 * G set the value of the CPU registers OK or ENN
62 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
63 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
73 * ? What was the last sigval ? SNN (signal NN)
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
81 * $<packet info>#<checksum>.
84 * <packet info> :: <characters representing the command or response>
85 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer. '-' indicates a failed transfer.
93 * $m0,10#2a +$00010203040506070809101112131415#42
95 ****************************************************************************/
97 #include <linux/kernel.h>
98 #include <linux/string.h>
100 #include <linux/smp.h>
101 #include <linux/smp_lock.h>
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/pgtable.h>
113 * external low-level support routines
116 extern void putDebugChar(char); /* write a single character */
117 extern char getDebugChar(void); /* read and return a single char */
120 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
121 * at least NUMREGBYTES*2 are needed for register packets
125 static int initialized
= 0; /* !0 means we've been initialized */
127 static const char hexchars
[]="0123456789abcdef";
131 /* Number of bytes of registers. */
132 #define NUMREGBYTES (NUMREGS * 4)
133 enum regnames
{G0
, G1
, G2
, G3
, G4
, G5
, G6
, G7
,
134 O0
, O1
, O2
, O3
, O4
, O5
, SP
, O7
,
135 L0
, L1
, L2
, L3
, L4
, L5
, L6
, L7
,
136 I0
, I1
, I2
, I3
, I4
, I5
, FP
, I7
,
138 F0
, F1
, F2
, F3
, F4
, F5
, F6
, F7
,
139 F8
, F9
, F10
, F11
, F12
, F13
, F14
, F15
,
140 F16
, F17
, F18
, F19
, F20
, F21
, F22
, F23
,
141 F24
, F25
, F26
, F27
, F28
, F29
, F30
, F31
,
142 Y
, PSR
, WIM
, TBR
, PC
, NPC
, FPSR
, CPSR
};
145 extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
147 unsigned long get_sun4cpte(unsigned long addr
)
151 __asm__
__volatile__("\n\tlda [%1] %2, %0\n\t" :
153 "r" (addr
), "i" (ASI_PTE
));
157 unsigned long get_sun4csegmap(unsigned long addr
)
161 __asm__
__volatile__("\n\tlduba [%1] %2, %0\n\t" :
163 "r" (addr
), "i" (ASI_SEGMAP
));
168 /* Have to sort this out. This cannot be done after initialization. */
169 static void flush_cache_all_nop(void) {}
172 /* Place where we save old trap entries for restoration */
173 struct tt_entry kgdb_savettable
[256];
174 typedef void (*trapfunc_t
)(void);
176 /* Helper routine for manipulation of kgdb_savettable */
177 static inline void copy_ttentry(struct tt_entry
*src
, struct tt_entry
*dest
)
179 dest
->inst_one
= src
->inst_one
;
180 dest
->inst_two
= src
->inst_two
;
181 dest
->inst_three
= src
->inst_three
;
182 dest
->inst_four
= src
->inst_four
;
185 /* Initialize the kgdb_savettable so that debugging can commence */
186 static void eh_init(void)
191 for(i
=0; i
< 256; i
++)
192 copy_ttentry(&sparc_ttable
[i
], &kgdb_savettable
[i
]);
193 restore_flags(flags
);
196 /* Install an exception handler for kgdb */
197 static void exceptionHandler(int tnum
, trapfunc_t trap_entry
)
199 unsigned long te_addr
= (unsigned long) trap_entry
;
202 /* We are dorking with a live trap table, all irqs off */
205 /* Make new vector */
206 sparc_ttable
[tnum
].inst_one
=
207 SPARC_BRANCH((unsigned long) te_addr
,
208 (unsigned long) &sparc_ttable
[tnum
].inst_one
);
209 sparc_ttable
[tnum
].inst_two
= SPARC_RD_PSR_L0
;
210 sparc_ttable
[tnum
].inst_three
= SPARC_NOP
;
211 sparc_ttable
[tnum
].inst_four
= SPARC_NOP
;
213 restore_flags(flags
);
216 /* Convert ch from a hex digit to an int */
218 hex(unsigned char ch
)
220 if (ch
>= 'a' && ch
<= 'f')
222 if (ch
>= '0' && ch
<= '9')
224 if (ch
>= 'A' && ch
<= 'F')
229 /* scan for the sequence $<data>#<checksum> */
231 getpacket(char *buffer
)
233 unsigned char checksum
;
234 unsigned char xmitcsum
;
240 /* wait around for the start character, ignore all other characters */
241 while ((ch
= (getDebugChar() & 0x7f)) != '$') ;
248 /* now, read until a # or end of buffer is found */
249 while (count
< BUFMAX
) {
250 ch
= getDebugChar() & 0x7f;
253 checksum
= checksum
+ ch
;
264 xmitcsum
= hex(getDebugChar() & 0x7f) << 4;
265 xmitcsum
|= hex(getDebugChar() & 0x7f);
266 if (checksum
!= xmitcsum
)
267 putDebugChar('-'); /* failed checksum */
269 putDebugChar('+'); /* successful transfer */
270 /* if a sequence char is present, reply the ID */
271 if (buffer
[2] == ':') {
272 putDebugChar(buffer
[0]);
273 putDebugChar(buffer
[1]);
274 /* remove sequence chars from buffer */
275 count
= strlen(buffer
);
276 for (i
=3; i
<= count
; i
++)
277 buffer
[i
-3] = buffer
[i
];
281 } while (checksum
!= xmitcsum
);
284 /* send the packet in buffer. */
287 putpacket(unsigned char *buffer
)
289 unsigned char checksum
;
291 unsigned char ch
, recv
;
293 /* $<packet info>#<checksum>. */
299 while ((ch
= buffer
[count
])) {
306 putDebugChar(hexchars
[checksum
>> 4]);
307 putDebugChar(hexchars
[checksum
& 0xf]);
308 recv
= getDebugChar();
309 } while ((recv
& 0x7f) != '+');
312 static char remcomInBuffer
[BUFMAX
];
313 static char remcomOutBuffer
[BUFMAX
];
315 /* Convert the memory pointed to by mem into hex, placing result in buf.
316 * Return a pointer to the last char put in buf (null), in case of mem fault,
320 static unsigned char *
321 mem2hex(char *mem
, char *buf
, int count
)
325 while (count
-- > 0) {
326 /* This assembler code is basically: ch = *mem++;
327 * except that we use the SPARC/Linux exception table
328 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
329 * to arrange for a "return 0" upon a memory fault
334 .section .fixup,#alloc,#execinstr
338 .section __ex_table, #alloc
342 : "=r" (mem
), "=r" (ch
) : "0" (mem
));
343 *buf
++ = hexchars
[ch
>> 4];
344 *buf
++ = hexchars
[ch
& 0xf];
351 /* convert the hex array pointed to by buf into binary to be placed in mem
352 * return a pointer to the character AFTER the last byte written.
355 hex2mem(char *buf
, char *mem
, int count
)
360 for (i
=0; i
<count
; i
++) {
362 ch
= hex(*buf
++) << 4;
364 /* Assembler code is *mem++ = ch; with return 0 on fault */
368 .section .fixup,#alloc,#execinstr
372 .section __ex_table, #alloc
376 : "=r" (mem
) : "r" (ch
) , "0" (mem
));
381 /* This table contains the mapping between SPARC hardware trap types, and
382 signals, which are primarily what GDB understands. It also indicates
383 which hardware traps we need to commandeer when initializing the stub. */
385 static struct hard_trap_info
387 unsigned char tt
; /* Trap type code for SPARC */
388 unsigned char signo
; /* Signal that we map this trap into */
389 } hard_trap_info
[] = {
390 {SP_TRAP_SBPT
, SIGTRAP
}, /* ta 1 - Linux/KGDB software breakpoint */
391 {0, 0} /* Must be last */
394 /* Set up exception handlers for tracing and breakpoints */
397 set_debug_traps(void)
399 struct hard_trap_info
*ht
;
404 /* Have to sort this out. This cannot be done after initialization. */
405 BTFIXUPSET_CALL(flush_cache_all
, flush_cache_all_nop
, BTFIXUPCALL_NOP
);
408 /* Initialize our copy of the Linux Sparc trap table */
411 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++) {
412 /* Only if it doesn't destroy our fault handlers */
413 if((ht
->tt
!= SP_TRAP_TFLT
) &&
414 (ht
->tt
!= SP_TRAP_DFLT
))
415 exceptionHandler(ht
->tt
, trap_low
);
418 /* In case GDB is started before us, ack any packets (presumably
419 * "$?#xx") sitting there.
421 * I've found this code causes more problems than it solves,
422 * so that's why it's commented out. GDB seems to work fine
423 * now starting either before or after the kernel -bwb
426 while((c
= getDebugChar()) != '$');
427 while((c
= getDebugChar()) != '#');
428 c
= getDebugChar(); /* eat first csum byte */
429 c
= getDebugChar(); /* eat second csum byte */
430 putDebugChar('+'); /* ack it */
433 initialized
= 1; /* connect! */
434 restore_flags(flags
);
437 /* Convert the SPARC hardware trap type code to a unix signal number. */
440 computeSignal(int tt
)
442 struct hard_trap_info
*ht
;
444 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++)
448 return SIGHUP
; /* default for things we don't know about */
452 * While we find nice hex chars, build an int.
453 * Return number of chars processed.
457 hexToInt(char **ptr
, int *intValue
)
465 hexValue
= hex(**ptr
);
469 *intValue
= (*intValue
<< 4) | hexValue
;
479 * This function does all command processing for interfacing to gdb. It
480 * returns 1 if you should skip the instruction at the trap address, 0
484 extern void breakinst(void);
487 handle_exception (unsigned long *registers
)
489 int tt
; /* Trap type */
496 /* First, we must force all of the windows to be spilled out */
498 asm("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 "save %sp, -64, %sp\n\t"
516 if (registers
[PC
] == (unsigned long)breakinst
) {
517 /* Skip over breakpoint trap insn */
518 registers
[PC
] = registers
[NPC
];
522 sp
= (unsigned long *)registers
[SP
];
524 tt
= (registers
[TBR
] >> 4) & 0xff;
526 /* reply to host that an exception has occurred */
527 sigval
= computeSignal(tt
);
528 ptr
= remcomOutBuffer
;
531 *ptr
++ = hexchars
[sigval
>> 4];
532 *ptr
++ = hexchars
[sigval
& 0xf];
534 *ptr
++ = hexchars
[PC
>> 4];
535 *ptr
++ = hexchars
[PC
& 0xf];
537 ptr
= mem2hex((char *)®isters
[PC
], ptr
, 4);
540 *ptr
++ = hexchars
[FP
>> 4];
541 *ptr
++ = hexchars
[FP
& 0xf];
543 ptr
= mem2hex((char *) (sp
+ 8 + 6), ptr
, 4); /* FP */
546 *ptr
++ = hexchars
[SP
>> 4];
547 *ptr
++ = hexchars
[SP
& 0xf];
549 ptr
= mem2hex((char *)&sp
, ptr
, 4);
552 *ptr
++ = hexchars
[NPC
>> 4];
553 *ptr
++ = hexchars
[NPC
& 0xf];
555 ptr
= mem2hex((char *)®isters
[NPC
], ptr
, 4);
558 *ptr
++ = hexchars
[O7
>> 4];
559 *ptr
++ = hexchars
[O7
& 0xf];
561 ptr
= mem2hex((char *)®isters
[O7
], ptr
, 4);
566 putpacket(remcomOutBuffer
);
568 /* XXX We may want to add some features dealing with poking the
569 * XXX page tables, the real ones on the srmmu, and what is currently
570 * XXX loaded in the sun4/sun4c tlb at this point in time. But this
571 * XXX also required hacking to the gdb sources directly...
575 remcomOutBuffer
[0] = 0;
577 getpacket(remcomInBuffer
);
578 switch (remcomInBuffer
[0]) {
580 remcomOutBuffer
[0] = 'S';
581 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
582 remcomOutBuffer
[2] = hexchars
[sigval
& 0xf];
583 remcomOutBuffer
[3] = 0;
587 /* toggle debug flag */
590 case 'g': /* return the value of the CPU registers */
592 ptr
= remcomOutBuffer
;
594 ptr
= mem2hex((char *)registers
, ptr
, 16 * 4);
596 ptr
= mem2hex((char *) (sp
+ 0), ptr
, 16 * 4);
598 memset(ptr
, '0', 32 * 8);
599 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
600 mem2hex((char *)®isters
[Y
], (ptr
+ 32 * 4 * 2), (8 * 4));
604 case 'G': /* set the value of the CPU registers - return OK */
606 unsigned long *newsp
, psr
;
608 psr
= registers
[PSR
];
610 ptr
= &remcomInBuffer
[1];
612 hex2mem(ptr
, (char *)registers
, 16 * 4);
614 hex2mem(ptr
+ 16 * 4 * 2, (char *) (sp
+ 0), 16 * 4);
615 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
616 hex2mem(ptr
+ 64 * 4 * 2, (char *)®isters
[Y
], 8 * 4);
618 /* See if the stack pointer has moved. If so,
619 * then copy the saved locals and ins to the
620 * new location. This keeps the window
621 * overflow and underflow routines happy.
624 newsp
= (unsigned long *)registers
[SP
];
626 sp
= memcpy(newsp
, sp
, 16 * 4);
628 /* Don't allow CWP to be modified. */
630 if (psr
!= registers
[PSR
])
631 registers
[PSR
] = (psr
& 0x1f) | (registers
[PSR
] & ~0x1f);
633 strcpy(remcomOutBuffer
,"OK");
637 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
638 /* Try to read %x,%x. */
640 ptr
= &remcomInBuffer
[1];
642 if (hexToInt(&ptr
, &addr
)
644 && hexToInt(&ptr
, &length
)) {
645 if (mem2hex((char *)addr
, remcomOutBuffer
, length
))
648 strcpy (remcomOutBuffer
, "E03");
650 strcpy(remcomOutBuffer
,"E01");
654 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
655 /* Try to read '%x,%x:'. */
657 ptr
= &remcomInBuffer
[1];
659 if (hexToInt(&ptr
, &addr
)
661 && hexToInt(&ptr
, &length
)
663 if (hex2mem(ptr
, (char *)addr
, length
)) {
664 strcpy(remcomOutBuffer
, "OK");
666 strcpy(remcomOutBuffer
, "E03");
669 strcpy(remcomOutBuffer
, "E02");
673 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
674 /* try to read optional parameter, pc unchanged if no parm */
676 ptr
= &remcomInBuffer
[1];
677 if (hexToInt(&ptr
, &addr
)) {
678 registers
[PC
] = addr
;
679 registers
[NPC
] = addr
+ 4;
682 /* Need to flush the instruction cache here, as we may have deposited a
683 * breakpoint, and the icache probably has no way of knowing that a data ref to
684 * some location may have changed something that is in the instruction cache.
690 /* kill the program */
691 case 'k' : /* do nothing */
693 case 'r': /* Reset */
699 /* reply to the request */
700 putpacket(remcomOutBuffer
);
704 /* This function will generate a breakpoint exception. It is used at the
705 beginning of a program to sync up with a debugger and can be used
706 otherwise as a quick means to stop program execution and "break" into
715 /* Again, watch those c-prefixes for ELF kernels */
716 #if defined(__svr4__) || defined(__ELF__)
717 asm(" .globl breakinst
722 asm(" .globl _breakinst