1 /* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem 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 glenne 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 /*
113  *
114  * external low-level support routines
115  */
116 
117 extern void putDebugChar(char);   /* write a single character      */
118 extern char getDebugChar(void);   /* read and return a single char */
119 
120 /*
121  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
122  * at least NUMREGBYTES*2 are needed for register packets
123  */
124 #define BUFMAX 2048
125 
126 static int initialized;	/* !0 means we've been initialized */
127 
128 static const char hexchars[]="0123456789abcdef";
129 
130 #define NUMREGS 72
131 
132 /* Number of bytes of registers.  */
133 #define NUMREGBYTES (NUMREGS * 4)
134 enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
135 		 O0, O1, O2, O3, O4, O5, SP, O7,
136 		 L0, L1, L2, L3, L4, L5, L6, L7,
137 		 I0, I1, I2, I3, I4, I5, FP, I7,
138 
139 		 F0, F1, F2, F3, F4, F5, F6, F7,
140 		 F8, F9, F10, F11, F12, F13, F14, F15,
141 		 F16, F17, F18, F19, F20, F21, F22, F23,
142 		 F24, F25, F26, F27, F28, F29, F30, F31,
143 		 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
144 
145 
146 extern void trap_low(void);  /* In arch/sparc/kernel/entry.S */
147 
get_sun4cpte(unsigned long addr)148 unsigned long get_sun4cpte(unsigned long addr)
149 {
150 	unsigned long entry;
151 
152 	__asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
153 			     "=r" (entry) :
154 			     "r" (addr), "i" (ASI_PTE));
155 	return entry;
156 }
157 
get_sun4csegmap(unsigned long addr)158 unsigned long get_sun4csegmap(unsigned long addr)
159 {
160 	unsigned long entry;
161 
162 	__asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
163 			     "=r" (entry) :
164 			     "r" (addr), "i" (ASI_SEGMAP));
165 	return entry;
166 }
167 
168 #if 0
169 /* Have to sort this out. This cannot be done after initialization. */
170 static void flush_cache_all_nop(void) {}
171 #endif
172 
173 /* Place where we save old trap entries for restoration */
174 struct tt_entry kgdb_savettable[256];
175 typedef void (*trapfunc_t)(void);
176 
177 /* Helper routine for manipulation of kgdb_savettable */
copy_ttentry(struct tt_entry * src,struct tt_entry * dest)178 static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
179 {
180 	dest->inst_one = src->inst_one;
181 	dest->inst_two = src->inst_two;
182 	dest->inst_three = src->inst_three;
183 	dest->inst_four = src->inst_four;
184 }
185 
186 /* Initialize the kgdb_savettable so that debugging can commence */
eh_init(void)187 static void eh_init(void)
188 {
189 	int i, flags;
190 
191 	save_and_cli(flags);
192 	for(i=0; i < 256; i++)
193 		copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
194 	restore_flags(flags);
195 }
196 
197 /* Install an exception handler for kgdb */
exceptionHandler(int tnum,trapfunc_t trap_entry)198 static void exceptionHandler(int tnum, trapfunc_t trap_entry)
199 {
200 	unsigned long te_addr = (unsigned long) trap_entry;
201 	int flags;
202 
203 	/* We are dorking with a live trap table, all irqs off */
204 	save_and_cli(flags);
205 
206 	/* Make new vector */
207 	sparc_ttable[tnum].inst_one =
208 		SPARC_BRANCH((unsigned long) te_addr,
209 			     (unsigned long) &sparc_ttable[tnum].inst_one);
210 	sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
211 	sparc_ttable[tnum].inst_three = SPARC_NOP;
212 	sparc_ttable[tnum].inst_four = SPARC_NOP;
213 
214 	restore_flags(flags);
215 }
216 
217 /* Convert ch from a hex digit to an int */
218 static int
hex(unsigned char ch)219 hex(unsigned char ch)
220 {
221 	if (ch >= 'a' && ch <= 'f')
222 		return ch-'a'+10;
223 	if (ch >= '0' && ch <= '9')
224 		return ch-'0';
225 	if (ch >= 'A' && ch <= 'F')
226 		return ch-'A'+10;
227 	return -1;
228 }
229 
230 /* scan for the sequence $<data>#<checksum>     */
231 static void
getpacket(char * buffer)232 getpacket(char *buffer)
233 {
234 	unsigned char checksum;
235 	unsigned char xmitcsum;
236 	int i;
237 	int count;
238 	unsigned char ch;
239 
240 	do {
241 		/* wait around for the start character, ignore all other characters */
242 		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
243 
244 		checksum = 0;
245 		xmitcsum = -1;
246 
247 		count = 0;
248 
249 		/* now, read until a # or end of buffer is found */
250 		while (count < BUFMAX) {
251 			ch = getDebugChar() & 0x7f;
252 			if (ch == '#')
253 				break;
254 			checksum = checksum + ch;
255 			buffer[count] = ch;
256 			count = count + 1;
257 		}
258 
259 		if (count >= BUFMAX)
260 			continue;
261 
262 		buffer[count] = 0;
263 
264 		if (ch == '#') {
265 			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
266 			xmitcsum |= hex(getDebugChar() & 0x7f);
267 			if (checksum != xmitcsum)
268 				putDebugChar('-');	/* failed checksum */
269 			else {
270 				putDebugChar('+'); /* successful transfer */
271 				/* if a sequence char is present, reply the ID */
272 				if (buffer[2] == ':') {
273 					putDebugChar(buffer[0]);
274 					putDebugChar(buffer[1]);
275 					/* remove sequence chars from buffer */
276 					count = strlen(buffer);
277 					for (i=3; i <= count; i++)
278 						buffer[i-3] = buffer[i];
279 				}
280 			}
281 		}
282 	} while (checksum != xmitcsum);
283 }
284 
285 /* send the packet in buffer.  */
286 
287 static void
putpacket(unsigned char * buffer)288 putpacket(unsigned char *buffer)
289 {
290 	unsigned char checksum;
291 	int count;
292 	unsigned char ch, recv;
293 
294 	/*  $<packet info>#<checksum>. */
295 	do {
296 		putDebugChar('$');
297 		checksum = 0;
298 		count = 0;
299 
300 		while ((ch = buffer[count])) {
301 			putDebugChar(ch);
302 			checksum += ch;
303 			count += 1;
304 		}
305 
306 		putDebugChar('#');
307 		putDebugChar(hexchars[checksum >> 4]);
308 		putDebugChar(hexchars[checksum & 0xf]);
309 		recv = getDebugChar();
310 	} while ((recv & 0x7f) != '+');
311 }
312 
313 static char remcomInBuffer[BUFMAX];
314 static char remcomOutBuffer[BUFMAX];
315 
316 /* Convert the memory pointed to by mem into hex, placing result in buf.
317  * Return a pointer to the last char put in buf (null), in case of mem fault,
318  * return 0.
319  */
320 
321 static unsigned char *
mem2hex(char * mem,char * buf,int count)322 mem2hex(char *mem, char *buf, int count)
323 {
324 	unsigned char ch;
325 
326 	while (count-- > 0) {
327 		/* This assembler code is basically:  ch = *mem++;
328 		 * except that we use the SPARC/Linux exception table
329 		 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
330 		 * to arrange for a "return 0" upon a memory fault
331 		 */
332 		__asm__(
333 			"\n1:\n\t"
334 			"ldub [%0], %1\n\t"
335 			"inc %0\n\t"
336 			".section .fixup,#alloc,#execinstr\n\t"
337 			".align 4\n"
338 			"2:\n\t"
339 			"retl\n\t"
340 			" mov 0, %%o0\n\t"
341 			".section __ex_table, #alloc\n\t"
342 			".align 4\n\t"
343 			".word 1b, 2b\n\t"
344 			".text\n"
345 			: "=r" (mem), "=r" (ch) : "0" (mem));
346 		*buf++ = hexchars[ch >> 4];
347 		*buf++ = hexchars[ch & 0xf];
348 	}
349 
350 	*buf = 0;
351 	return buf;
352 }
353 
354 /* convert the hex array pointed to by buf into binary to be placed in mem
355  * return a pointer to the character AFTER the last byte written.
356 */
357 static char *
hex2mem(char * buf,char * mem,int count)358 hex2mem(char *buf, char *mem, int count)
359 {
360 	int i;
361 	unsigned char ch;
362 
363 	for (i=0; i<count; i++) {
364 
365 		ch = hex(*buf++) << 4;
366 		ch |= hex(*buf++);
367 		/* Assembler code is   *mem++ = ch;   with return 0 on fault */
368 		__asm__(
369 			"\n1:\n\t"
370 			"stb %1, [%0]\n\t"
371 			"inc %0\n\t"
372 			".section .fixup,#alloc,#execinstr\n\t"
373 			".align 4\n"
374 			"2:\n\t"
375 			"retl\n\t"
376 			" mov 0, %%o0\n\t"
377 			".section __ex_table, #alloc\n\t"
378 			".align 4\n\t"
379 			".word 1b, 2b\n\t"
380 			".text\n"
381 			: "=r" (mem) : "r" (ch) , "0" (mem));
382 	}
383 	return mem;
384 }
385 
386 /* This table contains the mapping between SPARC hardware trap types, and
387    signals, which are primarily what GDB understands.  It also indicates
388    which hardware traps we need to commandeer when initializing the stub. */
389 
390 static struct hard_trap_info
391 {
392   unsigned char tt;		/* Trap type code for SPARC */
393   unsigned char signo;		/* Signal that we map this trap into */
394 } hard_trap_info[] = {
395   {SP_TRAP_SBPT, SIGTRAP},      /* ta 1 - Linux/KGDB software breakpoint */
396   {0, 0}			/* Must be last */
397 };
398 
399 /* Set up exception handlers for tracing and breakpoints */
400 
401 void
set_debug_traps(void)402 set_debug_traps(void)
403 {
404 	struct hard_trap_info *ht;
405 	unsigned long flags;
406 
407 	save_and_cli(flags);
408 #if 0
409 /* Have to sort this out. This cannot be done after initialization. */
410 	BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
411 #endif
412 
413 	/* Initialize our copy of the Linux Sparc trap table */
414 	eh_init();
415 
416 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
417 		/* Only if it doesn't destroy our fault handlers */
418 		if((ht->tt != SP_TRAP_TFLT) &&
419 		   (ht->tt != SP_TRAP_DFLT))
420 			exceptionHandler(ht->tt, trap_low);
421 	}
422 
423 	/* In case GDB is started before us, ack any packets (presumably
424 	 * "$?#xx") sitting there.
425 	 *
426 	 * I've found this code causes more problems than it solves,
427 	 * so that's why it's commented out.  GDB seems to work fine
428 	 * now starting either before or after the kernel   -bwb
429 	 */
430 #if 0
431 	while((c = getDebugChar()) != '$');
432 	while((c = getDebugChar()) != '#');
433 	c = getDebugChar(); /* eat first csum byte */
434 	c = getDebugChar(); /* eat second csum byte */
435 	putDebugChar('+'); /* ack it */
436 #endif
437 
438 	initialized = 1; /* connect! */
439 	restore_flags(flags);
440 }
441 
442 /* Convert the SPARC hardware trap type code to a unix signal number. */
443 
444 static int
computeSignal(int tt)445 computeSignal(int tt)
446 {
447 	struct hard_trap_info *ht;
448 
449 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
450 		if (ht->tt == tt)
451 			return ht->signo;
452 
453 	return SIGHUP;         /* default for things we don't know about */
454 }
455 
456 /*
457  * While we find nice hex chars, build an int.
458  * Return number of chars processed.
459  */
460 
461 static int
hexToInt(char ** ptr,int * intValue)462 hexToInt(char **ptr, int *intValue)
463 {
464 	int numChars = 0;
465 	int hexValue;
466 
467 	*intValue = 0;
468 
469 	while (**ptr) {
470 		hexValue = hex(**ptr);
471 		if (hexValue < 0)
472 			break;
473 
474 		*intValue = (*intValue << 4) | hexValue;
475 		numChars ++;
476 
477 		(*ptr)++;
478 	}
479 
480 	return (numChars);
481 }
482 
483 /*
484  * This function does all command processing for interfacing to gdb.  It
485  * returns 1 if you should skip the instruction at the trap address, 0
486  * otherwise.
487  */
488 
489 extern void breakinst(void);
490 
491 void
handle_exception(unsigned long * registers)492 handle_exception (unsigned long *registers)
493 {
494 	int tt;       /* Trap type */
495 	int sigval;
496 	int addr;
497 	int length;
498 	char *ptr;
499 	unsigned long *sp;
500 
501 	/* First, we must force all of the windows to be spilled out */
502 
503 	asm("save %sp, -64, %sp\n\t"
504 	    "save %sp, -64, %sp\n\t"
505 	    "save %sp, -64, %sp\n\t"
506 	    "save %sp, -64, %sp\n\t"
507 	    "save %sp, -64, %sp\n\t"
508 	    "save %sp, -64, %sp\n\t"
509 	    "save %sp, -64, %sp\n\t"
510 	    "save %sp, -64, %sp\n\t"
511 	    "restore\n\t"
512 	    "restore\n\t"
513 	    "restore\n\t"
514 	    "restore\n\t"
515 	    "restore\n\t"
516 	    "restore\n\t"
517 	    "restore\n\t"
518 	    "restore\n\t");
519 
520 	lock_kernel();
521 	if (registers[PC] == (unsigned long)breakinst) {
522 		/* Skip over breakpoint trap insn */
523 		registers[PC] = registers[NPC];
524 		registers[NPC] += 4;
525 	}
526 
527 	sp = (unsigned long *)registers[SP];
528 
529 	tt = (registers[TBR] >> 4) & 0xff;
530 
531 	/* reply to host that an exception has occurred */
532 	sigval = computeSignal(tt);
533 	ptr = remcomOutBuffer;
534 
535 	*ptr++ = 'T';
536 	*ptr++ = hexchars[sigval >> 4];
537 	*ptr++ = hexchars[sigval & 0xf];
538 
539 	*ptr++ = hexchars[PC >> 4];
540 	*ptr++ = hexchars[PC & 0xf];
541 	*ptr++ = ':';
542 	ptr = mem2hex((char *)&registers[PC], ptr, 4);
543 	*ptr++ = ';';
544 
545 	*ptr++ = hexchars[FP >> 4];
546 	*ptr++ = hexchars[FP & 0xf];
547 	*ptr++ = ':';
548 	ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
549 	*ptr++ = ';';
550 
551 	*ptr++ = hexchars[SP >> 4];
552 	*ptr++ = hexchars[SP & 0xf];
553 	*ptr++ = ':';
554 	ptr = mem2hex((char *)&sp, ptr, 4);
555 	*ptr++ = ';';
556 
557 	*ptr++ = hexchars[NPC >> 4];
558 	*ptr++ = hexchars[NPC & 0xf];
559 	*ptr++ = ':';
560 	ptr = mem2hex((char *)&registers[NPC], ptr, 4);
561 	*ptr++ = ';';
562 
563 	*ptr++ = hexchars[O7 >> 4];
564 	*ptr++ = hexchars[O7 & 0xf];
565 	*ptr++ = ':';
566 	ptr = mem2hex((char *)&registers[O7], ptr, 4);
567 	*ptr++ = ';';
568 
569 	*ptr++ = 0;
570 
571 	putpacket(remcomOutBuffer);
572 
573 	/* XXX We may want to add some features dealing with poking the
574 	 * XXX page tables, the real ones on the srmmu, and what is currently
575 	 * XXX loaded in the sun4/sun4c tlb at this point in time.  But this
576 	 * XXX also required hacking to the gdb sources directly...
577 	 */
578 
579 	while (1) {
580 		remcomOutBuffer[0] = 0;
581 
582 		getpacket(remcomInBuffer);
583 		switch (remcomInBuffer[0]) {
584 		case '?':
585 			remcomOutBuffer[0] = 'S';
586 			remcomOutBuffer[1] = hexchars[sigval >> 4];
587 			remcomOutBuffer[2] = hexchars[sigval & 0xf];
588 			remcomOutBuffer[3] = 0;
589 			break;
590 
591 		case 'd':
592 			/* toggle debug flag */
593 			break;
594 
595 		case 'g':		/* return the value of the CPU registers */
596 		{
597 			ptr = remcomOutBuffer;
598 			/* G & O regs */
599 			ptr = mem2hex((char *)registers, ptr, 16 * 4);
600 			/* L & I regs */
601 			ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
602 			/* Floating point */
603 			memset(ptr, '0', 32 * 8);
604 			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
605 			mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
606 		}
607 			break;
608 
609 		case 'G':	   /* set the value of the CPU registers - return OK */
610 		{
611 			unsigned long *newsp, psr;
612 
613 			psr = registers[PSR];
614 
615 			ptr = &remcomInBuffer[1];
616 			/* G & O regs */
617 			hex2mem(ptr, (char *)registers, 16 * 4);
618 			/* L & I regs */
619 			hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
620 			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
621 			hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
622 
623 			/* See if the stack pointer has moved.  If so,
624 			 * then copy the saved locals and ins to the
625 			 * new location.  This keeps the window
626 			 * overflow and underflow routines happy.
627 			 */
628 
629 			newsp = (unsigned long *)registers[SP];
630 			if (sp != newsp)
631 				sp = memcpy(newsp, sp, 16 * 4);
632 
633 			/* Don't allow CWP to be modified. */
634 
635 			if (psr != registers[PSR])
636 				registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
637 
638 			strcpy(remcomOutBuffer,"OK");
639 		}
640 			break;
641 
642 		case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
643 			/* Try to read %x,%x.  */
644 
645 			ptr = &remcomInBuffer[1];
646 
647 			if (hexToInt(&ptr, &addr)
648 			    && *ptr++ == ','
649 			    && hexToInt(&ptr, &length))	{
650 				if (mem2hex((char *)addr, remcomOutBuffer, length))
651 					break;
652 
653 				strcpy (remcomOutBuffer, "E03");
654 			} else {
655 				strcpy(remcomOutBuffer,"E01");
656 			}
657 			break;
658 
659 		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
660 			/* Try to read '%x,%x:'.  */
661 
662 			ptr = &remcomInBuffer[1];
663 
664 			if (hexToInt(&ptr, &addr)
665 			    && *ptr++ == ','
666 			    && hexToInt(&ptr, &length)
667 			    && *ptr++ == ':') {
668 				if (hex2mem(ptr, (char *)addr, length)) {
669 					strcpy(remcomOutBuffer, "OK");
670 				} else {
671 					strcpy(remcomOutBuffer, "E03");
672 				}
673 			} else {
674 				strcpy(remcomOutBuffer, "E02");
675 			}
676 			break;
677 
678 		case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
679 			/* try to read optional parameter, pc unchanged if no parm */
680 
681 			ptr = &remcomInBuffer[1];
682 			if (hexToInt(&ptr, &addr)) {
683 				registers[PC] = addr;
684 				registers[NPC] = addr + 4;
685 			}
686 
687 /* Need to flush the instruction cache here, as we may have deposited a
688  * breakpoint, and the icache probably has no way of knowing that a data ref to
689  * some location may have changed something that is in the instruction cache.
690  */
691 			flush_cache_all();
692 			unlock_kernel();
693 			return;
694 
695 			/* kill the program */
696 		case 'k' :		/* do nothing */
697 			break;
698 		case 'r':		/* Reset */
699 			asm ("call 0\n\t"
700 			     "nop\n\t");
701 			break;
702 		}			/* switch */
703 
704 		/* reply to the request */
705 		putpacket(remcomOutBuffer);
706 	} /* while(1) */
707 }
708 
709 /* This function will generate a breakpoint exception.  It is used at the
710    beginning of a program to sync up with a debugger and can be used
711    otherwise as a quick means to stop program execution and "break" into
712    the debugger. */
713 
714 void
breakpoint(void)715 breakpoint(void)
716 {
717 	if (!initialized)
718 		return;
719 
720 	/* Again, watch those c-prefixes for ELF kernels */
721 #if defined(__svr4__) || defined(__ELF__)
722 	asm(".globl breakinst\n"
723 	    "breakinst:\n\t"
724 	    "ta 1\n");
725 #else
726 	asm(".globl _breakinst\n"
727 	    "_breakinst:\n\t"
728 	    "ta 1\n");
729 #endif
730 }
731