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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  arch/s390/kernel/gdb-stub.c
3
 *
4
 *  S390 version
5
 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6
 *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
7
 *
8
 *  Originally written by Glenn Engel, Lake Stevens Instrument Division
9
 *
10
 *  Contributed by HP Systems
11
 *
12
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
13
 *
14
 *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
15
 *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
16
 *
17
 *  Copyright (C) 1995 Andreas Busse
18
 */
19
 
20
/*
21
 *  To enable debugger support, two things need to happen.  One, a
22
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
23
 *  or error conditions to be properly intercepted and reported to gdb.
24
 *  Two, a breakpoint needs to be generated to begin communication.  This
25
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
26
 *  simulates a breakpoint by executing a BREAK instruction.
27
 *
28
 *
29
 *    The following gdb commands are supported:
30
 *
31
 * command          function                               Return value
32
 *
33
 *    g             return the value of the CPU registers  hex data or ENN
34
 *    G             set the value of the CPU registers     OK or ENN
35
 *
36
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
37
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
38
 *
39
 *    c             Resume at current address              SNN   ( signal NN)
40
 *    cAA..AA       Continue at address AA..AA             SNN
41
 *
42
 *    s             Step one instruction                   SNN
43
 *    sAA..AA       Step one instruction from AA..AA       SNN
44
 *
45
 *    k             kill
46
 *
47
 *    ?             What was the last sigval ?             SNN   (signal NN)
48
 *
49
 *
50
 * All commands and responses are sent with a packet which includes a
51
 * checksum.  A packet consists of
52
 *
53
 * $<packet info>#<checksum>.
54
 *
55
 * where
56
 * <packet info> :: <characters representing the command or response>
57
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
58
 *
59
 * When a packet is received, it is first acknowledged with either '+' or '-'.
60
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
61
 *
62
 * Example:
63
 *
64
 * Host:                  Reply:
65
 * $m0,10#2a               +$00010203040506070809101112131415#42
66
 *
67
 */
68
 
69
#include <asm/gdb-stub.h>
70
#include <linux/string.h>
71
#include <linux/kernel.h>
72
#include <linux/signal.h>
73
#include <linux/sched.h>
74
#include <linux/mm.h>
75
#include <asm/pgtable.h>
76
#include <asm/system.h>
77
 
78
 
79
/*
80
 * external low-level support routines
81
 */
82
 
83
extern int putDebugChar(char c);    /* write a single character      */
84
extern char getDebugChar(void);     /* read and return a single char */
85
extern void fltr_set_mem_err(void);
86
extern void trap_low(void);
87
 
88
/*
89
 * breakpoint and test functions
90
 */
91
extern void breakpoint(void);
92
extern void breakinst(void);
93
 
94
/*
95
 * local prototypes
96
 */
97
 
98
static void getpacket(char *buffer);
99
static void putpacket(char *buffer);
100
static int hex(unsigned char ch);
101
static int hexToInt(char **ptr, int *intValue);
102
static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
103
 
104
 
105
/*
106
 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
107
 * at least NUMREGBYTES*2 are needed for register packets
108
 */
109
#define BUFMAX 2048
110
 
111
static char input_buffer[BUFMAX];
112
static char output_buffer[BUFMAX];
113
int gdb_stub_initialised = FALSE;
114
static const char hexchars[]="0123456789abcdef";
115
 
116
 
117
/*
118
 * Convert ch from a hex digit to an int
119
 */
120
static int hex(unsigned char ch)
121
{
122
        if (ch >= 'a' && ch <= 'f')
123
                return ch-'a'+10;
124
        if (ch >= '0' && ch <= '9')
125
                return ch-'0';
126
        if (ch >= 'A' && ch <= 'F')
127
                return ch-'A'+10;
128
        return -1;
129
}
130
 
131
/*
132
 * scan for the sequence $<data>#<checksum>
133
 */
