OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ppc64/] [kernel/] [ppc-stub.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * ppc-stub.c:  KGDB support for the Linux kernel.
3
 *
4
 * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
5
 * some stuff borrowed from Paul Mackerras' xmon
6
 * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
7
 *
8
 * Modifications to run under Linux
9
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
10
 *
11
 * This file originally came from the gdb sources, and the
12
 * copyright notices have been retained below.
13
 */
14
 
15
/****************************************************************************
16
 
17
                THIS SOFTWARE IS NOT COPYRIGHTED
18
 
19
   HP offers the following for use in the public domain.  HP makes no
20
   warranty with regard to the software or its performance and the
21
   user accepts the software "AS IS" with all faults.
22
 
23
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
24
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26
 
27
****************************************************************************/
28
 
29
/****************************************************************************
30
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
31
 *
32
 *  Module name: remcom.c $
33
 *  Revision: 1.34 $
34
 *  Date: 91/03/09 12:29:49 $
35
 *  Contributor:     Lake Stevens Instrument Division$
36
 *
37
 *  Description:     low level support for gdb debugger. $
38
 *
39
 *  Considerations:  only works on target hardware $
40
 *
41
 *  Written by:      Glenn Engel $
42
 *  ModuleState:     Experimental $
43
 *
44
 *  NOTES:           See Below $
45
 *
46
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
47
 *
48
 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
49
 *
50
 *  To enable debugger support, two things need to happen.  One, a
51
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
52
 *  or error conditions to be properly intercepted and reported to gdb.
53
 *  Two, a breakpoint needs to be generated to begin communication.  This
54
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
55
 *  simulates a breakpoint by executing a trap #1.
56
 *
57
 *************
58
 *
59
 *    The following gdb commands are supported:
60
 *
61
 * command          function                               Return value
62
 *
63
 *    g             return the value of the CPU registers  hex data or ENN
64
 *    G             set the value of the CPU registers     OK or ENN
65
 *    qOffsets      Get section offsets.  Reply is Text=xxx;Data=yyy;Bss=zzz
66
 *
67
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
68
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
69
 *
70
 *    c             Resume at current address              SNN   ( signal NN)
71
 *    cAA..AA       Continue at address AA..AA             SNN
72
 *
73
 *    s             Step one instruction                   SNN
74
 *    sAA..AA       Step one instruction from AA..AA       SNN
75
 *
76
 *    k             kill
77
 *
78
 *    ?             What was the last sigval ?             SNN   (signal NN)
79
 *
80
 *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
81
 *                                                         baud rate
82
 *
83
 * All commands and responses are sent with a packet which includes a
84
 * checksum.  A packet consists of
85
 *
86
 * $<packet info>#<checksum>.
87
 *
88
 * where
89
 * <packet info> :: <characters representing the command or response>
90
 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
91
 *
92
 * When a packet is received, it is first acknowledged with either '+' or '-'.
93
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
94
 *
95
 * Example:
96
 *
97
 * Host:                  Reply:
98
 * $m0,10#2a               +$00010203040506070809101112131415#42
99
 *
100
 ****************************************************************************/
101
 
102
#include <linux/config.h>
103
#include <linux/kernel.h>
104
#include <linux/string.h>
105
#include <linux/mm.h>
106
#include <linux/smp.h>
107
#include <linux/smp_lock.h>
108
 
109
#include <asm/system.h>
110
#include <asm/signal.h>
111
#include <asm/kgdb.h>
112
#include <asm/pgtable.h>
113
#include <asm/ptrace.h>
114
 
115
void breakinst(void);
116
 
117
/*
118
 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
119
 * at least NUMREGBYTES*2 are needed for register packets
120
 */
121
#define BUFMAX 2048
122
static char remcomInBuffer[BUFMAX];
123
static char remcomOutBuffer[BUFMAX];
124
 
125
static int initialized = 0;
126
static int kgdb_active = 0;
127
static int kgdb_started = 0;
128
static u_int fault_jmp_buf[100];
129
static int kdebug;
130
 
131
static const char hexchars[]="0123456789abcdef";
132
 
133
/* Place where we save old trap entries for restoration - sparc*/
134
/* struct tt_entry kgdb_savettable[256]; */
135
/* typedef void (*trapfunc_t)(void); */
136
 
137
#if 0
138
/* Install an exception handler for kgdb */
139
static void exceptionHandler(int tnum, unsigned int *tfunc)
140
{
141
        /* We are dorking with a live trap table, all irqs off */
142
}
143
#endif
144
 
145
int
146
kgdb_setjmp(long *buf)
147
{
148
        asm ("mflr 0; stw 0,0(%0);"
149
             "stw 1,4(%0); stw 2,8(%0);"
150
             "mfcr 0; stw 0,12(%0);"
151
             "stmw 13,16(%0)"
152
             : : "r" (buf));
153
        /* XXX should save fp regs as well */
154
        return 0;
155
}
156
void
157
kgdb_longjmp(long *buf, int val)
158
{
159
        if (val == 0)
160
                val = 1;
161
        asm ("lmw 13,16(%0);"
162
             "lwz 0,12(%0); mtcrf 0x38,0;"
163
             "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
164
             "mtlr 0; mr 3,%1"
165
             : : "r" (buf), "r" (val));
166
}
167
/* Convert ch from a hex digit to an int */
168
static int
169
hex(unsigned char ch)
170
{
171
        if (ch >= 'a' && ch <= 'f')
172
                return ch-'a'+10;
173
        if (ch >= '0' && ch <= '9')
174
                return ch-'0';
175
        if (ch >= 'A' && ch <= 'F')
176
                return ch-'A'+10;
177
        return -1;
178
}
179
 
180
/* Convert the memory pointed to by mem into hex, placing result in buf.
181
 * Return a pointer to the last char put in buf (null), in case of mem fault,
182
 * return 0.
183
 */
184
static unsigned char *
185
mem2hex(char *mem, char *buf, int count)
186
{
187
        unsigned char ch;
188
 
189
        if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
190
                debugger_fault_handler = kgdb_fault_handler;
191
                while (count-- > 0) {
192
                        ch = *mem++;
193
                        *buf++ = hexchars[ch >> 4];
194
                        *buf++ = hexchars[ch & 0xf];
195
                }
196
        } else {
197
                /* error condition */
198
        }
199
        debugger_fault_handler = 0;
200
        *buf = 0;
201
        return buf;
202
}
203
 
