]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/db_trace.c
Merge ACPICA 20130214.
[FreeBSD/FreeBSD.git] / sys / mips / mips / db_trace.c
1 /*-
2  * Copyright (c) 2004-2005, Juniper Networks, Inc.
3  * All rights reserved.
4  *
5  *      JNPR: db_trace.c,v 1.8 2007/08/09 11:23:32 katta
6  */
7
8 #include <sys/cdefs.h>
9 __FBSDID("$FreeBSD$");
10
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <sys/kdb.h>
14 #include <sys/proc.h>
15 #include <sys/stack.h>
16 #include <sys/sysent.h>
17
18 #include <machine/db_machdep.h>
19 #include <machine/md_var.h>
20 #include <machine/mips_opcode.h>
21 #include <machine/pcb.h>
22 #include <machine/trap.h>
23
24 #include <ddb/ddb.h>
25 #include <ddb/db_sym.h>
26
27 extern char _locore[];
28 extern char _locoreEnd[];
29 extern char edata[];
30
31 /*
32  * A function using a stack frame has the following instruction as the first
33  * one: [d]addiu sp,sp,-<frame_size>
34  *
35  * We make use of this to detect starting address of a function. This works
36  * better than using 'j ra' instruction to signify end of the previous
37  * function (for e.g. functions like boot() or panic() do not actually
38  * emit a 'j ra' instruction).
39  *
40  * XXX the abi does not require that the addiu instruction be the first one.
41  */
42 #define MIPS_START_OF_FUNCTION(ins)     ((((ins) & 0xffff8000) == 0x27bd8000) \
43         || (((ins) & 0xffff8000) == 0x67bd8000))
44
45 /*
46  * MIPS ABI 3.0 requires that all functions return using the 'j ra' instruction
47  *
48  * XXX gcc doesn't do this for functions with __noreturn__ attribute.
49  */
50 #define MIPS_END_OF_FUNCTION(ins)       ((ins) == 0x03e00008)
51
52 #if defined(__mips_n64)
53 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
54                                         ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
55 #else
56 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
57                                         ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
58 #endif
59
60 /*
61  * Functions ``special'' enough to print by name
62  */
63 #ifdef __STDC__
64 #define Name(_fn)  { (void*)_fn, # _fn }
65 #else
66 #define Name(_fn) { _fn, "_fn"}
67 #endif
68 static struct {
69         void *addr;
70         char *name;
71 }      names[] = {
72
73         Name(trap),
74         Name(MipsKernGenException),
75         Name(MipsUserGenException),
76         Name(MipsKernIntr),
77         Name(MipsUserIntr),
78         Name(cpu_switch),
79         {
80                 0, 0
81         }
82 };
83
84 /*
85  * Map a function address to a string name, if known; or a hex string.
86  */
87 static char *
88 fn_name(uintptr_t addr)
89 {
90         static char buf[17];
91         int i = 0;
92
93         db_expr_t diff;
94         c_db_sym_t sym;
95         char *symname;
96
97         diff = 0;
98         symname = NULL;
99         sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
100         db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
101         if (symname && diff == 0)
102                 return (symname);
103
104         for (i = 0; names[i].name; i++)
105                 if (names[i].addr == (void *)addr)
106                         return (names[i].name);
107         sprintf(buf, "%jx", (uintmax_t)addr);
108         return (buf);
109 }
110
111 void
112 stacktrace_subr(register_t pc, register_t sp, register_t ra,
113         int (*printfn) (const char *,...))
114 {
115         InstFmt i;
116         /*
117          * Arrays for a0..a3 registers and flags if content
118          * of these registers is valid, e.g. obtained from the stack
119          */
120         int valid_args[4];
121         uintptr_t args[4];
122         uintptr_t va, subr;
123         unsigned instr, mask;
124         unsigned int frames = 0;
125         int more, stksize, j;
126
127 /* Jump here when done with a frame, to start a new one */
128 loop:
129
130         /*
131          * Invalidate arguments values
132          */
133         valid_args[0] = 0;
134         valid_args[1] = 0;
135         valid_args[2] = 0;
136         valid_args[3] = 0;
137 /* Jump here after a nonstandard (interrupt handler) frame */
138         stksize = 0;
139         subr = 0;
140         if (frames++ > 100) {
141                 (*printfn) ("\nstackframe count exceeded\n");
142                 /* return breaks stackframe-size heuristics with gcc -O2 */
143                 goto finish;    /* XXX */
144         }
145         /* check for bad SP: could foul up next frame */
146         /*XXX MIPS64 bad: this hard-coded SP is lame */
147         if (!MIPS_IS_VALID_KERNELADDR(sp)) {
148                 (*printfn) ("SP 0x%jx: not in kernel\n", sp);
149                 ra = 0;
150                 subr = 0;
151                 goto done;
152         }
153 #define Between(x, y, z) \
154                 ( ((x) <= (y)) && ((y) < (z)) )
155 #define pcBetween(a,b) \
156                 Between((uintptr_t)a, pc, (uintptr_t)b)
157
158         /*
159          * Check for current PC in  exception handler code that don't have a
160          * preceding "j ra" at the tail of the preceding function. Depends
161          * on relative ordering of functions in exception.S, swtch.S.
162          */
163         if (pcBetween(MipsKernGenException, MipsUserGenException))
164                 subr = (uintptr_t)MipsKernGenException;
165         else if (pcBetween(MipsUserGenException, MipsKernIntr))
166                 subr = (uintptr_t)MipsUserGenException;
167         else if (pcBetween(MipsKernIntr, MipsUserIntr))
168                 subr = (uintptr_t)MipsKernIntr;
169         else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
170                 subr = (uintptr_t)MipsUserIntr;
171         else if (pcBetween(MipsTLBInvalidException, MipsTLBMissException))
172                 subr = (uintptr_t)MipsTLBInvalidException;
173         else if (pcBetween(fork_trampoline, savectx))
174                 subr = (uintptr_t)fork_trampoline;
175         else if (pcBetween(savectx, cpu_throw))
176                 subr = (uintptr_t)savectx;
177         else if (pcBetween(cpu_throw, cpu_switch))
178                 subr = (uintptr_t)cpu_throw;
179         else if (pcBetween(cpu_switch, MipsSwitchFPState))
180                 subr = (uintptr_t)cpu_switch;
181         else if (pcBetween(_locore, _locoreEnd)) {
182                 subr = (uintptr_t)_locore;
183                 ra = 0;
184                 goto done;
185         }
186         /* check for bad PC */
187         /*XXX MIPS64 bad: These hard coded constants are lame */
188         if (!MIPS_IS_VALID_KERNELADDR(pc)) {
189                 (*printfn) ("PC 0x%jx: not in kernel\n", pc);
190                 ra = 0;
191                 goto done;
192         }
193         /*
194          * Find the beginning of the current subroutine by scanning
195          * backwards from the current PC for the end of the previous
196          * subroutine.
197          */
198         if (!subr) {
199                 va = pc - sizeof(int);
200                 while (1) {
201                         instr = kdbpeek((int *)va);
202
203                         if (MIPS_START_OF_FUNCTION(instr))
204                                 break;
205
206                         if (MIPS_END_OF_FUNCTION(instr)) {
207                                 /* skip over branch-delay slot instruction */
208                                 va += 2 * sizeof(int);
209                                 break;
210                         }
211
212                         va -= sizeof(int);
213                 }
214
215                 /* skip over nulls which might separate .o files */
216                 while ((instr = kdbpeek((int *)va)) == 0)
217                         va += sizeof(int);
218                 subr = va;
219         }
220         /* scan forwards to find stack size and any saved registers */
221         stksize = 0;
222         more = 3;
223         mask = 0;
224         for (va = subr; more; va += sizeof(int),
225             more = (more == 3) ? 3 : more - 1) {
226                 /* stop if hit our current position */
227                 if (va >= pc)
228                         break;
229                 instr = kdbpeek((int *)va);
230                 i.word = instr;
231                 switch (i.JType.op) {
232                 case OP_SPECIAL:
233                         switch (i.RType.func) {
234                         case OP_JR:
235                         case OP_JALR:
236                                 more = 2;       /* stop after next instruction */
237                                 break;
238
239                         case OP_SYSCALL:
240                         case OP_BREAK:
241                                 more = 1;       /* stop now */
242                         };
243                         break;
244
245                 case OP_BCOND:
246                 case OP_J:
247                 case OP_JAL:
248                 case OP_BEQ:
249                 case OP_BNE:
250                 case OP_BLEZ:
251                 case OP_BGTZ:
252                         more = 2;       /* stop after next instruction */
253                         break;
254
255                 case OP_COP0:
256                 case OP_COP1:
257                 case OP_COP2:
258                 case OP_COP3:
259                         switch (i.RType.rs) {
260                         case OP_BCx:
261                         case OP_BCy:
262                                 more = 2;       /* stop after next instruction */
263                         };
264                         break;
265
266                 case OP_SW:
267                         /* look for saved registers on the stack */
268                         if (i.IType.rs != 29)
269                                 break;
270                         /* only restore the first one */
271                         if (mask & (1 << i.IType.rt))
272                                 break;
273                         mask |= (1 << i.IType.rt);
274                         switch (i.IType.rt) {
275                         case 4:/* a0 */
276                                 args[0] = kdbpeek((int *)(sp + (short)i.IType.imm));
277                                 valid_args[0] = 1;
278                                 break;
279
280                         case 5:/* a1 */
281                                 args[1] = kdbpeek((int *)(sp + (short)i.IType.imm));
282                                 valid_args[1] = 1;
283                                 break;
284
285                         case 6:/* a2 */
286                                 args[2] = kdbpeek((int *)(sp + (short)i.IType.imm));
287                                 valid_args[2] = 1;
288                                 break;
289
290                         case 7:/* a3 */
291                                 args[3] = kdbpeek((int *)(sp + (short)i.IType.imm));
292                                 valid_args[3] = 1;
293                                 break;
294
295                         case 31:        /* ra */
296                                 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
297                         }
298                         break;
299
300                 case OP_SD:
301                         /* look for saved registers on the stack */
302                         if (i.IType.rs != 29)
303                                 break;
304                         /* only restore the first one */
305                         if (mask & (1 << i.IType.rt))
306                                 break;
307                         mask |= (1 << i.IType.rt);
308                         switch (i.IType.rt) {
309                         case 4:/* a0 */
310                                 args[0] = kdbpeekd((int *)(sp + (short)i.IType.imm));
311                                 valid_args[0] = 1;
312                                 break;
313
314                         case 5:/* a1 */
315                                 args[1] = kdbpeekd((int *)(sp + (short)i.IType.imm));
316                                 valid_args[1] = 1;
317                                 break;
318
319                         case 6:/* a2 */
320                                 args[2] = kdbpeekd((int *)(sp + (short)i.IType.imm));
321                                 valid_args[2] = 1;
322                                 break;
323
324                         case 7:/* a3 */
325                                 args[3] = kdbpeekd((int *)(sp + (short)i.IType.imm));
326                                 valid_args[3] = 1;
327                                 break;
328
329                         case 31:        /* ra */
330                                 ra = kdbpeekd((int *)(sp + (short)i.IType.imm));
331                         }
332                         break;
333
334                 case OP_ADDI:
335                 case OP_ADDIU:
336                 case OP_DADDI:
337                 case OP_DADDIU:
338                         /* look for stack pointer adjustment */
339                         if (i.IType.rs != 29 || i.IType.rt != 29)
340                                 break;
341                         stksize = -((short)i.IType.imm);
342                 }
343         }
344
345 done:
346         (*printfn) ("%s+%x (", fn_name(subr), pc - subr);
347         for (j = 0; j < 4; j ++) {
348                 if (j > 0)
349                         (*printfn)(",");
350                 if (valid_args[j])
351                         (*printfn)("%x", args[j]);
352                 else
353                         (*printfn)("?");
354         }
355
356         (*printfn) (") ra %jx sp %jx sz %d\n", ra, sp, stksize);
357
358         if (ra) {
359                 if (pc == ra && stksize == 0)
360                         (*printfn) ("stacktrace: loop!\n");
361                 else {
362                         pc = ra;
363                         sp += stksize;
364                         ra = 0;
365                         goto loop;
366                 }
367         } else {
368 finish:
369                 if (curproc)
370                         (*printfn) ("pid %d\n", curproc->p_pid);
371                 else
372                         (*printfn) ("curproc NULL\n");
373         }
374 }
375
376
377 int
378 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
379 {
380
381         return(0);
382 }
383
384
385 int
386 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
387 {
388
389         return(0);
390 }
391
392
393 void
394 db_md_list_watchpoints()
395 {
396 }
397
398 void
399 db_trace_self(void)
400 {
401         db_trace_thread (curthread, -1);
402         return;
403 }
404
405 int
406 db_trace_thread(struct thread *thr, int count)
407 {
408         register_t pc, ra, sp;
409         struct pcb *ctx;
410
411         if (thr == curthread) {
412                 sp = (register_t)(intptr_t)__builtin_frame_address(0);
413                 ra = (register_t)(intptr_t)__builtin_return_address(0);
414
415                 __asm __volatile(
416                         "jal 99f\n"
417                         "nop\n"
418                         "99:\n"
419                          "move %0, $31\n" /* get ra */
420                          "move $31, %1\n" /* restore ra */
421                          : "=r" (pc)
422                          : "r" (ra));
423
424         } else {
425                 ctx = kdb_thr_ctx(thr);
426                 sp = (register_t)ctx->pcb_context[PREG_SP];
427                 pc = (register_t)ctx->pcb_context[PREG_PC];
428                 ra = (register_t)ctx->pcb_context[PREG_RA];
429         }
430
431         stacktrace_subr(pc, sp, ra,
432             (int (*) (const char *, ...))db_printf);
433
434         return (0);
435 }
436
437 void
438 db_show_mdpcpu(struct pcpu *pc)
439 {
440
441         db_printf("ipis         = 0x%x\n", pc->pc_pending_ipis);
442         db_printf("next ASID    = %d\n", pc->pc_next_asid);
443         db_printf("GENID        = %d\n", pc->pc_asid_generation);
444         return;
445 }