134
static void getpacket(char *buffer)
135
{
136
        unsigned char checksum;
137
        unsigned char xmitcsum;
138
        int i;
139
        int count;
140
        unsigned char ch;
141
 
142
        do {
143
                /*
144
                 * wait around for the start character,
145
                 * ignore all other characters
146
                 */
147
                while ((ch = (getDebugChar() & 0x7f)) != '$') ;
148
 
149
                checksum = 0;
150
                xmitcsum = -1;
151
                count = 0;
152
 
153
                /*
154
                 * now, read until a # or end of buffer is found
155
                 */
156
                while (count < BUFMAX) {
157
                        ch = getDebugChar() & 0x7f;
158
                        if (ch == '#')
159
                                break;
160
                        checksum = checksum + ch;
161
                        buffer[count] = ch;
162
                        count = count + 1;
163
                }
164
 
165
                if (count >= BUFMAX)
166
                        continue;
167
 
168
                buffer[count] = 0;
169
 
170
                if (ch == '#') {
171
                        xmitcsum = hex(getDebugChar() & 0x7f) << 4;
172
                        xmitcsum |= hex(getDebugChar() & 0x7f);
173
 
174
                        if (checksum != xmitcsum)
175
                                putDebugChar('-');      /* failed checksum */
176
                        else {
177
                                putDebugChar('+'); /* successful transfer */
178
 
179
                                /*
180
                                 * if a sequence char is present,
181
                                 * reply the sequence ID
182
                                 */
183
                                if (buffer[2] == ':') {
184
                                        putDebugChar(buffer[0]);
185
                                        putDebugChar(buffer[1]);
186
 
187
                                        /*
188
                                         * remove sequence chars from buffer
189
                                         */
190
                                        count = strlen(buffer);
191
                                        for (i=3; i <= count; i++)
192
                                                buffer[i-3] = buffer[i];
193
                                }
194
                        }
195
                }
196
        }
197
        while (checksum != xmitcsum);
198
}
199
 
200
/*
201
 * send the packet in buffer.
202
 */
203
static void putpacket(char *buffer)
204
{
205
        unsigned char checksum;
206
        int count;
207
        unsigned char ch;
208
 
209
        /*
210
         * $<packet info>#<checksum>.
211
         */
212
 
213
        do {
214
                putDebugChar('$');
215
                checksum = 0;
216
                count = 0;
217
 
218
                while ((ch = buffer[count]) != 0) {
219
                        if (!(putDebugChar(ch)))
220
                                return;
221
                        checksum += ch;
222
                        count += 1;
223
                }
224
 
225
                putDebugChar('#');
226
                putDebugChar(hexchars[checksum >> 4]);
227
                putDebugChar(hexchars[checksum & 0xf]);
228
 
229
        }
230
        while ((getDebugChar() & 0x7f) != '+');
231
}
232
 
233
 
234
 
235
/*
236
 * Convert the memory pointed to by mem into hex, placing result in buf.
237
 * Return a pointer to the last char put in buf (null), in case of mem fault,
238
 * return 0.
239
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
240
 * a 0, else treat a fault like any other fault in the stub.
241
 */
242
static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
243
{
244
        unsigned char ch;
245
 
246
/*      set_mem_fault_trap(may_fault); */
247
 
248
        while (count-- > 0) {
249
                ch = *(mem++);
250
                if (mem_err)
251
                        return 0;
252
                *buf++ = hexchars[ch >> 4];
253
                *buf++ = hexchars[ch & 0xf];
254
        }
255
 
256
        *buf = 0;
257
 
258
/*      set_mem_fault_trap(0); */
259
 
260
        return buf;
261
}
262
 
263
/*
264
 * convert the hex array pointed to by buf into binary to be placed in mem
265
 * return a pointer to the character AFTER the last byte written
266
 */
267
static char *hex2mem(char *buf, char *mem, int count, int may_fault)
268
{
269
        int i;
270
        unsigned char ch;
271
 
272
/*      set_mem_fault_trap(may_fault); */
273
 
274
        for (i=0; i<count; i++)
275
        {
276
                ch = hex(*buf++) << 4;
277
                ch |= hex(*buf++);
278
                *(mem++) = ch;
279
                if (mem_err)
280
                        return 0;
281
        }
282
 
283
/*      set_mem_fault_trap(0); */
284
 
285
        return mem;
286
}
287
 