204
/* convert the hex array pointed to by buf into binary to be placed in mem
205
 * return a pointer to the character AFTER the last byte written.
206
*/
207
static char *
208
hex2mem(char *buf, char *mem, int count)
209
{
210
        int i;
211
        unsigned char ch;
212
 
213
        if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
214
                debugger_fault_handler = kgdb_fault_handler;
215
                for (i=0; i<count; i++) {
216
                        ch = hex(*buf++) << 4;
217
                        ch |= hex(*buf++);
218
                        *mem++ = ch;
219
                }
220
                flush_icache_range((int)mem, (int)mem+count);
221
        } else {
222
                /* error condition */
223
        }
224
        debugger_fault_handler = 0;
225
        return mem;
226
}
227
 
228
/*
229
 * While we find nice hex chars, build an int.
230
 * Return number of chars processed.
231
 */
232
static int
233
hexToInt(char **ptr, int *intValue)
234
{
235
        int numChars = 0;
236
        int hexValue;
237
 
238
        *intValue = 0;
239
 
240
        if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
241
                debugger_fault_handler = kgdb_fault_handler;
242
                while (**ptr) {
243
                        hexValue = hex(**ptr);
244
                        if (hexValue < 0)
245
                                break;
246
 
247
                        *intValue = (*intValue << 4) | hexValue;
248
                        numChars ++;
249
 
250
                        (*ptr)++;
251
                }
252
        } else {
253
             /* error condition */
254
        }
255
        debugger_fault_handler = 0;
256
 
257
        return (numChars);
258
}
259
 
