1/* $Id: sparc-stub.c,v 1.1.1.1 2007/08/03 18:52:17 Exp $
2 * sparc-stub.c:  KGDB support for the Linux kernel.
3 *
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 *
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
9 */
10
11/****************************************************************************
12
13		THIS SOFTWARE IS NOT COPYRIGHTED
14
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.
18
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.
22
23****************************************************************************/
24
25/****************************************************************************
26 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 Exp $
27 *
28 *  Module name: remcom.c $
29 *  Revision: 1.34 $
30 *  Date: 91/03/09 12:29:49 $
31 *  Contributor:     Lake Stevens Instrument Division$
32 *
33 *  Description:     low level support for gdb debugger. $
34 *
35 *  Considerations:  only works on target hardware $
36 *
37 *  Written by:      Glenn Engel $
38 *  ModuleState:     Experimental $
39 *
40 *  NOTES:           See Below $
41 *
42 *  Modified for SPARC by Stu Grossman, Cygnus Support.
43 *
44 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
45 *
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.
52 *
53 *************
54 *
55 *    The following gdb commands are supported:
56 *
57 * command          function                               Return value
58 *
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
61 *
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
64 *
65 *    c             Resume at current address              SNN   ( signal NN)
66 *    cAA..AA       Continue at address AA..AA             SNN
67 *
68 *    s             Step one instruction                   SNN
69 *    sAA..AA       Step one instruction from AA..AA       SNN
70 *
71 *    k             kill
72 *
73 *    ?             What was the last sigval ?             SNN   (signal NN)
74 *
75 *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
76 *							   baud rate
77 *
78 * All commands and responses are sent with a packet which includes a
79 * checksum.  A packet consists of
80 *
81 * $<packet info>#<checksum>.
82 *
83 * where
84 * <packet info> :: <characters representing the command or response>
85 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
86 *
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
89 *
90 * Example:
91 *
92 * Host:                  Reply:
93 * $m0,10#2a               +$00010203040506070809101112131415#42
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 * external low-level support routines
117 */
118
119extern void putDebugChar(char);   /* write a single character      */
120extern char getDebugChar(void);   /* read and return a single char */
121
122/*
123 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
124 * at least NUMREGBYTES*2 are needed for register packets
125 */
126#define BUFMAX 2048
127
128static int initialized;	/* !0 means we've been initialized */
129
130static const char hexchars[]="0123456789abcdef";
131
132#define NUMREGS 72
133
134/* Number of bytes of registers.  */
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);  /* In arch/sparc/kernel/entry.S */
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
171/* Place where we save old trap entries for restoration */
172struct tt_entry kgdb_savettable[256];
173typedef void (*trapfunc_t)(void);
174
175/* Helper routine for manipulation of kgdb_savettable */
176static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
177{
178	dest->inst_one = src->inst_one;
179	dest->inst_two = src->inst_two;
180	dest->inst_three = src->inst_three;
181	dest->inst_four = src->inst_four;
182}
183
184/* Initialize the kgdb_savettable so that debugging can commence */
185static void eh_init(void)
186{
187	int i;
188
189	for(i=0; i < 256; i++)
190		copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
191}
192
193/* Install an exception handler for kgdb */
194static void exceptionHandler(int tnum, trapfunc_t trap_entry)
195{
196	unsigned long te_addr = (unsigned long) trap_entry;
197
198	/* Make new vector */
199	sparc_ttable[tnum].inst_one =
200		SPARC_BRANCH((unsigned long) te_addr,
201			     (unsigned long) &sparc_ttable[tnum].inst_one);
202	sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
203	sparc_ttable[tnum].inst_three = SPARC_NOP;
204	sparc_ttable[tnum].inst_four = SPARC_NOP;
205}
206
207/* Convert ch from a hex digit to an int */
208static int
209hex(unsigned char ch)
210{
211	if (ch >= 'a' && ch <= 'f')
212		return ch-'a'+10;
213	if (ch >= '0' && ch <= '9')
214		return ch-'0';
215	if (ch >= 'A' && ch <= 'F')
216		return ch-'A'+10;
217	return -1;
218}
219
220/* scan for the sequence $<data>#<checksum>     */
221static void
222getpacket(char *buffer)
223{
224	unsigned char checksum;
225	unsigned char xmitcsum;
226	int i;
227	int count;
228	unsigned char ch;
229
230	do {
231		/* wait around for the start character, ignore all other characters */
232		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
233
234		checksum = 0;
235		xmitcsum = -1;
236
237		count = 0;
238
239		/* now, read until a # or end of buffer is found */
240		while (count < BUFMAX) {
241			ch = getDebugChar() & 0x7f;
242			if (ch == '#')
243				break;
244			checksum = checksum + ch;
245			buffer[count] = ch;
246			count = count + 1;
247		}
248
249		if (count >= BUFMAX)
250			continue;
251
252		buffer[count] = 0;
253
254		if (ch == '#') {
255			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
256			xmitcsum |= hex(getDebugChar() & 0x7f);
257			if (checksum != xmitcsum)
258				putDebugChar('-');	/* failed checksum */
259			else {
260				putDebugChar('+'); /* successful transfer */
261				/* if a sequence char is present, reply the ID */
262				if (buffer[2] == ':') {
263					putDebugChar(buffer[0]);
264					putDebugChar(buffer[1]);
265					/* remove sequence chars from buffer */
266					count = strlen(buffer);
267					for (i=3; i <= count; i++)
268						buffer[i-3] = buffer[i];
269				}
270			}
271		}
272	} while (checksum != xmitcsum);
273}
274
275/* send the packet in buffer.  */
276
277static void
278putpacket(unsigned char *buffer)
279{
280	unsigned char checksum;
281	int count;
282	unsigned char ch, recv;
283
284	/*  $<packet info>#<checksum>. */
285	do {
286		putDebugChar('$');
287		checksum = 0;
288		count = 0;
289
290		while ((ch = buffer[count])) {
291			putDebugChar(ch);
292			checksum += ch;
293			count += 1;
294		}
295
296		putDebugChar('#');
297		putDebugChar(hexchars[checksum >> 4]);
298		putDebugChar(hexchars[checksum & 0xf]);
299		recv = getDebugChar();
300	} while ((recv & 0x7f) != '+');
301}
302
303static char remcomInBuffer[BUFMAX];
304static char remcomOutBuffer[BUFMAX];
305
306/* Convert the memory pointed to by mem into hex, placing result in buf.
307 * Return a pointer to the last char put in buf (null), in case of mem fault,
308 * return 0.
309 */
310
311static unsigned char *
312mem2hex(char *mem, char *buf, int count)
313{
314	unsigned char ch;
315
316	while (count-- > 0) {
317		/* This assembler code is basically:  ch = *mem++;
318		 * except that we use the SPARC/Linux exception table
319		 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
320		 * to arrange for a "return 0" upon a memory fault
321		 */
322		__asm__(
323			"\n1:\n\t"
324			"ldub [%0], %1\n\t"
325			"inc %0\n\t"
326			".section .fixup,#alloc,#execinstr\n\t"
327			".align 4\n"
328			"2:\n\t"
329			"retl\n\t"
330			" mov 0, %%o0\n\t"
331			".section __ex_table, #alloc\n\t"
332			".align 4\n\t"
333			".word 1b, 2b\n\t"
334			".text\n"
335			: "=r" (mem), "=r" (ch) : "0" (mem));
336		*buf++ = hexchars[ch >> 4];
337		*buf++ = hexchars[ch & 0xf];
338	}
339
340	*buf = 0;
341	return buf;
342}
343
344/* convert the hex array pointed to by buf into binary to be placed in mem
345 * return a pointer to the character AFTER the last byte written.
346*/
347static char *
348hex2mem(char *buf, char *mem, int count)
349{
350	int i;
351	unsigned char ch;
352
353	for (i=0; i<count; i++) {
354
355		ch = hex(*buf++) << 4;
356		ch |= hex(*buf++);
357		/* Assembler code is   *mem++ = ch;   with return 0 on fault */
358		__asm__(
359			"\n1:\n\t"
360			"stb %1, [%0]\n\t"
361			"inc %0\n\t"
362			".section .fixup,#alloc,#execinstr\n\t"
363			".align 4\n"
364			"2:\n\t"
365			"retl\n\t"
366			" mov 0, %%o0\n\t"
367			".section __ex_table, #alloc\n\t"
368			".align 4\n\t"
369			".word 1b, 2b\n\t"
370			".text\n"
371			: "=r" (mem) : "r" (ch) , "0" (mem));
372	}
373	return mem;
374}
375
376/* This table contains the mapping between SPARC hardware trap types, and
377   signals, which are primarily what GDB understands.  It also indicates
378   which hardware traps we need to commandeer when initializing the stub. */
379
380static struct hard_trap_info
381{
382  unsigned char tt;		/* Trap type code for SPARC */
383  unsigned char signo;		/* Signal that we map this trap into */
384} hard_trap_info[] = {
385  {SP_TRAP_SBPT, SIGTRAP},      /* ta 1 - Linux/KGDB software breakpoint */
386  {0, 0}			/* Must be last */
387};
388
389/* Set up exception handlers for tracing and breakpoints */
390
391void
392set_debug_traps(void)
393{
394	struct hard_trap_info *ht;
395	unsigned long flags;
396
397	local_irq_save(flags);
398
399	/* Initialize our copy of the Linux Sparc trap table */
400	eh_init();
401
402	for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
403		/* Only if it doesn't destroy our fault handlers */
404		if((ht->tt != SP_TRAP_TFLT) &&
405		   (ht->tt != SP_TRAP_DFLT))
406			exceptionHandler(ht->tt, trap_low);
407	}
408
409	/* In case GDB is started before us, ack any packets (presumably
410	 * "$?#xx") sitting there.
411	 *
412	 * I've found this code causes more problems than it solves,
413	 * so that's why it's commented out.  GDB seems to work fine
414	 * now starting either before or after the kernel   -bwb
415	 */
416
417	initialized = 1; /* connect! */
418	local_irq_restore(flags);
419}
420
421/* Convert the SPARC hardware trap type code to a unix signal number. */
422
423static int
424computeSignal(int tt)
425{
426	struct hard_trap_info *ht;
427
428	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
429		if (ht->tt == tt)
430			return ht->signo;
431
432	return SIGHUP;         /* default for things we don't know about */
433}
434
435/*
436 * While we find nice hex chars, build an int.
437 * Return number of chars processed.
438 */
439
440static int
441hexToInt(char **ptr, int *intValue)
442{
443	int numChars = 0;
444	int hexValue;
445
446	*intValue = 0;
447
448	while (**ptr) {
449		hexValue = hex(**ptr);
450		if (hexValue < 0)
451			break;
452
453		*intValue = (*intValue << 4) | hexValue;
454		numChars ++;
455
456		(*ptr)++;
457	}
458
459	return (numChars);
460}
461
462/*
463 * This function does all command processing for interfacing to gdb.  It
464 * returns 1 if you should skip the instruction at the trap address, 0
465 * otherwise.
466 */
467
468extern void breakinst(void);
469
470void
471handle_exception (unsigned long *registers)
472{
473	int tt;       /* Trap type */
474	int sigval;
475	int addr;
476	int length;
477	char *ptr;
478	unsigned long *sp;
479
480	/* First, we must force all of the windows to be spilled out */
481
482	asm("save %sp, -64, %sp\n\t"
483	    "save %sp, -64, %sp\n\t"
484	    "save %sp, -64, %sp\n\t"
485	    "save %sp, -64, %sp\n\t"
486	    "save %sp, -64, %sp\n\t"
487	    "save %sp, -64, %sp\n\t"
488	    "save %sp, -64, %sp\n\t"
489	    "save %sp, -64, %sp\n\t"
490	    "restore\n\t"
491	    "restore\n\t"
492	    "restore\n\t"
493	    "restore\n\t"
494	    "restore\n\t"
495	    "restore\n\t"
496	    "restore\n\t"
497	    "restore\n\t");
498
499	lock_kernel();
500	if (registers[PC] == (unsigned long)breakinst) {
501		/* Skip over breakpoint trap insn */
502		registers[PC] = registers[NPC];
503		registers[NPC] += 4;
504	}
505
506	sp = (unsigned long *)registers[SP];
507
508	tt = (registers[TBR] >> 4) & 0xff;
509
510	/* reply to host that an exception has occurred */
511	sigval = computeSignal(tt);
512	ptr = remcomOutBuffer;
513
514	*ptr++ = 'T';
515	*ptr++ = hexchars[sigval >> 4];
516	*ptr++ = hexchars[sigval & 0xf];
517
518	*ptr++ = hexchars[PC >> 4];
519	*ptr++ = hexchars[PC & 0xf];
520	*ptr++ = ':';
521	ptr = mem2hex((char *)&registers[PC], ptr, 4);
522	*ptr++ = ';';
523
524	*ptr++ = hexchars[FP >> 4];
525	*ptr++ = hexchars[FP & 0xf];
526	*ptr++ = ':';
527	ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
528	*ptr++ = ';';
529
530	*ptr++ = hexchars[SP >> 4];
531	*ptr++ = hexchars[SP & 0xf];
532	*ptr++ = ':';
533	ptr = mem2hex((char *)&sp, ptr, 4);
534	*ptr++ = ';';
535
536	*ptr++ = hexchars[NPC >> 4];
537	*ptr++ = hexchars[NPC & 0xf];
538	*ptr++ = ':';
539	ptr = mem2hex((char *)&registers[NPC], ptr, 4);
540	*ptr++ = ';';
541
542	*ptr++ = hexchars[O7 >> 4];
543	*ptr++ = hexchars[O7 & 0xf];
544	*ptr++ = ':';
545	ptr = mem2hex((char *)&registers[O7], ptr, 4);
546	*ptr++ = ';';
547
548	*ptr++ = 0;
549
550	putpacket(remcomOutBuffer);
551
552
553	while (1) {
554		remcomOutBuffer[0] = 0;
555
556		getpacket(remcomInBuffer);
557		switch (remcomInBuffer[0]) {
558		case '?':
559			remcomOutBuffer[0] = 'S';
560			remcomOutBuffer[1] = hexchars[sigval >> 4];
561			remcomOutBuffer[2] = hexchars[sigval & 0xf];
562			remcomOutBuffer[3] = 0;
563			break;
564
565		case 'd':
566			/* toggle debug flag */
567			break;
568
569		case 'g':		/* return the value of the CPU registers */
570		{
571			ptr = remcomOutBuffer;
572			/* G & O regs */
573			ptr = mem2hex((char *)registers, ptr, 16 * 4);
574			/* L & I regs */
575			ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
576			/* Floating point */
577			memset(ptr, '0', 32 * 8);
578			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
579			mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
580		}
581			break;
582
583		case 'G':	   /* set the value of the CPU registers - return OK */
584		{
585			unsigned long *newsp, psr;
586
587			psr = registers[PSR];
588
589			ptr = &remcomInBuffer[1];
590			/* G & O regs */
591			hex2mem(ptr, (char *)registers, 16 * 4);
592			/* L & I regs */
593			hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
594			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
595			hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
596
597			/* See if the stack pointer has moved.  If so,
598			 * then copy the saved locals and ins to the
599			 * new location.  This keeps the window
600			 * overflow and underflow routines happy.
601			 */
602
603			newsp = (unsigned long *)registers[SP];
604			if (sp != newsp)
605				sp = memcpy(newsp, sp, 16 * 4);
606
607			/* Don't allow CWP to be modified. */
608
609			if (psr != registers[PSR])
610				registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
611
612			strcpy(remcomOutBuffer,"OK");
613		}
614			break;
615
616		case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
617			/* Try to read %x,%x.  */
618
619			ptr = &remcomInBuffer[1];
620
621			if (hexToInt(&ptr, &addr)
622			    && *ptr++ == ','
623			    && hexToInt(&ptr, &length))	{
624				if (mem2hex((char *)addr, remcomOutBuffer, length))
625					break;
626
627				strcpy (remcomOutBuffer, "E03");
628			} else {
629				strcpy(remcomOutBuffer,"E01");
630			}
631			break;
632
633		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
634			/* Try to read '%x,%x:'.  */
635
636			ptr = &remcomInBuffer[1];
637
638			if (hexToInt(&ptr, &addr)
639			    && *ptr++ == ','
640			    && hexToInt(&ptr, &length)
641			    && *ptr++ == ':') {
642				if (hex2mem(ptr, (char *)addr, length)) {
643					strcpy(remcomOutBuffer, "OK");
644				} else {
645					strcpy(remcomOutBuffer, "E03");
646				}
647			} else {
648				strcpy(remcomOutBuffer, "E02");
649			}
650			break;
651
652		case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
653			/* try to read optional parameter, pc unchanged if no parm */
654
655			ptr = &remcomInBuffer[1];
656			if (hexToInt(&ptr, &addr)) {
657				registers[PC] = addr;
658				registers[NPC] = addr + 4;
659			}
660
661/* Need to flush the instruction cache here, as we may have deposited a
662 * breakpoint, and the icache probably has no way of knowing that a data ref to
663 * some location may have changed something that is in the instruction cache.
664 */
665			flush_cache_all();
666			unlock_kernel();
667			return;
668
669			/* kill the program */
670		case 'k' :		/* do nothing */
671			break;
672		case 'r':		/* Reset */
673			asm ("call 0\n\t"
674			     "nop\n\t");
675			break;
676		}			/* switch */
677
678		/* reply to the request */
679		putpacket(remcomOutBuffer);
680	} /* while(1) */
681}
682
683/* This function will generate a breakpoint exception.  It is used at the
684   beginning of a program to sync up with a debugger and can be used
685   otherwise as a quick means to stop program execution and "break" into
686   the debugger. */
687
688void
689breakpoint(void)
690{
691	if (!initialized)
692		return;
693
694	/* Again, watch those c-prefixes for ELF kernels */
695#if defined(__svr4__) || defined(__ELF__)
696	asm(".globl breakinst\n"
697	    "breakinst:\n\t"
698	    "ta 1\n");
699#else
700	asm(".globl _breakinst\n"
701	    "_breakinst:\n\t"
702	    "ta 1\n");
703#endif
704}
705