288
 
289
 
290
/*
291
 * Set up exception handlers for tracing and breakpoints
292
 */
293
void set_debug_traps(void)
294
{
295
//      unsigned long flags;
296
        unsigned char c;
297
 
298
//      save_and_cli(flags);
299
        /*
300
         * In case GDB is started before us, ack any packets
301
         * (presumably "$?#xx") sitting there.
302
         */
303
        while((c = getDebugChar()) != '$');
304
        while((c = getDebugChar()) != '#');
305
        c = getDebugChar(); /* eat first csum byte */
306
        c = getDebugChar(); /* eat second csum byte */
307
        putDebugChar('+'); /* ack it */
308
 
309
        gdb_stub_initialised = TRUE;
310
//      restore_flags(flags);
311
}
312
 
313
 
314
/*
315
 * Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
316
 * assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
317
 * 0 would ever contain code that could mem fault.  This routine will skip
318
 * past the faulting instruction after setting mem_err.
319
 */
320
extern void fltr_set_mem_err(void)
321
{
322
  /* FIXME: Needs to be written... */
323
}
324
 
325
 
326
/*
327
 * While we find nice hex chars, build an int.
328
 * Return number of chars processed.
329
 */
330
static int hexToInt(char **ptr, int *intValue)
331
{
332
        int numChars = 0;
333
        int hexValue;
334
 
335
        *intValue = 0;
336
 
337
        while (**ptr)
338
        {
339
                hexValue = hex(**ptr);
340
                if (hexValue < 0)
341
                        break;
342
 
343
                *intValue = (*intValue << 4) | hexValue;
344
                numChars ++;
345
 
346
                (*ptr)++;
347
        }
348
 
349
        return (numChars);
350
}
351
 
352
void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs)
353
{
354
        s390_fp_regs *fpregs=&regs->fp_regs;
355
        int has_ieee=save_fp_regs1(fpregs);
356
 
357
        if(!has_ieee)
358
        {
359
                fpregs->fpc=0;
360
                fpregs->fprs[1].d=
361
                fpregs->fprs[3].d=
362
                fpregs->fprs[5].d=
363
                fpregs->fprs[7].d=0;
364
                memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
365
        }
366
}
367
 
368
void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
369
{
370
        restore_fp_regs1(&regs->fp_regs);
371
}
372
 
373
void gdb_stub_send_signal(int sigval)
374
{
375
        char *ptr;
376
        ptr = output_buffer;
377
 
378
        /*
379
         * Send trap type (converted to signal)
380
         */
381
        *ptr++ = 'S';
382
        *ptr++ = hexchars[sigval >> 4];
383
        *ptr++ = hexchars[sigval & 0xf];
384
        *ptr++ = 0;
385
        putpacket(output_buffer);       /* send it off... */
386
}
387
 
388
/*
389
 * This function does all command processing for interfacing to gdb.  It
390
 * returns 1 if you should skip the instruction at the trap address, 0
391
 * otherwise.
392
 */
