source: svn/trunk/newcon3bcm2_21bu/dta/src/gdb_nub.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 28.7 KB
Line 
1/**************************************************************
2**
3**      Broadcom Corp. Confidential
4**      Copyright 1999 - 2002 Broadcom Corp.  All Rights Reserved.
5**
6**  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7**  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8**  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9**
10**      File:         gdb_nub.c
11**      Description:  simple mips debug nub
12**      Created:      Jeff Fisher, July 7, 2004
13**
14**
15**      REVISION:
16**
17**              $Log: $
18**
19**************************************************************/
20
21
22#include "ministd.h"
23#include "bcm_mips.h"
24#include "serial.h"
25#include "cache_util.h"
26
27#undef gdb_handler
28
29/* external functions to read/write from UARTB in serial.c */
30#define dbg_putc(x) serial_putc(CONSOLE_UART,x)
31#define dbg_getc() serial_getc(CONSOLE_UART,1)
32static const char g_reg_names[ROFF_NUM_REG][7] = /*  "STATUS" takes 7 characters */
33{
34        "zero", "AT", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2",     
35        "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5",     
36        "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
37        "STATUS", "LO", "HI", "BADVA", "CAUSE", "EPC", "START", "ErrPC",
38        "40", "41", "DEPC", "42"
39};
40
41#define RS(a) (((a) >> 21) & 0x1f)              /* extract the RS field */
42#define RT(a) (((a) >> 16) & 0x1f)              /* extract the RT field */
43
44#define NOT_KSEG0_OR_KSEG1(x) ((0x80000000 > (unsigned int)(x)) || (0xc0000000 < (unsigned int)(x)))
45#define KSEG0_TO_KSEG1(x) (0xa0000000 | (unsigned int)(x))
46
47/* Locals */
48
49#define EX_MASK (0x1f << 2)
50#define TLBL_EX (0x02 << 2)
51#define IBE_EX (0x06 << 2)
52#define BP_EX (0x09 << 2)
53
54#define IN_BUF_SIZE     0x800
55#define OUT_BUF_SIZE    0x800
56
57/* PR28549, don't run dbg mode if not DEBUG is not enabled */
58#ifdef  BCM_DEBUG
59static unsigned char s_inbuf[IN_BUF_SIZE];
60static unsigned char s_outbuf[OUT_BUF_SIZE];
61#endif
62
63static const char s_hex[]="0123456789abcdef";   /* used for conversion to hex */
64
65/*
66 * The following is a mapping from our exception codes to the
67 * signals in gdb.  Definitions found in <bits/signum.h> stdc headers.
68 */
69#define SIGHUP           1      /* Hangup (POSIX).  */
70#define SIGINT           2      /* Interrupt (ANSI).  */
71#define SIGQUIT          3      /* Quit (POSIX).  */
72#define SIGILL           4      /* Illegal instruction (ANSI).  */
73#define SIGTRAP          5      /* Trace trap (POSIX).  */
74#define SIGIOT           6      /* IOT trap (4.2 BSD).  */
75#define SIGABRT          SIGIOT /* Abort (ANSI).  */
76#define SIGEMT           7
77#define SIGFPE           8      /* Floating-point exception (ANSI).  */
78#define SIGKILL          9      /* Kill, unblockable (POSIX).  */
79#define SIGBUS          10      /* BUS error (4.2 BSD).  */
80#define SIGSEGV         11      /* Segmentation violation (ANSI).  */
81#define SIGSYS          12
82#define SIGPIPE         13      /* Broken pipe (POSIX).  */
83#define SIGALRM         14      /* Alarm clock (POSIX).  */
84#define SIGTERM         15      /* Termination (ANSI).  */
85#define SIGUSR1         16      /* User-defined signal 1 (POSIX).  */
86#define SIGUSR2         17      /* User-defined signal 2 (POSIX).  */
87#define SIGCHLD         18      /* Child status has changed (POSIX).  */
88#define SIGCLD          SIGCHLD /* Same as SIGCHLD (System V).  */
89#define SIGPWR          19      /* Power failure restart (System V).  */
90#define SIGWINCH        20      /* Window size change (4.3 BSD, Sun).  */
91#define SIGURG          21      /* Urgent condition on socket (4.2 BSD).  */
92#define SIGIO           22      /* I/O now possible (4.2 BSD).  */
93#define SIGPOLL         SIGIO   /* Pollable event occurred (System V).  */
94#define SIGSTOP         23      /* Stop, unblockable (POSIX).  */
95#define SIGTSTP         24      /* Keyboard stop (POSIX).  */
96#define SIGCONT         25      /* Continue (POSIX).  */
97#define SIGTTIN         26      /* Background read from tty (POSIX).  */
98#define SIGTTOU         27      /* Background write to tty (POSIX).  */
99#define SIGVTALRM       28      /* Virtual alarm clock (4.2 BSD).  */
100#define SIGPROF         29      /* Profiling alarm clock (4.2 BSD).  */
101#define SIGXCPU         30      /* CPU limit exceeded (4.2 BSD).  */
102#define SIGXFSZ         31      /* File size limit exceeded (4.2 BSD).  */
103
104
105static const unsigned char  sigequ[16] =
106{
107        SIGINT, SIGSEGV, SIGSEGV, SIGSEGV,
108        SIGSYS, SIGSYS, SIGBUS, SIGBUS,
109        SIGSYS, SIGTRAP, SIGILL, SIGILL,
110        SIGFPE, SIGHUP, SIGHUP, SIGFPE
111};
112
113struct break_info_t
114{
115        unsigned int ref;
116        unsigned int * addr;
117        unsigned int instruction;
118};
119#define BREAK ((unsigned int)0x0007000d)
120#define MAX_BP 50
121static struct break_info_t brps[MAX_BP];
122
123static int gdb_active = 0;
124
125void gdb_console_output (const char *buf, int len);
126static void skip_user_break(unsigned int regs[]);
127static void power_off(void);
128static inline char nibble_to_hex (char i);
129static int gdb_insert_break(unsigned int * addr, unsigned int size);
130static int gdb_remove_break(unsigned int * addr, unsigned int size);
131static char * gdb_strcpy(char * dest, const char * src);
132static unsigned gdb_where(void);
133
134static void gdb_halt_ejtag(void);
135
136/* PR28549, don't run dbg mode if not DEBUG is not enabled */
137#ifdef  BCM_DEBUG
138
139/*#define nested_jump (*(unsigned*)(0x80002004))*/
140unsigned nested_jump;
141static volatile int nested_exception;
142        #ifndef CONFIG_SYMBOLS
143const char *
144bsymtable_lookup(uint32_t addr, unsigned *offset)
145{
146        *offset = (unsigned)-1;
147        return "";
148}
149
150const char *
151bsymtable_get_name(uint32_t addr, char *buf, size_t buf_len)
152{
153        snprintf(buf, buf_len, "0x%08x", addr);
154        return buf;
155}
156        #endif
157
158/****************************************************************
159* INPUTS:       none
160* OUTPUTS:      none
161* RETURNS:      none
162* FUNCTION: Flush the instruction cache.
163*
164****************************************************************/
165static void gdb_invalidate_icache(void)
166{
167        invalidate_icache_all();
168}
169
170static void gdb_flush_dcache(unsigned int start, unsigned int end)
171{
172        flush_dcache(start, end);
173}
174/****************************************************************
175* INPUTS:       inst_val - instruction value
176* OUTPUTS:      none
177* RETURNS:      return the offset from the branch instruction
178* FUNCTION: Determine the relative offset from the branch instruction.
179*
180****************************************************************/
181static int gdb_offset(unsigned int inst_val)
182{
183        int val;
184
185        val = inst_val & 0xffff;
186        if (val & 0x8000)
187                val |= 0xffff0000;
188
189        return(val << 2);
190}
191
192/****************************************************************
193* INPUTS:       regs - register array
194* OUTPUTS:      none
195* RETURNS:      return the address of the next instruction.
196* FUNCTION: Set breakpoint for next single step operation.
197*
198****************************************************************/
199static unsigned int gdb_next_pc(unsigned int regs[])
200{
201        unsigned int    inst, pc, op;
202
203        pc = regs[ROFF_PC];
204        inst = *((unsigned int *)pc);
205
206        if ((inst & 0xe0000000) != 0)
207        {
208                /* not a special,regimm,jump,branch */
209                if ((inst >> 28) == 5)
210                {
211                        op = ((inst >> 26) & 0x03);
212                        switch (op)
213                        {
214                       
215                        case 0:/* BEQL */
216
217                                if (regs[RS(inst)] == regs[RT(inst)]) /* taken */
218                                        pc += gdb_offset(inst) + 4;
219                                else
220                                        pc += 8; /* not taken */
221                                break;
222
223                        case 1:/* BNEL */
224
225                                if (regs[RS(inst)] != regs[RT(inst)]) /* taken */
226                                        pc += gdb_offset(inst) + 4;
227                                else
228                                        pc += 8; /* not taken */
229                                break;
230
231                        case 2:/* BLEZL */ 
232
233                                if (regs[RS(inst)] <= 0) /* taken */
234                                        pc += gdb_offset(inst) + 4;
235                                else
236                                        pc += 8; /* not taken */
237                                break;
238
239                        case 3:/* BGTZL */
240
241                                if (regs[RS(inst)] > 0) /* taken */
242                                        pc += gdb_offset(inst) + 4;
243                                else
244                                        pc += 8; /* not taken */
245                                break;
246                        }
247                } else
248                {
249                        pc += 4; /* go to the next one */
250                }
251        } else /* is a special,regimm,jump,branch */
252        {
253                op = ((inst >> 26) & 0x07);
254                switch (op)/* then handle each case separately */
255                {
256                case 0: /* SPECIAL format */
257
258                        if (((inst & 0x3f) == 8) ||     /* JR */
259                                ((inst & 0x3f) == 9))   /* JALR */
260                        {
261                                pc = regs[RS(inst)];    /* take the jump */
262                        } else /* all other specials */
263                                pc += 4; /* just go to the next instruction */
264                        break;
265
266                case 1: /*  REGIMM */
267
268                        if (!(inst & 0x140000)) /* if one of the branches */
269                        {
270                                if (inst & 0x10000)     /* BGEZ,BGEZAL,BGEZL,BGEZALL */
271                                {
272                                        if (((int)regs[RS(inst)]) >= 0) /* taken */
273                                                pc += gdb_offset(inst) + 4;
274                                        else
275                                                pc += 8; /* not taken */
276                                } else /* BLTZ,BLTZAL,BLTZL,BLTZALL */
277                                {
278                                        if (((int)regs[RS(inst)]) < 0) /* taken */
279                                                pc += gdb_offset(inst) + 4;
280                                        else
281                                                pc += 8; /* not taken */
282                                }
283                        } else
284                                pc += 4; /* go to the next instruction */
285                        break;
286
287                case 2: /*  J */
288                case 3: /*  JAL */
289
290                        pc = ((inst << 2) & 0x0fffffff) | ((pc + 4) & 0xf0000000);
291                        break;
292
293                case 4: /*  BEQ */
294
295                        if (regs[RS(inst)] == regs[RT(inst)]) /* taken */
296                                pc += gdb_offset(inst) + 4;
297                        else
298                                pc += 8; /* not taken */
299                        break;
300
301                case 5: /*  BNE */
302
303                        if (regs[RS(inst)] != regs[RT(inst)]) /* taken */
304                                pc += gdb_offset(inst) + 4;
305                        else
306                                pc += 8; /* not taken */
307                        break;
308
309                case 6: /*  BLEZ */
310
311                        if (regs[RS(inst)] <= 0) /* taken */
312                                pc += gdb_offset(inst) + 4;
313                        else
314                                pc += 8; /* not taken */
315                        break;
316
317                case 7: /*  BGTZ */
318
319                        if (regs[RS(inst)] > 0) /* taken */
320                                pc += gdb_offset(inst) + 4;
321                        else
322                                pc += 8; /* not taken */
323                        break;
324                }
325        }
326
327        return(pc);
328}
329
330/****************************************************************
331* INPUTS:       regs - register array
332*               set - when non-zero set the breakpoint else remove a
333*               previously set breakpoint
334* OUTPUTS:      none
335* RETURNS:      none.
336* FUNCTION: Set breakpoint at next instruction or clear previously
337*                       set breakpoint.
338*
339****************************************************************/
340
341static void gdb_step(unsigned int regs[], unsigned int set)
342{
343        static unsigned int stepping = 0; /* flag indicating break set */
344        static unsigned int inst; /* overwritten instruction */
345        static unsigned int *loc; /* where it was put */
346
347        if (stepping)
348        {
349                *loc = inst; /* put the instruction back */
350                stepping = 0; /* mark it cleared */
351        }
352
353        if (set)
354        {
355                loc = (unsigned int *)gdb_next_pc(regs);
356
357                nested_exception = 0;
358                nested_jump = gdb_where();
359                if (0 == nested_exception)
360                {
361                        nested_exception = 1;
362                        inst = *loc; /* get old instruction */
363                        *loc = 0x0000000d; /* put in a BREAK 0 instruction */
364                        stepping = 1; /* keep track of the change */
365                        gdb_flush_dcache((unsigned int)loc, (unsigned int)loc + 4);
366                }
367                nested_jump = 0;
368                nested_exception = 0;
369        }
370}
371
372/****************************************************************
373* INPUTS:       c - hex character to convert
374* OUTPUTS:      none
375* RETURNS:      integer value or -1 if not a valid hex value.
376* FUNCTION: Convert hex character to integer.
377*
378****************************************************************/
379static int gdb_hex(unsigned char c)
380{
381        if (c >= 'a' && c <= 'f')
382                return(c-'a'+10);
383
384        if (c >= '0' && c <= '9')
385                return(c-'0');
386
387        if (c >= 'A' && c <= 'F')
388                return(c-'A'+10);
389
390        return(-1);
391}
392
393
394/****************************************************************
395* INPUTS:       none
396* OUTPUTS:      buffer - gdb packet
397* RETURNS:      integer value or -1 if not a valid hex value.
398* FUNCTION: Scan for valid gdb packet of the form $<data>#<checksum>
399*                       and acknowledge the receiption.
400*
401****************************************************************/
402
403static void gdb_get_packet(unsigned char *buffer)
404{
405        unsigned char       ch, checksum, rcksum;
406        unsigned int    count, i;
407
408        do
409        {
410                /* scan for start char */
411                while ((ch = (dbg_getc() & 0x7f)) != '$')
412                        ;       
413/*              printf("Found start char\n");*/
414                restart:
415                checksum = 0;
416                rcksum = 1;     /*  and set this to something different */
417                count = 0; /*  clear the count */
418
419                while (count < IN_BUF_SIZE)
420                {
421                        ch = dbg_getc() & 0x7f;
422                        if (ch == '$') goto restart;
423                        if (ch == '#')
424                                break;
425
426                        checksum = checksum + ch;
427                        buffer[count++] = ch;
428                }
429
430                if (count >= IN_BUF_SIZE)
431                        continue; /* Buffer full so start over */
432
433                buffer[count++] = 0; /* terminate the input string */
434
435                rcksum = gdb_hex(dbg_getc() & 0x7f) << 4;
436                rcksum |= gdb_hex(dbg_getc() & 0x7f);
437
438#if 0 
439                dbg_putc('+');
440                return;
441                printf("Checksum = 0x%08x\n",checksum);
442                printf("rcksum = 0x%08x\n",rcksum);
443#endif
444                if (checksum != rcksum) /* checksum bad */
445                {
446                        dbg_putc('-'); /* nack */
447                } else
448                {
449                        /* printf("Ack \n");*/
450                        dbg_putc('+'); /* ack */
451
452                        if (buffer[2] == ':') /* is there a sequence number? */
453                        {
454                                dbg_putc(buffer[0]); /* if so, send it back too */
455                                dbg_putc(buffer[1]);
456
457                                for (i = 3; i < count; i++)     /* remove the sequence number */
458                                        buffer[i-3] = buffer[i];
459                        }
460                }
461        }
462        while (checksum != rcksum);     /* while we don't have a good one */
463}
464
465/****************************************************************
466* INPUTS:       buffer - buffer to output
467* OUTPUTS:      none
468* RETURNS:      check sum of the buffer
469* FUNCTION: Send a buffer to gdb.
470*
471****************************************************************/
472static unsigned char gdb_put_buffer(const unsigned char * buf)
473{
474        unsigned char sum;
475        sum = 0;
476        while (0 != *buf)
477        {
478                sum += *buf;
479                dbg_putc(*buf);
480                ++buf;
481        }
482        return sum;
483}
484
485/****************************************************************
486* INPUTS:       buffer - gdb packet
487* OUTPUTS:      none
488* RETURNS:      integer value or -1 if not a valid hex value.
489* FUNCTION: Send a gdb packet of the form $<data>#<checksum>.
490*
491****************************************************************/
492
493static void gdb_put_packet(unsigned char *buffer)
494{
495        unsigned char checksum;
496
497        do 
498        {
499                dbg_putc('$'); /* send the start of the packet */
500                checksum = gdb_put_buffer(buffer);
501                dbg_putc('#'); /*  send the separator */
502                dbg_putc(nibble_to_hex(checksum >> 4)); /* send the checksum */
503                dbg_putc(nibble_to_hex(checksum));
504        }
505        while ((dbg_getc() & 0x7f) != '+');     /* wait for ack */
506}
507
508/****************************************************************
509* INPUTS:       pptr - pointer to a buffer pointer containing hex chars,
510*                       null terminated
511* OUTPUTS:      pptr - updated buffer pointer to end of value
512*                       vptr - pointer to integer value
513* RETURNS:      number of characters used.
514* FUNCTION: Find hex chars and convert to integer.
515*
516****************************************************************/
517
518static unsigned int gdb_hex_to_int(unsigned char **pptr, unsigned int *vptr)
519{
520        unsigned int count = 0, value = 0;
521        unsigned char *ptr = *pptr;
522        int x;
523
524        while (*ptr)
525        {
526                if ((x = gdb_hex(*ptr)) < 0)
527                        break; /* stop when an invalid character is found */
528
529                value = (value << 4) + x;
530                ptr += 1;
531                count += 1;
532        }
533
534        *pptr = ptr;
535        *vptr = value;
536        return(count);
537}
538
539/****************************************************************
540* INPUTS:       mem - data to convert
541*                       count - size of mem.
542*                       may_fault - protect against exceptions when non-zero
543* OUTPUTS:      buf - hex buffer converted from chars in mem
544* RETURNS:      End of buffer.
545* FUNCTION: Convert the data in mem to hex and store in buf.
546*
547****************************************************************/
548static unsigned char    *gdb_mem_to_hex(unsigned char *mem, unsigned char *buf, unsigned int count)
549{
550        unsigned char       ch;
551
552        nested_exception = 0;
553        nested_jump = gdb_where();
554        if (0 == nested_exception)
555        {
556                nested_exception = 1;
557                while (count--)
558                {
559                        ch = *mem;
560                        mem += 1;
561                        *buf++ = nibble_to_hex(ch >> 4);
562                        *buf++ = nibble_to_hex(ch);
563                }
564        } else
565        {
566                buf = NULL;
567        }
568        nested_jump = 0;
569        nested_exception = 0;
570
571        return(buf);
572}
573
574/****************************************************************
575* INPUTS:       buf - buffer containing hex characters
576*                       count - size of buf.
577* OUTPUTS:      mem - binary characters converted from hex in buf
578* RETURNS:      End of mem values.
579* FUNCTION: Convert the hex in buf to binary values in mem.
580*
581****************************************************************/
582static unsigned char    *gdb_hex_to_mem(unsigned char *buf, unsigned char *mem, unsigned int count)
583{
584        unsigned char ch;
585        unsigned int addr, len;
586
587        addr = (unsigned int)mem;
588        len = count;
589
590        nested_exception = 0;
591        nested_jump = gdb_where();
592        if (0 == nested_exception)
593        {
594                nested_exception = 1;
595                while (count--)
596                {
597                        ch = gdb_hex(*buf++) << 4;
598                        ch |= gdb_hex(*buf++);
599
600                        *mem = ch;
601                        mem += 1;
602                }
603                gdb_flush_dcache(addr, addr+len);
604        } else
605        {
606                mem = NULL;
607        }
608        nested_exception = 0;
609        nested_jump = 0;
610        return(mem);
611}
612
613
614/****************************************************************
615* INPUTS:       regs - register array
616* OUTPUTS:      none
617* RETURNS:      Signal value.
618* FUNCTION: Send an exception report to gdb.
619*
620****************************************************************/
621static inline unsigned int gdb_send_exception(unsigned int regs[])
622{
623        unsigned char *ptr;
624        unsigned int sig;
625
626        sig = sigequ[(regs[ROFF_CAUSE] >> 2) & 0x0f];
627
628        ptr = s_outbuf;
629        *ptr++ = 'T';/* EPC */
630
631        *ptr++ = nibble_to_hex(sig >> 4);
632        *ptr++ = nibble_to_hex(sig);
633
634        *ptr++ = nibble_to_hex(ROFF_PC >> 4); 
635        *ptr++ = nibble_to_hex(ROFF_PC);
636        *ptr++ = ':';                   /*  separator */
637        ptr = gdb_mem_to_hex((unsigned char *)&regs[ROFF_PC], ptr, 4);
638        *ptr++ = ';'; /*  final separator */
639
640        *ptr++ = nibble_to_hex(ROFF_CAUSE >> 4); /* CAUSE */
641        *ptr++ = nibble_to_hex(ROFF_CAUSE);
642        *ptr++ = ':';
643        ptr = gdb_mem_to_hex((unsigned char *)&regs[ROFF_CAUSE], ptr, 4);
644        *ptr++ = ';';
645
646        *ptr++ = nibble_to_hex(ROFF_BADVA >> 4);/* BAD */
647        *ptr++ = nibble_to_hex(ROFF_BADVA);
648        *ptr++ = ':';
649        ptr = gdb_mem_to_hex((unsigned char *)&regs[ROFF_BADVA], ptr, 4);
650        *ptr++ = ';';
651
652        *ptr++ = nibble_to_hex(ROFF_SP >> 4);/* SP */
653        *ptr++ = nibble_to_hex(ROFF_SP);
654        *ptr++ = ':';
655        ptr = gdb_mem_to_hex((unsigned char *)&regs[ROFF_SP], ptr, 4); 
656        *ptr++ = ';';
657        *ptr++ = nibble_to_hex(ROFF_RA >> 4);/* SP */
658        *ptr++ = nibble_to_hex(ROFF_RA);
659        *ptr++ = ':';
660        ptr = gdb_mem_to_hex((unsigned char *)&regs[ROFF_RA], ptr, 4); 
661        *ptr++ = ';';
662        /* send rs and rs registers to preempt gdb request at breakpoint */
663        if (BP_EX == (regs[ROFF_CAUSE] & EX_MASK))
664        {
665                int i;
666                i = 0;
667                while ((i < MAX_BP) && (regs[ROFF_PC] != (unsigned int)brps[i].addr))
668                {
669                        ++i;
670                }
671                if (MAX_BP != i)
672                {       /* found breakpoint */
673                        unsigned char rs, rt;
674                        rs = RS(brps[i].instruction);
675                        rt = RT(brps[i].instruction);
676                        if (ROFF_SP != rs)
677                        {
678                                *ptr++ = nibble_to_hex(rs >> 4);
679                                *ptr++ = nibble_to_hex(rs);
680                                *ptr++ = ':';
681                                ptr = gdb_mem_to_hex((unsigned char *)&regs[rs], ptr, 4);
682                                *ptr++ = ';';
683                        }
684                        if ((ROFF_SP != rt) && (rt != rs))
685                        {
686                                *ptr++ = nibble_to_hex(rt >> 4);
687                                *ptr++ = nibble_to_hex(rt);
688                                *ptr++ = ':';
689                                ptr = gdb_mem_to_hex((unsigned char *)&regs[rt], ptr, 4);
690                                *ptr++ = ';';
691                        }
692                }
693        }
694        *ptr++ = 0;     /* NULL terminate */
695
696        gdb_put_packet(s_outbuf);
697
698        return(sig);
699}
700#endif
701
702
703/****************************************************************
704* INPUTS:       none
705* OUTPUTS:      none
706* RETURNS:      none.
707* FUNCTION: Set up for debugging.
708*
709****************************************************************/
710void set_debug_traps(void)
711{
712        dbg_putc('+'); /* ack everything */
713}
714
715
716/*
717Summary:
718Returns bits 'e'..'b' from word 'w',
719
720Example:
721        B_GET_BITS(0xDE,7,4)==0x0D
722        B_GET_BITS(0xDE,3,0)=0x0E
723*/
724#define B_GET_BITS(w,e,b)  (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
725
726
727/****************************************************************
728* INPUTS:       MIPS32 opcode
729* OUTPUTS:      none
730* RETURNS:      true if this opcode is a function calll
731* FUNCTION: test whether opcode is a function call
732*
733****************************************************************/
734static inline bool
735b_is_call(uint32_t opcode) 
736{
737        return(B_GET_BITS(opcode, 31, (31-5)) == 0x03) /* opcode jal */ || 
738        (B_GET_BITS(opcode, 31, (31-5)) == 0 /* opcode reg-op */ && B_GET_BITS(opcode, 5, 0) == 0x09); /* function jalr */
739}
740/****************************************************************
741* INPUTS:       cause - value of CP0_CAUSE
742*               regs - register array containing gp registers and select
743*               CP0 registers.
744* OUTPUTS:      none
745* RETURNS:      none.
746* FUNCTION: main gdb exception handler.
747*
748****************************************************************/
749void bcm_test_regs( unsigned int *regs)
750{
751        unsigned int i;
752        const unsigned int *base;
753        char buf[32];
754        unsigned cause;
755
756        for (i = 0; i < ROFF_NUM_REG; ++i)
757        {
758                if (i % 4 == 0)
759                {
760                        printf("\n");
761                }
762#ifndef BCM_DEBUG
763                printf("%6s = 0x%08x",g_reg_names[i], regs[i]);
764        }
765#else
766#if 0
767{ /* balance { so editor stops complaining. Never enable this conditional */
768#endif
769            printf("%6s = %-10s",g_reg_names[i],bsymtable_get_name(regs[i], buf, sizeof(buf)));
770    }
771        cause = regs[ROFF_CAUSE] & EX_MASK;
772        if ((TLBL_EX != cause) && (IBE_EX != cause))
773        {
774                base = (unsigned int*)regs[ROFF_SP];
775                printf("\nBacktrace PC(%s) ", bsymtable_get_name(regs[ROFF_PC], buf, sizeof(buf)));
776                printf("ra(%s):\n", bsymtable_get_name(regs[ROFF_RA], buf, sizeof(buf)));
777                for (i=0;i<256;i++,base++)
778                {
779                        unsigned offset;
780                        uint32_t addr;
781                        const char *symbol;
782                        addr = *base;
783                        if ((addr&(0x3))!=0)
784                        { /* address shall be 32 bit alligned */
785                                continue;
786                        }
787                        symbol = bsymtable_lookup(addr, &offset); 
788                        if (offset>2048)
789                        { /* test whether the symbol is good  */
790                                continue;
791                        }
792                        if (!b_is_call( ((uint32_t *)addr)[-2]))
793                        { /* test whether address points to call instruction */
794                                continue;
795                        }
796                        printf("\t%s+0x%x\n", symbol, offset);
797                }
798
799                base = (unsigned int*)regs[ROFF_PC];
800                base -= 4;
801
802                for (i = 0; i < 24; ++i)
803                {
804                        if (i % 4 == 0)
805                        {
806                                printf("\nCode @ %08x:  ",&base[i]);
807                        }
808                        printf("%08x, ",base[i]);
809                }
810        }
811
812        printf("\n");
813#endif
814}
815
816/****************************************************************
817* INPUTS:       cause - value of CP0_CAUSE
818*                       regs - register array containing gp registers and select
819*                               CP0 registers.
820* OUTPUTS:      none
821* RETURNS:      none.
822* FUNCTION: main gdb exception handler.
823*
824****************************************************************/
825extern void bprint_flush(void);
826
827void gdb_handler(unsigned int regs[], unsigned int cause)
828{
829#ifdef  BCM_DEBUG
830        unsigned char       *ptr;
831        unsigned int    sigval, addr, length;
832        unsigned int do_power_off;
833
834        sigval = 0;
835        do_power_off = 0;
836        regs[0] = 0;
837
838        if (0 == gdb_active)
839        {
840#endif
841                console_shutdown();
842                bcm_test_regs(regs);
843#ifdef  BCM_DEBUG
844                gdb_active = 1;
845#ifndef ENABLE_GDB_SERIAL
846                bprint_flush();
847                regs[ROFF_RA] = regs[ROFF_PC];
848                regs[ROFF_PC] = (unsigned int)&gdb_halt_ejtag;
849                return;
850#endif
851        printf("Waiting for gdb to connect ...\n");
852        }
853
854        gdb_step(regs, 0);      /*  clear any previous stepping action */
855        cause &= EX_MASK;
856        if ((TLBL_EX != cause) && (IBE_EX != cause))
857        {
858                skip_user_break(regs);
859        } else
860        {
861                /* we called function by invalid ptr causing this exception */
862                if (NOT_KSEG0_OR_KSEG1(regs[ROFF_PC]))
863                {
864                        regs[ROFF_PC] = regs[ROFF_RA] - 8; /* adjust pc for gdb */
865                }
866        }
867        sigval = gdb_send_exception(regs);
868
869        /*  process input commands */
870        while (1)
871        {
872                s_outbuf[0] = 0;
873                gdb_get_packet(s_inbuf);
874                switch (s_inbuf[0])
875                {
876                case '?': /*  report last signal */
877                        s_outbuf[0] = 'S';                 
878                        s_outbuf[1] = nibble_to_hex(sigval >> 4);
879                        s_outbuf[2] = nibble_to_hex(sigval);
880                        s_outbuf[3] = 0;
881                        break;
882
883                case 'd':       /*  toggle debug flag*/
884                case 'b':       /*  change baud rate */
885                        break;
886
887                case 'g':                       /*  send the registers */
888                        ptr = s_outbuf; /*  start at the beginning */
889                        ptr = gdb_mem_to_hex((unsigned char *)regs, ptr, ROFF_NUM_REG*4);
890                        *ptr = 0;
891                        break;
892
893                case 'G':                       /*  set register values */
894                        ptr = s_inbuf+1;        /*  starting position */
895
896                        if (gdb_hex_to_mem(ptr, (unsigned char *)regs, ROFF_NUM_REG*4))
897                        {
898                                gdb_strcpy(s_outbuf, "OK");
899                        } else
900                        {
901                                gdb_strcpy(s_outbuf, "E01");
902                        }
903
904                        break;
905
906                case 'm':                       /*  read memory */
907
908                        ptr = s_inbuf+1;
909
910                        if (gdb_hex_to_int(&ptr, &addr) && *ptr++ == ',' && gdb_hex_to_int(&ptr, &length))
911                        {
912                                ptr = gdb_mem_to_hex((unsigned char *)addr, s_outbuf, length);
913                                if (ptr != NULL)
914                                {
915                                        *ptr = 0;
916                                } else  /*  if some error */
917                                {
918                                        gdb_strcpy(s_outbuf, "E02");
919                                }
920                        } else    /*  command no good */
921                        {
922                                gdb_strcpy(s_outbuf, "E01");
923                        }
924
925                        break;
926
927                case 'M':                       /*  update memory */
928
929                        ptr = s_inbuf+1;        /*  start of parm data */
930
931                        if (gdb_hex_to_int(&ptr, &addr) && 
932                                *ptr++ == ',' && gdb_hex_to_int(&ptr, &length) && *ptr++ == ':')
933                        {
934                                if (gdb_hex_to_mem(ptr, (unsigned char *)addr, length))
935                                {
936                                        gdb_strcpy(s_outbuf, "OK");
937                                } else
938                                {
939                                        gdb_strcpy(s_outbuf, "E02");
940                                }
941                        } else
942                        {
943                                gdb_strcpy(s_outbuf, "E01");
944                        }
945                        break;
946
947                case 's':                       /*  handle step as continue */
948
949                        ptr = s_inbuf+1; 
950
951                        if (gdb_hex_to_int(&ptr, &addr))
952                                regs[ROFF_PC] = addr;
953
954                        gdb_step(regs, 1);      /*  set a step breakpoint */
955
956                        gdb_invalidate_icache();
957                        return;
958
959                case 'c':                       /*  continue */
960
961                        ptr = s_inbuf+1;
962
963                        if (gdb_hex_to_int(&ptr, &addr))
964                                regs[ROFF_PC] = addr;
965
966                        gdb_invalidate_icache();
967                        return;
968                case 'D':
969                case 'k':                                        /*  kill the target program */
970                        gdb_strcpy(s_outbuf, "OK");
971                        do_power_off = 1;
972                        break;
973                case 'H':
974                        gdb_strcpy(s_outbuf, "OK");
975                        break;
976                case 'Z':
977                        ptr = s_inbuf + 1;
978                        if (('0' == ptr[0]) && (',' == ptr[1]))
979                        { /* sw breakpoint */
980                                ptr += 2;
981                                if (gdb_hex_to_int(&ptr, &addr) && 
982                                        *ptr++ == ',' && 
983                                        gdb_hex_to_int(&ptr, &length) &&
984                                        (0 ==gdb_insert_break((unsigned int *)addr, length)))
985                                {
986                                        gdb_strcpy(s_outbuf, "OK");
987                                        gdb_invalidate_icache();
988                                } else
989                                {
990                                        gdb_strcpy(s_outbuf, "E02");
991                                }
992                        } else
993                        {
994                                gdb_strcpy(s_outbuf, "E02");
995                        }
996                        break;
997                case 'z':
998                        ptr = s_inbuf + 1;
999                        if (('0' == ptr[0]) && (',' == ptr[1]))
1000                        { /* sw breakpoint */
1001                                ptr += 2;
1002                                if (gdb_hex_to_int(&ptr, &addr) && 
1003                                        *ptr++ == ',' && 
1004                                        gdb_hex_to_int(&ptr, &length) &&
1005                                        (0 == gdb_remove_break((unsigned int *)addr, length)))
1006                                {
1007                                        gdb_strcpy(s_outbuf, "OK");
1008                                        gdb_invalidate_icache();
1009                                } else
1010                                {
1011                                        gdb_strcpy(s_outbuf, "E02");
1012                                }
1013                        } else
1014                        {
1015                                gdb_strcpy(s_outbuf, "E01");
1016                        }
1017                        break;
1018                default:
1019                        break;
1020                } /* switch */
1021
1022                gdb_put_packet(s_outbuf);
1023
1024                if (0 != do_power_off)
1025                {
1026                        power_off();
1027                }
1028        } /* while (1) */
1029#else
1030                while (1)
1031                {
1032                        __asm__("wait");
1033                }
1034#endif
1035        }
1036
1037        char nibble_to_hex (char i)
1038        {
1039                return s_hex[i & 0xf];
1040        }
1041
1042#ifdef  BCM_DEBUG
1043
1044        void gdb_console_output (const char *buf, int len)
1045        {
1046                unsigned char checksum;
1047                unsigned char hi_nibble;
1048                unsigned char lo_nibble;
1049
1050                dbg_putc('$'); /* send the start of the packet */
1051                dbg_putc('O');
1052                checksum = 'O';
1053                while (len--)
1054                {
1055                        hi_nibble = nibble_to_hex(*buf >> 4);
1056                        lo_nibble = nibble_to_hex(*buf++);
1057                        checksum += hi_nibble;
1058                        checksum += lo_nibble;
1059                        dbg_putc(hi_nibble);
1060                        dbg_putc(lo_nibble);
1061                }
1062
1063                dbg_putc('#'); /*  send the separator */
1064                dbg_putc(nibble_to_hex(checksum >> 4)); /* send the checksum */
1065                dbg_putc(nibble_to_hex(checksum));
1066
1067                return;
1068        }
1069
1070#define SUN_TOP_CTRL_RESET_CTRL ((unsigned int *)0xB0404008)
1071#define SUN_TOP_CTRL_SW_RESET ((unsigned int *)0xB0404014)
1072        void power_off(void)
1073        {
1074                *SUN_TOP_CTRL_RESET_CTRL = 0x0;
1075                *SUN_TOP_CTRL_RESET_CTRL = 0x8;
1076                *SUN_TOP_CTRL_SW_RESET = 0x80000000;
1077        }
1078
1079        void skip_user_break(unsigned int regs[])
1080        {
1081                unsigned int inst;
1082                inst = *((unsigned int *)regs[ROFF_PC]);
1083
1084                if (0xd == (0x3f & inst))
1085                {       /* breakpoint */
1086                        if (0x2 == (inst >> 16))
1087                        { /* user breakpoint */
1088                                regs[ROFF_PC] += 4;     /* skip to the next instruction */
1089                        }
1090                }
1091        }
1092
1093        int gdb_insert_break(unsigned int * addr, unsigned int size)
1094        {
1095                int i;
1096                if (4 != size)
1097                {
1098                        return 1;
1099                }
1100                i = MAX_BP;
1101                if (BREAK == *addr)
1102                {
1103                        i = 0;
1104                        while ((i < MAX_BP) && (addr != brps[i].addr))
1105                        {
1106                                ++i;
1107                        }
1108                }
1109                if (MAX_BP == i)
1110                {
1111                        i = 0;
1112                        while ((i < MAX_BP) && (NULL != brps[i].addr))
1113                        {
1114                                ++i;
1115                        }
1116                }
1117                if (MAX_BP != i)
1118                {
1119                        if (0 == brps[i].ref)
1120                        {
1121                                ++brps[i].ref;
1122                                brps[i].addr = addr;
1123                                brps[i].instruction = *addr;
1124                                *(unsigned int *)(KSEG0_TO_KSEG1(addr)) = BREAK;
1125                        } else
1126                        {
1127                                brps[i].ref++;
1128                        }
1129                } else
1130                { /* no free slots */
1131                        return 1;
1132                }
1133                return 0;
1134        }
1135
1136        int gdb_remove_break(unsigned int * addr, unsigned int size)
1137        {
1138                int i;
1139                if (4 != size)
1140                {
1141                        return 1;
1142                }
1143                i = 0;
1144                while ((i < MAX_BP) && (addr != brps[i].addr))
1145                {
1146                        ++i;
1147                }
1148                if (MAX_BP != i)
1149                {
1150                        if (0 == (--brps[i].ref))
1151                        {
1152                                *(unsigned int *)(KSEG0_TO_KSEG1(addr)) = brps[i].instruction;
1153                                brps[i].addr = 0;
1154                                brps[i].instruction = 0;
1155                                brps[i].ref = 0;
1156                        }
1157                } else
1158                {
1159                        return 1;
1160                }
1161                return 0;
1162        }
1163
1164        char * gdb_strcpy(char * dest, const char * src)
1165        {
1166                char * old_dest;
1167                old_dest = dest;
1168                while (0 != *src)
1169                {
1170                        *dest = *src;
1171                        ++dest;
1172                        ++src;
1173                }
1174                *dest = 0;
1175                return old_dest;
1176        }
1177
1178        unsigned gdb_where(void)
1179        {
1180                unsigned val;
1181                __asm("or %0, $0, $31" : "=r"(val));
1182                return val;
1183        }
1184
1185        void gdb_control_breakpoints(unsigned int enable)
1186        {
1187                int i;
1188                i = 0;
1189                if (0 != gdb_active)
1190                {
1191                        while ((i < MAX_BP) && (NULL != brps[i].addr))
1192                        {
1193                                *(unsigned int *)(KSEG0_TO_KSEG1(brps[i].addr)) = (0 == enable) ? brps[i].instruction : BREAK ;
1194                                ++i;
1195                        }
1196                        gdb_invalidate_icache();
1197                }
1198        }
1199#endif
1200
1201#ifdef CONFIG_WATCHDOG
1202#include "os_cpu.h"
1203#endif
1204
1205void gdb_halt_ejtag(void)
1206{
1207#ifdef CONFIG_WATCHDOG
1208        unsigned int cpu_sr;
1209    /* __asm__("sdbbp") will put the cpu in debug mode that will freeze watchdog timer */
1210        /* we also need to disable interrupt */
1211        OS_ENTER_CRITICAL();
1212        while (1);
1213        /* if we are here, it can't recover */
1214        //OS_EXIT_CRITICAL();
1215#else
1216        __asm__("sdbbp ; 1: b 1b; nop");
1217#endif
1218}       
Note: See TracBrowser for help on using the repository browser.