260
/* scan for the sequence $<data>#<checksum>     */
261
static void
262
getpacket(char *buffer)
263
{
264
        unsigned char checksum;
265
        unsigned char xmitcsum;
266
        int i;
267
        int count;
268
        unsigned char ch;
269
 
270
        do {
271
                /* wait around for the start character, ignore all other
272
                 * characters */
273
                while ((ch = (getDebugChar() & 0x7f)) != '$') ;
274
 
275
                checksum = 0;
276
                xmitcsum = -1;
277
 
278
                count = 0;
279
 
280
                /* now, read until a # or end of buffer is found */
281
                while (count < BUFMAX) {
282
                        ch = getDebugChar() & 0x7f;
283
                        if (ch == '#')
284
                                break;
285
                        checksum = checksum + ch;
286
                        buffer[count] = ch;
287
                        count = count + 1;
288
                }
289
 
290
                if (count >= BUFMAX)
291
                        continue;
292
 
293
                buffer[count] = 0;
294
 
295
                if (ch == '#') {
296
                        xmitcsum = hex(getDebugChar() & 0x7f) << 4;
297
                        xmitcsum |= hex(getDebugChar() & 0x7f);
298
                        if (checksum != xmitcsum)
299
                                putDebugChar('-');      /* failed checksum */
300
                        else {
301
                                putDebugChar('+'); /* successful transfer */
302
                                /* if a sequence char is present, reply the ID */
303
                                if (buffer[2] == ':') {
304
                                        putDebugChar(buffer[0]);
305
                                        putDebugChar(buffer[1]);
306
                                        /* remove sequence chars from buffer */
307
                                        count = strlen(buffer);
308
                                        for (i=3; i <= count; i++)
309
                                                buffer[i-3] = buffer[i];
310
                                }
311
                        }
312
                }
313
        } while (checksum != xmitcsum);
314
}
315
 
316
/* send the packet in buffer.  */
317
static void putpacket(unsigned char *buffer)
318
{
319
        unsigned char checksum;
320
        int count;
321
        unsigned char ch, recv;
322
 
323
        /*  $<packet info>#<checksum>. */
324
        do {
325
                putDebugChar('$');
326
                checksum = 0;
327
                count = 0;
328
 
329
                while ((ch = buffer[count])) {
330
                        putDebugChar(ch);
331
                        checksum += ch;
332
                        count += 1;
333
                }
334
 
335
                putDebugChar('#');
336
                putDebugChar(hexchars[checksum >> 4]);
337
                putDebugChar(hexchars[checksum & 0xf]);
338
                recv = getDebugChar();
339
        } while ((recv & 0x7f) != '+');
340
}
341
 
342
static void kgdb_flush_cache_all(void)
343
{
344
        flush_instruction_cache();
345
}
346
 
347
 
348
/* Set up exception handlers for tracing and breakpoints
349
 * [could be called kgdb_init()]
350
 */
351
void set_debug_traps(void)
352
{
353
#if 0
354
        unsigned char c;
355
 
356
        save_and_cli(flags);
357
 
358
        /* In case GDB is started before us, ack any packets (presumably
359
         * "$?#xx") sitting there.
360
         *
361
         * I've found this code causes more problems than it solves,
362
         * so that's why it's commented out.  GDB seems to work fine
363
         * now starting either before or after the kernel   -bwb
364
         */
365
 
366
        while((c = getDebugChar()) != '$');
367
        while((c = getDebugChar()) != '#');
368
        c = getDebugChar(); /* eat first csum byte */
369
        c = getDebugChar(); /* eat second csum byte */
370
        putDebugChar('+'); /* ack it */
371
#endif
372
        debugger = kgdb;
373
        debugger_bpt = kgdb_bpt;
374
        debugger_sstep = kgdb_sstep;
375
        debugger_iabr_match = kgdb_iabr_match;
376
        debugger_dabr_match = kgdb_dabr_match;
377
 
378
        initialized = 1;
379
}
380
 
381
static void kgdb_fault_handler(struct pt_regs *regs)
382
{
383
        kgdb_longjmp((long*)fault_jmp_buf, 1);
384
}
385
 
386
int kgdb_bpt(struct pt_regs *regs)
387
{
388
        handle_exception(regs);
389
        return 1;
390
}
391
 
392
int kgdb_sstep(struct pt_regs *regs)
393
{
394
        handle_exception(regs);
395
        return 1;
396
}
397
 
398
void kgdb(struct pt_regs *regs)
399
{
400
        handle_exception(regs);
401
}
402
 
