root/arch/sparc/kernel/sparc-stub.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_sun4cpte
  2. get_sun4csegmap
  3. copy_ttentry
  4. eh_init
  5. exceptionHandler
  6. hex
  7. getpacket
  8. putpacket
  9. mem2hex
  10. hex2mem
  11. set_debug_traps
  12. computeSignal
  13. hexToInt
  14. handle_exception
  15. breakpoint

   1 /* $Id: sparc-stub.c,v 1.10 1996/02/15 09:12:09 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 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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 processing 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][next][first][last][top][bottom][index][help] */
 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 *)&registers[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 *)&registers[NPC], ptr, 4);
 509         *ptr++ = ';';
 510 
 511         *ptr++ = hexchars[O7 >> 4];
 512         *ptr++ = hexchars[O7 & 0xf];
 513         *ptr++ = ':';
 514         ptr = mem2hex((char *)&registers[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 *)&registers[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 *)&registers[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                         /* Only instruction cache flushing on the sun4c/sun4
 640                          * for now.  We assume control flow during the kgdb
 641                          * transaction has not left the context in which it
 642                          * was entered.
 643                          */
 644                         if((sparc_cpu_model==sun4 || sparc_cpu_model==sun4c) &&
 645                            (sun4c_vacinfo.num_bytes && sun4c_vacinfo.on))
 646                                 sun4c_flush_context();
 647                         /* XXX SRMMU and on-chip v8 instruction cache
 648                          * XXX flushing goes here!
 649                          */
 650 
 651                         return;
 652 
 653                         /* kill the program */
 654                 case 'k' :              /* do nothing */
 655                         break;
 656                 case 'r':               /* Reset */
 657                         asm ("call 0\n\t"
 658                              "nop\n\t");
 659                         break;
 660                 }                       /* switch */
 661 
 662                 /* reply to the request */
 663                 putpacket(remcomOutBuffer);
 664         } /* while(1) */
 665 }
 666 
 667 /* This function will generate a breakpoint exception.  It is used at the
 668    beginning of a program to sync up with a debugger and can be used
 669    otherwise as a quick means to stop program execution and "break" into
 670    the debugger. */
 671 
 672 void
 673 breakpoint(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 674 {
 675         if (!initialized)
 676                 return;
 677 
 678         /* Again, watch those c-prefixes for solaris/elf kernels */
 679 #ifndef __svr4__
 680         asm("   .globl _breakinst
 681 
 682              _breakinst: ta 1
 683             ");
 684 #else
 685         asm("   .globl breakinst
 686 
 687              breakinst: ta 1
 688             ");
 689 #endif
 690 }

/* [previous][next][first][last][top][bottom][index][help] */