4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
28 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/stack.h>
36 #include <machine/frame.h>
37 #include <machine/md_var.h>
38 #include <machine/reg.h>
41 #include <vm/vm_param.h>
44 #include <machine/db_machdep.h>
45 #include <machine/md_var.h>
46 #include <machine/mips_opcode.h>
47 #include <machine/vmparam.h>
48 #include <ddb/db_sym.h>
55 #define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
56 ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
58 #define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
59 ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
65 * Wee need some reasonable default to prevent backtrace code
66 * from wandering too far
68 #define MAX_FUNCTION_SIZE 0x10000
69 #define MAX_PROLOGUE_SIZE 0x100
71 uint8_t dtrace_fuword8_nocheck(void *);
72 uint16_t dtrace_fuword16_nocheck(void *);
73 uint32_t dtrace_fuword32_nocheck(void *);
74 uint64_t dtrace_fuword64_nocheck(void *);
76 static int dtrace_next_frame(register_t *pc, register_t *sp, register_t *args, int *valid_args);
77 static int dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra);
80 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
85 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
86 register_t sp, ra, pc;
89 pcstack[depth++] = (pc_t) intrpc;
93 sp = (register_t)(intptr_t)__builtin_frame_address(0);
94 ra = (register_t)(intptr_t)__builtin_return_address(0);
100 "move %0, $31\n" /* get ra */
101 "move $31, %1\n" /* restore ra */
105 while (depth < pcstack_limit) {
111 if ((aframes == 0) && (caller != 0)) {
112 pcstack[depth++] = caller;
116 pcstack[depth++] = callpc;
119 if (dtrace_next_frame(&pc, &sp, NULL, NULL) < 0)
123 for (; depth < pcstack_limit; depth++) {
129 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
132 struct trapframe *tf;
133 register_t sp, ra, pc;
134 volatile uint16_t *flags =
135 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
137 if (*flags & CPU_DTRACE_FAULT)
140 if (pcstack_limit <= 0)
144 * If there's no user context we still need to zero the stack.
146 if (p == NULL || (tf = curthread->td_frame) == NULL)
149 *pcstack++ = (uint64_t)p->p_pid;
152 if (pcstack_limit <= 0)
155 pc = (uint64_t)tf->pc;
156 sp = (uint64_t)tf->sp;
157 ra = (uint64_t)tf->ra;
158 *pcstack++ = (uint64_t)tf->pc;
161 * Unwind, and unwind, and unwind
164 if (dtrace_next_uframe(&pc, &sp, &ra) < 0)
170 if (pcstack_limit <= 0)
175 while (pcstack_limit-- > 0)
180 dtrace_getustackdepth(void)
184 struct trapframe *tf;
185 register_t sp, ra, pc;
186 volatile uint16_t *flags =
187 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
189 if (*flags & CPU_DTRACE_FAULT)
192 if (p == NULL || (tf = curthread->td_frame) == NULL)
195 pc = (uint64_t)tf->pc;
196 sp = (uint64_t)tf->sp;
197 ra = (uint64_t)tf->ra;
201 * Unwind, and unwind, and unwind
204 if (dtrace_next_uframe(&pc, &sp, &ra) < 0)
213 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
215 printf("IMPLEMENT ME: %s\n", __func__);
220 dtrace_getarg(int arg, int aframes)
223 register_t sp, ra, pc;
224 /* XXX: Fix this ugly code */
228 sp = (register_t)(intptr_t)__builtin_frame_address(0);
229 ra = (register_t)(intptr_t)__builtin_return_address(0);
235 "move %0, $31\n" /* get ra */
236 "move $31, %1\n" /* restore ra */
240 for (i = 0; i <= aframes + 1; i++) {
241 if (dtrace_next_frame(&pc, &sp, args, valid) < 0) {
242 printf("%s: stack ends at frame #%d\n", __func__, i);
251 printf("%s: request arg%d is not valid\n", __func__, arg);
258 dtrace_getstackdepth(int aframes)
260 register_t sp, ra, pc;
263 sp = (register_t)(intptr_t)__builtin_frame_address(0);
264 ra = (register_t)(intptr_t)__builtin_return_address(0);
270 "move %0, $31\n" /* get ra */
271 "move $31, %1\n" /* restore ra */
276 if (dtrace_next_frame(&pc, &sp, NULL, NULL) < 0)
284 return depth - aframes;
288 dtrace_getreg(struct trapframe *rp, uint_t reg)
295 dtrace_next_frame(register_t *pc, register_t *sp,
296 register_t *args, int *valid_args)
300 * Arrays for a0..a3 registers and flags if content
301 * of these registers is valid, e.g. obtained from the stack
304 unsigned instr, mask;
305 unsigned int frames = 0;
312 * Invalidate arguments values
315 for (r = 0; r < 8; r++)
319 /* Jump here after a nonstandard (interrupt handler) frame */
321 if (frames++ > 100) {
322 /* return breaks stackframe-size heuristics with gcc -O2 */
323 goto error; /* XXX */
326 /* check for bad SP: could foul up next frame */
327 if (!MIPS_IS_VALID_KERNELADDR(*sp)) {
331 /* check for bad PC */
332 if (!MIPS_IS_VALID_KERNELADDR(*pc)) {
337 * Find the beginning of the current subroutine by scanning
338 * backwards from the current PC for the end of the previous
341 va = *pc - sizeof(int);
343 instr = kdbpeek((int *)va);
345 /* [d]addiu sp,sp,-X */
346 if (((instr & 0xffff8000) == 0x27bd8000)
347 || ((instr & 0xffff8000) == 0x67bd8000))
351 if (instr == 0x03e00008) {
352 /* skip over branch-delay slot instruction */
353 va += 2 * sizeof(int);
360 /* skip over nulls which might separate .o files */
361 while ((instr = kdbpeek((int *)va)) == 0)
364 /* scan forwards to find stack size and any saved registers */
368 for (; more; va += sizeof(int),
369 more = (more == 3) ? 3 : more - 1) {
370 /* stop if hit our current position */
373 instr = kdbpeek((int *)va);
375 switch (i.JType.op) {
377 switch (i.RType.func) {
380 more = 2; /* stop after next instruction */
385 more = 1; /* stop now */
396 more = 2; /* stop after next instruction */
403 switch (i.RType.rs) {
406 more = 2; /* stop after next instruction */
411 /* look for saved registers on the stack */
412 if (i.IType.rs != 29)
414 /* only restore the first one */
415 if (mask & (1 << i.IType.rt))
417 mask |= (1 << i.IType.rt);
418 addr = (vm_offset_t)(*sp + (short)i.IType.imm);
419 switch (i.IType.rt) {
424 #if defined(__mips_n64) || defined(__mips_n32)
430 arg = i.IType.rt - 4;
432 args[arg] = kdbpeek((int*)addr);
437 ra = kdbpeek((int *)addr);
442 /* look for saved registers on the stack */
443 if (i.IType.rs != 29)
445 /* only restore the first one */
446 if (mask & (1 << i.IType.rt))
448 mask |= (1 << i.IType.rt);
449 addr = (vm_offset_t)(*sp + (short)i.IType.imm);
450 switch (i.IType.rt) {
455 #if defined(__mips_n64) || defined(__mips_n32)
461 arg = i.IType.rt - 4;
463 args[arg] = kdbpeekd((int *)addr);
469 ra = kdbpeekd((int *)addr);
477 /* look for stack pointer adjustment */
478 if (i.IType.rs != 29 || i.IType.rt != 29)
480 stksize = -((short)i.IType.imm);
484 if (!MIPS_IS_VALID_KERNELADDR(ra))
490 #if defined(__mips_o32)
492 * For MIPS32 fill out arguments 5..8 from the stack
494 for (arg = 4; arg < 8; arg++) {
495 addr = (vm_offset_t)(*sp + arg*sizeof(register_t));
497 args[arg] = kdbpeekd((int *)addr);
509 dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra)
511 int offset, registers_on_stack;
512 uint32_t opcode, mask;
513 register_t function_start;
517 volatile uint16_t *flags =
518 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
520 registers_on_stack = 0;
526 while (offset < MAX_FUNCTION_SIZE) {
527 opcode = dtrace_fuword32((void *)(vm_offset_t)(*pc - offset));
529 if (*flags & CPU_DTRACE_FAULT)
532 /* [d]addiu sp, sp, -X*/
533 if (((opcode & 0xffff8000) == 0x27bd8000)
534 || ((opcode & 0xffff8000) == 0x67bd8000)) {
535 function_start = *pc - offset;
536 registers_on_stack = 1;
541 if ((opcode & 0xffff8000) == 0x3c1c0000) {
543 * Function might start with this instruction
544 * Keep an eye on "jr ra" and sp correction
545 * with positive value further on
547 function_start = *pc - offset;
550 if (function_start) {
552 * Stop looking further. Possible end of
553 * function instruction: it means there is no
554 * stack modifications, sp is unchanged
557 /* [d]addiu sp,sp,X */
558 if (((opcode & 0xffff8000) == 0x27bd0000)
559 || ((opcode & 0xffff8000) == 0x67bd0000))
562 if (opcode == 0x03e00008)
566 offset += sizeof(int);
572 if (registers_on_stack) {
574 while ((offset < MAX_PROLOGUE_SIZE)
575 && ((function_start + offset) < *pc)) {
577 dtrace_fuword32((void *)(vm_offset_t)(function_start + offset));
578 switch (i.JType.op) {
580 /* look for saved registers on the stack */
581 if (i.IType.rs != 29)
583 /* only restore the first one */
584 if (mask & (1 << i.IType.rt))
586 mask |= (1 << i.IType.rt);
587 if (i.IType.rt == 31)
588 *ra = dtrace_fuword32((void *)(vm_offset_t)(*sp + (short)i.IType.imm));
592 /* look for saved registers on the stack */
593 if (i.IType.rs != 29)
595 /* only restore the first one */
596 if (mask & (1 << i.IType.rt))
598 mask |= (1 << i.IType.rt);
600 if (i.IType.rt == 31)
601 *ra = dtrace_fuword64((void *)(vm_offset_t)(*sp + (short)i.IType.imm));
608 /* look for stack pointer adjustment */
609 if (i.IType.rs != 29 || i.IType.rt != 29)
611 stksize = -((short)i.IType.imm);
614 offset += sizeof(int);
616 if (*flags & CPU_DTRACE_FAULT)
622 * We reached the end of backtrace
633 * We just got lost in backtrace, no big deal
635 *flags &= ~CPU_DTRACE_FAULT;
640 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
643 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
644 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
645 cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
653 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
654 volatile uint16_t *flags)
656 if (dtrace_copycheck(uaddr, kaddr, size))
657 dtrace_copy(uaddr, kaddr, size);
661 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
662 volatile uint16_t *flags)
664 if (dtrace_copycheck(uaddr, kaddr, size))
665 dtrace_copy(kaddr, uaddr, size);
669 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
670 volatile uint16_t *flags)
672 if (dtrace_copycheck(uaddr, kaddr, size))
673 dtrace_copystr(uaddr, kaddr, size, flags);
677 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
678 volatile uint16_t *flags)
680 if (dtrace_copycheck(uaddr, kaddr, size))
681 dtrace_copystr(kaddr, uaddr, size, flags);
685 dtrace_fuword8(void *uaddr)
687 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
688 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
689 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
692 return (dtrace_fuword8_nocheck(uaddr));
696 dtrace_fuword16(void *uaddr)
698 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
699 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
700 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
703 return (dtrace_fuword16_nocheck(uaddr));
707 dtrace_fuword32(void *uaddr)
709 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
710 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
711 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
714 return (dtrace_fuword32_nocheck(uaddr));
718 dtrace_fuword64(void *uaddr)
720 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
721 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
722 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
725 return (dtrace_fuword64_nocheck(uaddr));