403
int kgdb_iabr_match(struct pt_regs *regs)
404
{
405
        printk("kgdb doesn't support iabr, what?!?\n");
406
        handle_exception(regs);
407
        return 1;
408
}
409
 
410
int kgdb_dabr_match(struct pt_regs *regs)
411
{
412
        printk("kgdb doesn't support dabr, what?!?\n");
413
        handle_exception(regs);
414
        return 1;
415
}
416
 
417
/* Convert the SPARC hardware trap type code to a unix signal number. */
418
/*
419
 * This table contains the mapping between PowerPC hardware trap types, and
420
 * signals, which are primarily what GDB understands.
421
 */
422
static struct hard_trap_info
423
{
424
        unsigned int tt;                /* Trap type code for powerpc */
425
        unsigned char signo;            /* Signal that we map this trap into */
426
} hard_trap_info[] = {
427
        { 0x200, SIGSEGV },                     /* machine check */
428
        { 0x300, SIGSEGV },                     /* address error (store) */
429
        { 0x400, SIGBUS },                      /* instruction bus error */
430
        { 0x500, SIGINT },                      /* interrupt */
431
        { 0x600, SIGBUS },                      /* alingment */
432
        { 0x700, SIGTRAP },                     /* breakpoint trap */
433
        { 0x800, SIGFPE },                      /* fpu unavail */
434
        { 0x900, SIGALRM },                     /* decrementer */
435
        { 0xa00, SIGILL },                      /* reserved */
436
        { 0xb00, SIGILL },                      /* reserved */
437
        { 0xc00, SIGCHLD },                     /* syscall */
438
        { 0xd00, SIGTRAP },                     /* single-step/watch */
439
        { 0xe00, SIGFPE },                      /* fp assist */
440
        { 0, 0}                           /* Must be last */
441
};
442
 
443
static int computeSignal(unsigned int tt)
444
{
445
        struct hard_trap_info *ht;
446
 
447
        for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
448
                if (ht->tt == tt)
449
                        return ht->signo;
450
 
451
        return SIGHUP;         /* default for things we don't know about */
452
}
453
 
454
#define PC_REGNUM 64
455
#define SP_REGNUM 1
456
 
457
/*
458
 * This function does all command processing for interfacing to gdb.
459
 */