393
void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
394
{
395
        int trap;                       /* Trap type */
396
        int addr;
397
        int length;
398
        char *ptr;
399
        unsigned long *stack;
400
 
401
 
402
        /*
403
         * reply to host that an exception has occurred
404
         */
405
        send_signal(sigval);
406
 
407
        /*
408
         * Wait for input from remote GDB
409
         */
410
        while (1) {
411
                output_buffer[0] = 0;
412
                getpacket(input_buffer);
413
 
414
                switch (input_buffer[0])
415
                {
416
                case '?':
417
                        send_signal(sigval);
418
                        continue;
419
 
420
                case 'd':
421
                        /* toggle debug flag */
422
                        break;
423
 
424
                /*
425
                 * Return the value of the CPU registers
426
                 */
427
                case 'g':
428
                        gdb_stub_get_non_pt_regs(regs);
429
                        ptr = output_buffer;
430
                        ptr=  mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE);
431
                        ptr=  mem2hex((char *)&regs->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
432
                        ptr = mem2hex((char *)&regs->fp_regs, ptr,sizeof(s390_fp_regs));
433
                        break;
434
 
435
                /*
436
                 * set the value of the CPU registers - return OK
437
                 * FIXME: Needs to be written
438
                 */
439
                case 'G':
440
                        ptr=input_buffer;
441
                        hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE);
442
                        ptr+=sizeof(s390_regs_common)*2;
443
                        hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
444
                        ptr+=NUM_CRS*CR_SIZE*2;
445
                        hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE);
446
                        gdb_stub_set_non_pt_regs(regs);
447
                        strcpy(output_buffer,"OK");
448
                break;
449
 
450
                /*
451
                 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
452
                 */
453
                case 'm':
454
                        ptr = &input_buffer[1];
455
 
456
                        if (hexToInt(&ptr, &addr)
457
                                && *ptr++ == ','
458
                                && hexToInt(&ptr, &length)) {
459
                                if (mem2hex((char *)addr, output_buffer, length, 1))
460
                                        break;
461
                                strcpy (output_buffer, "E03");
462
                        } else
463
                                strcpy(output_buffer,"E01");
464
                        break;
465
 
466
                /*
467
                 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
468
                 */
469
                case 'M':
470
                        ptr = &input_buffer[1];
471
 
472
                        if (hexToInt(&ptr, &addr)
473
                                && *ptr++ == ','
474
                                && hexToInt(&ptr, &length)
475
                                && *ptr++ == ':') {
476
                                if (hex2mem(ptr, (char *)addr, length, 1))
477
                                        strcpy(output_buffer, "OK");
478
                                else
479
                                        strcpy(output_buffer, "E03");
480
                        }
481
                        else
482
                                strcpy(output_buffer, "E02");
483
                        break;
484
 
485
                /*
486
                 * cAA..AA    Continue at address AA..AA(optional)
487
                 */
488
                case 'c':
489
                        /* try to read optional parameter, pc unchanged if no parm */
490
 
491
                        ptr = &input_buffer[1];
492
                        if (hexToInt(&ptr, &addr))
493
                                regs->cp0_epc = addr;
494
 
495
                        /*
496
                         * Need to flush the instruction cache here, as we may
497
                         * have deposited a breakpoint, and the icache probably
498
                         * has no way of knowing that a data ref to some location
499
                         * may have changed something that is in the instruction
500
                         * cache.
501
                         * NB: We flush both caches, just to be sure...
502
                         */
503
 
504
                        flush_cache_all();
505
                        return;
506
                        /* NOTREACHED */
507
                        break;
508
 
509
 
510
                /*
511
                 * kill the program
512
                 */
513
                case 'k' :
514
                        break;          /* do nothing */
515
 
516
 
517
                /*
518
                 * Reset the whole machine (FIXME: system dependent)
519
                 */
520
                case 'r':
521
                        break;
522
 
523
 
524
                /*
525
                 * Step to next instruction
526
                 */
527
                case 's':
528
                        /*
529
                         * There is no single step insn in the MIPS ISA, so we
530
                         * use breakpoints and continue, instead.
531
                         */
532
                        single_step(regs);
533
                        flush_cache_all();
534
                        return;
535
                        /* NOTREACHED */
536
 
537
                }
538
                break;
539
 
540
                }                       /* switch */
541
 
542
                /*
543
                 * reply to the request
544
                 */
545
 
546
                putpacket(output_buffer);
547
 
548
        } /* while */
549
}
550
 
551
/*
552
 * This function will generate a breakpoint exception.  It is used at the
553
 * beginning of a program to sync up with a debugger and can be used
554
 * otherwise as a quick means to stop program execution and "break" into
555
 * the debugger.
556
 */
557
void breakpoint(void)
558
{
559
        if (!gdb_stub_initialised)
560
                return;
561
        __asm__ __volatile__(
562
                        ".globl breakinst\n"
563
                        "breakinst:\t.word   %0\n\t"
564
                        :
565
                        : "i" (S390_BREAKPOINT_U16)
566
                                :
567
                                );
568
}
569
 
570
 
571
 
572
 
573
 
574
 
575
 

powered by: WebSVN 2.1.0

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