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