460
static void
461
handle_exception (struct pt_regs *regs)
462
{
463
        int sigval;
464
        int addr;
465
        int length;
466
        char *ptr;
467
        unsigned long msr;
468
 
469
        if (debugger_fault_handler) {
470
                debugger_fault_handler(regs);
471
                panic("kgdb longjump failed!\n");
472
        }
473
        if (kgdb_active) {
474
                printk("interrupt while in kgdb, returning\n");
475
                return;
476
        }
477
        kgdb_active = 1;
478
        kgdb_started = 1;
479
 
480
#ifdef KGDB_DEBUG
481
        printk("kgdb: entering handle_exception; trap [0x%x]\n",
482
               (unsigned int)regs->trap);
483
#endif
484
 
485
        kgdb_interruptible(0);
486
        lock_kernel();
487
        msr = get_msr();
488
        set_msr(msr & ~MSR_EE); /* disable interrupts */
489
 
490
        if (regs->nip == (unsigned long)breakinst) {
491
                /* Skip over breakpoint trap insn */
492
                regs->nip += 4;
493
        }
494
 
495
        /* reply to host that an exception has occurred */
496
        sigval = computeSignal(regs->trap);
497
        ptr = remcomOutBuffer;
498
 
499
#if 0
500
        *ptr++ = 'S';
501
        *ptr++ = hexchars[sigval >> 4];
502
        *ptr++ = hexchars[sigval & 0xf];
503
#else
504
        *ptr++ = 'T';
505
        *ptr++ = hexchars[sigval >> 4];
506
        *ptr++ = hexchars[sigval & 0xf];
507
        *ptr++ = hexchars[PC_REGNUM >> 4];
508
        *ptr++ = hexchars[PC_REGNUM & 0xf];
509
        *ptr++ = ':';
510
        ptr = mem2hex((char *)&regs->nip, ptr, 4);
511
        *ptr++ = ';';
512
        *ptr++ = hexchars[SP_REGNUM >> 4];
513
        *ptr++ = hexchars[SP_REGNUM & 0xf];
514
        *ptr++ = ':';
515
        ptr = mem2hex(((char *)&regs) + SP_REGNUM*4, ptr, 4);
516
        *ptr++ = ';';
517
#endif
518
 
519
        *ptr++ = 0;
520
 
521
        putpacket(remcomOutBuffer);
522
 
523
        /* XXX We may want to add some features dealing with poking the
524
         * XXX page tables, ... (look at sparc-stub.c for more info)
525
         * XXX also required hacking to the gdb sources directly...
526
         */
527
 
528
        while (1) {
529
                remcomOutBuffer[0] = 0;
530
 
531
                getpacket(remcomInBuffer);
532
                switch (remcomInBuffer[0]) {
533
                case '?':               /* report most recent signal */
534
                        remcomOutBuffer[0] = 'S';
535
                        remcomOutBuffer[1] = hexchars[sigval >> 4];
536
                        remcomOutBuffer[2] = hexchars[sigval & 0xf];
537
                        remcomOutBuffer[3] = 0;
538
                        break;
539
#if 0
540
                case 'q': /* this screws up gdb for some reason...*/
541
                {
542
                        extern long _start, sdata, __bss_start;
543
 
544
                        ptr = &remcomInBuffer[1];
545
                        if (strncmp(ptr, "Offsets", 7) != 0)
546
                                break;
547
 
548
                        ptr = remcomOutBuffer;
549
                        sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
550
                                &_start, &sdata, &__bss_start);
551
                        break;
552
                }
553
#endif
554
                case 'd':
555
                        /* toggle debug flag */
556
                        kdebug ^= 1;
557
                        break;
558
 
559
                case 'g':       /* return the value of the CPU registers.
560
                                 * some of them are non-PowerPC names :(
561
                                 * they are stored in gdb like:
562
                                 * struct {
563
                                 *     u32 gpr[32];
564
                                 *     f64 fpr[32];
565
                                 *     u32 pc, ps, cnd, lr; (ps=msr)
566
                                 *     u32 cnt, xer, mq;
567
                                 * }
568
                                 */
569
                {
570
                        int i;
571
                        ptr = remcomOutBuffer;
572
                        /* General Purpose Regs */
573
                        ptr = mem2hex((char *)regs, ptr, 32 * 4);
574
                        /* Floating Point Regs - FIXME */
575
                        /*ptr = mem2hex((char *), ptr, 32 * 8);*/
576
                        for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
577
                                ptr[i] = '0';
578
                        }
579
                        ptr += 32*8*2;
580
                        /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
581
                        ptr = mem2hex((char *)&regs->nip, ptr, 4);
582
                        ptr = mem2hex((char *)&regs->msr, ptr, 4);
583
                        ptr = mem2hex((char *)&regs->ccr, ptr, 4);
584
                        ptr = mem2hex((char *)&regs->link, ptr, 4);
585
                        ptr = mem2hex((char *)&regs->ctr, ptr, 4);
586
                        ptr = mem2hex((char *)&regs->xer, ptr, 4);
587
                }
588
                        break;
589
 
590
                case 'G':   /* set the value of the CPU registers */
591
                {
592
                        ptr = &remcomInBuffer[1];
593
 
594
                        /*
595
                         * If the stack pointer has moved, you should pray.
596
                         * (cause only god can help you).
597
                         */
598
 
599
                        /* General Purpose Regs */
600
                        hex2mem(ptr, (char *)regs, 32 * 4);
601
 
602
                        /* Floating Point Regs - FIXME?? */
603
                        /*ptr = hex2mem(ptr, ??, 32 * 8);*/
604
                        ptr += 32*8*2;
605
 
606
                        /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
607
                        ptr = hex2mem(ptr, (char *)&regs->nip, 4);
608
                        ptr = hex2mem(ptr, (char *)&regs->msr, 4);
609
                        ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
610
                        ptr = hex2mem(ptr, (char *)&regs->link, 4);
611
                        ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
612
                        ptr = hex2mem(ptr, (char *)&regs->xer, 4);
613
 
614
                        strcpy(remcomOutBuffer,"OK");
615
                }
616
                        break;
617
                case 'H':
618
                        /* don't do anything, yet, just acknowledge */
619
                        hexToInt(&ptr, &addr);
620
                        strcpy(remcomOutBuffer,"OK");
621
                        break;
622
 
623
                case 'm':       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
624
                                /* Try to read %x,%x.  */
625
 
626
                        ptr = &remcomInBuffer[1];
627
 
628
                        if (hexToInt(&ptr, &addr)
629
                            && *ptr++ == ','
630
                            && hexToInt(&ptr, &length)) {
631
                                if (mem2hex((char *)addr, remcomOutBuffer,length))
632
                                        break;
633
                                strcpy (remcomOutBuffer, "E03");
634
                        } else {
635
                                strcpy(remcomOutBuffer,"E01");
636
                        }
637
                        break;
638
 
639
                case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
640
                        /* Try to read '%x,%x:'.  */
641
 
642
                        ptr = &remcomInBuffer[1];
643
 
644
                        if (hexToInt(&ptr, &addr)
645
                            && *ptr++ == ','
646
                            && hexToInt(&ptr, &length)
647
                            && *ptr++ == ':') {
648
                                if (hex2mem(ptr, (char *)addr, length)) {
649
                                        strcpy(remcomOutBuffer, "OK");
650
                                } else {
651
                                        strcpy(remcomOutBuffer, "E03");
652
                                }
653
                                flush_icache_range(addr, addr+length);
654
                        } else {
655
                                strcpy(remcomOutBuffer, "E02");
656
                        }
657
                        break;
658
 
659
 
660
                case 'k':    /* kill the program, actually just continue */
661
                case 'c':    /* cAA..AA  Continue; address AA..AA optional */
662
                        /* try to read optional parameter, pc unchanged if no parm */
663
 
664
                        ptr = &remcomInBuffer[1];
665
                        if (hexToInt(&ptr, &addr)) {
666
                                regs->nip = addr;
667
                        }
668
 
669
/* Need to flush the instruction cache here, as we may have deposited a
670
 * breakpoint, and the icache probably has no way of knowing that a data ref to
671
 * some location may have changed something that is in the instruction cache.
672
 */
673
                        kgdb_flush_cache_all();
674
                        set_msr(msr);
675
                        kgdb_interruptible(1);
676
                        unlock_kernel();
677
                        kgdb_active = 0;
678
                        return;
679
 
680
                case 's':
681
                        kgdb_flush_cache_all();
682
                        regs->msr |= MSR_SE;
683
#if 0
684
                        set_msr(msr | MSR_SE);
685
#endif
686
                        unlock_kernel();
687
                        kgdb_active = 0;
688
                        return;
689
 
690
                case 'r':               /* Reset (if user process..exit ???)*/
691
                        panic("kgdb reset.");
692
                        break;
693
                }                       /* switch */
