1fcb56067SGeorge V. Neville-Neil /* 2fcb56067SGeorge V. Neville-Neil * CDDL HEADER START 3fcb56067SGeorge V. Neville-Neil * 4fcb56067SGeorge V. Neville-Neil * The contents of this file are subject to the terms of the 5fcb56067SGeorge V. Neville-Neil * Common Development and Distribution License, Version 1.0 only 6fcb56067SGeorge V. Neville-Neil * (the "License"). You may not use this file except in compliance 7fcb56067SGeorge V. Neville-Neil * with the License. 8fcb56067SGeorge V. Neville-Neil * 9fcb56067SGeorge V. Neville-Neil * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10fcb56067SGeorge V. Neville-Neil * or http://www.opensolaris.org/os/licensing. 11fcb56067SGeorge V. Neville-Neil * See the License for the specific language governing permissions 12fcb56067SGeorge V. Neville-Neil * and limitations under the License. 13fcb56067SGeorge V. Neville-Neil * 14fcb56067SGeorge V. Neville-Neil * When distributing Covered Code, include this CDDL HEADER in each 15fcb56067SGeorge V. Neville-Neil * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16fcb56067SGeorge V. Neville-Neil * If applicable, add the following below this CDDL HEADER, with the 17fcb56067SGeorge V. Neville-Neil * fields enclosed by brackets "[]" replaced with your own identifying 18fcb56067SGeorge V. Neville-Neil * information: Portions Copyright [yyyy] [name of copyright owner] 19fcb56067SGeorge V. Neville-Neil * 20fcb56067SGeorge V. Neville-Neil * CDDL HEADER END 21fcb56067SGeorge V. Neville-Neil * 22fcb56067SGeorge V. Neville-Neil * $FreeBSD$ 23fcb56067SGeorge V. Neville-Neil */ 24fcb56067SGeorge V. Neville-Neil /* 25fcb56067SGeorge V. Neville-Neil * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26fcb56067SGeorge V. Neville-Neil * Use is subject to license terms. 27fcb56067SGeorge V. Neville-Neil */ 28fcb56067SGeorge V. Neville-Neil #include <sys/cdefs.h> 29fcb56067SGeorge V. Neville-Neil 30fcb56067SGeorge V. Neville-Neil #include <sys/param.h> 31fcb56067SGeorge V. Neville-Neil #include <sys/systm.h> 32fcb56067SGeorge V. Neville-Neil #include <sys/kernel.h> 33fcb56067SGeorge V. Neville-Neil #include <sys/stack.h> 34fcb56067SGeorge V. Neville-Neil #include <sys/pcpu.h> 35fcb56067SGeorge V. Neville-Neil 36fcb56067SGeorge V. Neville-Neil #include <machine/frame.h> 37fcb56067SGeorge V. Neville-Neil #include <machine/md_var.h> 38fcb56067SGeorge V. Neville-Neil #include <machine/reg.h> 39fcb56067SGeorge V. Neville-Neil 40fcb56067SGeorge V. Neville-Neil #include <vm/vm.h> 41fcb56067SGeorge V. Neville-Neil #include <vm/vm_param.h> 42fcb56067SGeorge V. Neville-Neil #include <vm/pmap.h> 43fcb56067SGeorge V. Neville-Neil 44fcb56067SGeorge V. Neville-Neil #include <machine/atomic.h> 45fcb56067SGeorge V. Neville-Neil #include <machine/db_machdep.h> 46fcb56067SGeorge V. Neville-Neil #include <machine/md_var.h> 47fcb56067SGeorge V. Neville-Neil #include <machine/vmparam.h> 48fcb56067SGeorge V. Neville-Neil #include <machine/stack.h> 49fcb56067SGeorge V. Neville-Neil #include <ddb/db_sym.h> 50fcb56067SGeorge V. Neville-Neil #include <ddb/ddb.h> 51fcb56067SGeorge V. Neville-Neil #include <sys/kdb.h> 52fcb56067SGeorge V. Neville-Neil 53fcb56067SGeorge V. Neville-Neil #include "regset.h" 54fcb56067SGeorge V. Neville-Neil 55fcb56067SGeorge V. Neville-Neil /* 56fcb56067SGeorge V. Neville-Neil * Wee need some reasonable default to prevent backtrace code 57fcb56067SGeorge V. Neville-Neil * from wandering too far 58fcb56067SGeorge V. Neville-Neil */ 59fcb56067SGeorge V. Neville-Neil #define MAX_FUNCTION_SIZE 0x10000 60fcb56067SGeorge V. Neville-Neil #define MAX_PROLOGUE_SIZE 0x100 61fcb56067SGeorge V. Neville-Neil 62fcb56067SGeorge V. Neville-Neil 63fcb56067SGeorge V. Neville-Neil uint8_t dtrace_fuword8_nocheck(void *); 64fcb56067SGeorge V. Neville-Neil uint16_t dtrace_fuword16_nocheck(void *); 65fcb56067SGeorge V. Neville-Neil uint32_t dtrace_fuword32_nocheck(void *); 66fcb56067SGeorge V. Neville-Neil uint64_t dtrace_fuword64_nocheck(void *); 67fcb56067SGeorge V. Neville-Neil 68fcb56067SGeorge V. Neville-Neil void 69fcb56067SGeorge V. Neville-Neil dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 70fcb56067SGeorge V. Neville-Neil uint32_t *intrpc) 71fcb56067SGeorge V. Neville-Neil { 72aeca5b8bSAndrew Turner struct unwind_state state; 73aeca5b8bSAndrew Turner register_t sp; 74fcb56067SGeorge V. Neville-Neil int scp_offset; 75fcb56067SGeorge V. Neville-Neil int depth = 0; 76fcb56067SGeorge V. Neville-Neil pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 77fcb56067SGeorge V. Neville-Neil 78fcb56067SGeorge V. Neville-Neil if (intrpc != 0) 79fcb56067SGeorge V. Neville-Neil pcstack[depth++] = (pc_t) intrpc; 80fcb56067SGeorge V. Neville-Neil 81fcb56067SGeorge V. Neville-Neil aframes++; 82fcb56067SGeorge V. Neville-Neil 83aeca5b8bSAndrew Turner __asm __volatile("mov %0, sp" : "=&r" (sp)); 84fcb56067SGeorge V. Neville-Neil 85aeca5b8bSAndrew Turner state.registers[FP] = (uint32_t)__builtin_frame_address(0); 86aeca5b8bSAndrew Turner state.registers[SP] = sp; 87aeca5b8bSAndrew Turner state.registers[LR] = (uint32_t)__builtin_return_address(0); 88aeca5b8bSAndrew Turner state.registers[PC] = (uint32_t)dtrace_getpcstack; 89fcb56067SGeorge V. Neville-Neil 90aeca5b8bSAndrew Turner while (depth < pcstack_limit) { 91aeca5b8bSAndrew Turner int done; 92aeca5b8bSAndrew Turner 93aeca5b8bSAndrew Turner done = unwind_stack_one(&state, 1); 94fcb56067SGeorge V. Neville-Neil 95fcb56067SGeorge V. Neville-Neil if (aframes > 0) { 96fcb56067SGeorge V. Neville-Neil aframes--; 97fcb56067SGeorge V. Neville-Neil if ((aframes == 0) && (caller != 0)) { 98fcb56067SGeorge V. Neville-Neil pcstack[depth++] = caller; 99fcb56067SGeorge V. Neville-Neil } 100fcb56067SGeorge V. Neville-Neil } 101fcb56067SGeorge V. Neville-Neil else { 102aeca5b8bSAndrew Turner pcstack[depth++] = state.registers[PC]; 103fcb56067SGeorge V. Neville-Neil } 104fcb56067SGeorge V. Neville-Neil 105aeca5b8bSAndrew Turner if (done) 106fcb56067SGeorge V. Neville-Neil break; 107fcb56067SGeorge V. Neville-Neil } 108fcb56067SGeorge V. Neville-Neil 109fcb56067SGeorge V. Neville-Neil for (; depth < pcstack_limit; depth++) { 110fcb56067SGeorge V. Neville-Neil pcstack[depth] = 0; 111fcb56067SGeorge V. Neville-Neil } 112fcb56067SGeorge V. Neville-Neil } 113fcb56067SGeorge V. Neville-Neil 114fcb56067SGeorge V. Neville-Neil void 115fcb56067SGeorge V. Neville-Neil dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 116fcb56067SGeorge V. Neville-Neil { 117fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 118fcb56067SGeorge V. Neville-Neil } 119fcb56067SGeorge V. Neville-Neil 120fcb56067SGeorge V. Neville-Neil int 121fcb56067SGeorge V. Neville-Neil dtrace_getustackdepth(void) 122fcb56067SGeorge V. Neville-Neil { 123fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 124fcb56067SGeorge V. Neville-Neil return (0); 125fcb56067SGeorge V. Neville-Neil } 126fcb56067SGeorge V. Neville-Neil 127fcb56067SGeorge V. Neville-Neil void 128fcb56067SGeorge V. Neville-Neil dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 129fcb56067SGeorge V. Neville-Neil { 130fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 131fcb56067SGeorge V. Neville-Neil } 132fcb56067SGeorge V. Neville-Neil 133fcb56067SGeorge V. Neville-Neil /*ARGSUSED*/ 134fcb56067SGeorge V. Neville-Neil uint64_t 135fcb56067SGeorge V. Neville-Neil dtrace_getarg(int arg, int aframes) 136fcb56067SGeorge V. Neville-Neil { 137fcb56067SGeorge V. Neville-Neil /* struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/ 138fcb56067SGeorge V. Neville-Neil 139fcb56067SGeorge V. Neville-Neil return (0); 140fcb56067SGeorge V. Neville-Neil } 141fcb56067SGeorge V. Neville-Neil 142fcb56067SGeorge V. Neville-Neil int 143fcb56067SGeorge V. Neville-Neil dtrace_getstackdepth(int aframes) 144fcb56067SGeorge V. Neville-Neil { 145aeca5b8bSAndrew Turner struct unwind_state state; 146aeca5b8bSAndrew Turner register_t sp; 147fcb56067SGeorge V. Neville-Neil int scp_offset; 148aeca5b8bSAndrew Turner int done = 0; 149fcb56067SGeorge V. Neville-Neil int depth = 1; 150fcb56067SGeorge V. Neville-Neil 151aeca5b8bSAndrew Turner __asm __volatile("mov %0, sp" : "=&r" (sp)); 152fcb56067SGeorge V. Neville-Neil 153aeca5b8bSAndrew Turner state.registers[FP] = (uint32_t)__builtin_frame_address(0); 154aeca5b8bSAndrew Turner state.registers[SP] = sp; 155aeca5b8bSAndrew Turner state.registers[LR] = (uint32_t)__builtin_return_address(0); 156aeca5b8bSAndrew Turner state.registers[PC] = (uint32_t)dtrace_getstackdepth; 157fcb56067SGeorge V. Neville-Neil 158aeca5b8bSAndrew Turner do { 159aeca5b8bSAndrew Turner done = unwind_stack_one(&state, 1); 160fcb56067SGeorge V. Neville-Neil depth++; 161aeca5b8bSAndrew Turner } while (!done); 162fcb56067SGeorge V. Neville-Neil 163fcb56067SGeorge V. Neville-Neil if (depth < aframes) 164fcb56067SGeorge V. Neville-Neil return 0; 165fcb56067SGeorge V. Neville-Neil else 166fcb56067SGeorge V. Neville-Neil return depth - aframes; 167fcb56067SGeorge V. Neville-Neil } 168fcb56067SGeorge V. Neville-Neil 169fcb56067SGeorge V. Neville-Neil ulong_t 170fcb56067SGeorge V. Neville-Neil dtrace_getreg(struct trapframe *rp, uint_t reg) 171fcb56067SGeorge V. Neville-Neil { 172fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 173fcb56067SGeorge V. Neville-Neil 174fcb56067SGeorge V. Neville-Neil return (0); 175fcb56067SGeorge V. Neville-Neil } 176fcb56067SGeorge V. Neville-Neil 177fcb56067SGeorge V. Neville-Neil static int 178fcb56067SGeorge V. Neville-Neil dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 179fcb56067SGeorge V. Neville-Neil { 180fcb56067SGeorge V. Neville-Neil 181fcb56067SGeorge V. Neville-Neil if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 182fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 183fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 184fcb56067SGeorge V. Neville-Neil return (0); 185fcb56067SGeorge V. Neville-Neil } 186fcb56067SGeorge V. Neville-Neil 187fcb56067SGeorge V. Neville-Neil return (1); 188fcb56067SGeorge V. Neville-Neil } 189fcb56067SGeorge V. Neville-Neil 190fcb56067SGeorge V. Neville-Neil void 191fcb56067SGeorge V. Neville-Neil dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 192fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 193fcb56067SGeorge V. Neville-Neil { 194fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 195fcb56067SGeorge V. Neville-Neil dtrace_copy(uaddr, kaddr, size); 196fcb56067SGeorge V. Neville-Neil } 197fcb56067SGeorge V. Neville-Neil 198fcb56067SGeorge V. Neville-Neil void 199fcb56067SGeorge V. Neville-Neil dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 200fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 201fcb56067SGeorge V. Neville-Neil { 202fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 203fcb56067SGeorge V. Neville-Neil dtrace_copy(kaddr, uaddr, size); 204fcb56067SGeorge V. Neville-Neil } 205fcb56067SGeorge V. Neville-Neil 206fcb56067SGeorge V. Neville-Neil void 207fcb56067SGeorge V. Neville-Neil dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 208fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 209fcb56067SGeorge V. Neville-Neil { 210fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 211fcb56067SGeorge V. Neville-Neil dtrace_copystr(uaddr, kaddr, size, flags); 212fcb56067SGeorge V. Neville-Neil } 213fcb56067SGeorge V. Neville-Neil 214fcb56067SGeorge V. Neville-Neil void 215fcb56067SGeorge V. Neville-Neil dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 216fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 217fcb56067SGeorge V. Neville-Neil { 218fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 219fcb56067SGeorge V. Neville-Neil dtrace_copystr(kaddr, uaddr, size, flags); 220fcb56067SGeorge V. Neville-Neil } 221fcb56067SGeorge V. Neville-Neil 222fcb56067SGeorge V. Neville-Neil uint8_t 223fcb56067SGeorge V. Neville-Neil dtrace_fuword8(void *uaddr) 224fcb56067SGeorge V. Neville-Neil { 225fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 226fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 227fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 228fcb56067SGeorge V. Neville-Neil return (0); 229fcb56067SGeorge V. Neville-Neil } 230fcb56067SGeorge V. Neville-Neil return (dtrace_fuword8_nocheck(uaddr)); 231fcb56067SGeorge V. Neville-Neil } 232fcb56067SGeorge V. Neville-Neil 233fcb56067SGeorge V. Neville-Neil uint16_t 234fcb56067SGeorge V. Neville-Neil dtrace_fuword16(void *uaddr) 235fcb56067SGeorge V. Neville-Neil { 236fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 237fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 238fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 239fcb56067SGeorge V. Neville-Neil return (0); 240fcb56067SGeorge V. Neville-Neil } 241fcb56067SGeorge V. Neville-Neil return (dtrace_fuword16_nocheck(uaddr)); 242fcb56067SGeorge V. Neville-Neil } 243fcb56067SGeorge V. Neville-Neil 244fcb56067SGeorge V. Neville-Neil uint32_t 245fcb56067SGeorge V. Neville-Neil dtrace_fuword32(void *uaddr) 246fcb56067SGeorge V. Neville-Neil { 247fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 248fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 249fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 250fcb56067SGeorge V. Neville-Neil return (0); 251fcb56067SGeorge V. Neville-Neil } 252fcb56067SGeorge V. Neville-Neil return (dtrace_fuword32_nocheck(uaddr)); 253fcb56067SGeorge V. Neville-Neil } 254fcb56067SGeorge V. Neville-Neil 255fcb56067SGeorge V. Neville-Neil uint64_t 256fcb56067SGeorge V. Neville-Neil dtrace_fuword64(void *uaddr) 257fcb56067SGeorge V. Neville-Neil { 258fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 259fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 260fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 261fcb56067SGeorge V. Neville-Neil return (0); 262fcb56067SGeorge V. Neville-Neil } 263fcb56067SGeorge V. Neville-Neil return (dtrace_fuword64_nocheck(uaddr)); 264fcb56067SGeorge V. Neville-Neil } 265fcb56067SGeorge V. Neville-Neil 266fcb56067SGeorge V. Neville-Neil #define __with_interrupts_disabled(expr) \ 267fcb56067SGeorge V. Neville-Neil do { \ 268fcb56067SGeorge V. Neville-Neil u_int cpsr_save, tmp; \ 269fcb56067SGeorge V. Neville-Neil \ 270fcb56067SGeorge V. Neville-Neil __asm __volatile( \ 271fcb56067SGeorge V. Neville-Neil "mrs %0, cpsr;" \ 272fcb56067SGeorge V. Neville-Neil "orr %1, %0, %2;" \ 273fcb56067SGeorge V. Neville-Neil "msr cpsr_fsxc, %1;" \ 274fcb56067SGeorge V. Neville-Neil : "=r" (cpsr_save), "=r" (tmp) \ 275fcb56067SGeorge V. Neville-Neil : "I" (PSR_I | PSR_F) \ 276fcb56067SGeorge V. Neville-Neil : "cc" ); \ 277fcb56067SGeorge V. Neville-Neil (expr); \ 278fcb56067SGeorge V. Neville-Neil __asm __volatile( \ 279fcb56067SGeorge V. Neville-Neil "msr cpsr_fsxc, %0" \ 280fcb56067SGeorge V. Neville-Neil : /* no output */ \ 281fcb56067SGeorge V. Neville-Neil : "r" (cpsr_save) \ 282fcb56067SGeorge V. Neville-Neil : "cc" ); \ 283fcb56067SGeorge V. Neville-Neil } while(0) 284fcb56067SGeorge V. Neville-Neil 285fcb56067SGeorge V. Neville-Neil uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 286fcb56067SGeorge V. Neville-Neil { 287fcb56067SGeorge V. Neville-Neil return atomic_cmpset_32((uint32_t*)target, (uint32_t)cmp, (uint32_t)new); 288fcb56067SGeorge V. Neville-Neil 289fcb56067SGeorge V. Neville-Neil } 290fcb56067SGeorge V. Neville-Neil 291fcb56067SGeorge V. Neville-Neil void * dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new) 292fcb56067SGeorge V. Neville-Neil { 293fcb56067SGeorge V. Neville-Neil return (void*)dtrace_cas32((uint32_t*)target, (uint32_t)cmp, (uint32_t)new); 294fcb56067SGeorge V. Neville-Neil } 295fcb56067SGeorge V. Neville-Neil 296