694
                if (remcomOutBuffer[0] && kdebug) {
695
                        printk("remcomInBuffer: %s\n", remcomInBuffer);
696
                        printk("remcomOutBuffer: %s\n", remcomOutBuffer);
697
                }
698
                /* reply to the request */
699
                putpacket(remcomOutBuffer);
700
        } /* while(1) */
701
}
702
 
703
/* This function will generate a breakpoint exception.  It is used at the
704
   beginning of a program to sync up with a debugger and can be used
705
   otherwise as a quick means to stop program execution and "break" into
706
   the debugger. */
707
 
708
void
709
breakpoint(void)
710
{
711
        if (!initialized) {
712
                printk("breakpoint() called b4 kgdb init\n");
713
                return;
714
        }
715
 
716
        asm("   .globl breakinst
717
             breakinst: .long 0x7d821008
718
            ");
719
}
720
 
721
/* Output string in GDB O-packet format if GDB has connected. If nothing
722
   output, returns 0 (caller must then handle output). */
723
int
724
kgdb_output_string (const char* s, unsigned int count)
725
{
726
        char buffer[512];
727
 
728
        if (!kgdb_started)
729
            return 0;
730
 
731
        count = (count <= (sizeof(buffer) / 2 - 2))
732
                ? count : (sizeof(buffer) / 2 - 2);
733
 
734
        buffer[0] = 'O';
735
        mem2hex (s, &buffer[1], count);
736
        putpacket(buffer);
737
 
738
        return 1;
739
 }

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.