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 { 72fcb56067SGeorge V. Neville-Neil u_int32_t *frame, *lastframe; 73fcb56067SGeorge V. Neville-Neil int scp_offset; 74fcb56067SGeorge V. Neville-Neil int depth = 0; 75fcb56067SGeorge V. Neville-Neil pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 76fcb56067SGeorge V. Neville-Neil 77fcb56067SGeorge V. Neville-Neil if (intrpc != 0) 78fcb56067SGeorge V. Neville-Neil pcstack[depth++] = (pc_t) intrpc; 79fcb56067SGeorge V. Neville-Neil 80fcb56067SGeorge V. Neville-Neil aframes++; 81fcb56067SGeorge V. Neville-Neil 82fcb56067SGeorge V. Neville-Neil frame = (u_int32_t *)__builtin_frame_address(0);; 83fcb56067SGeorge V. Neville-Neil lastframe = NULL; 84fcb56067SGeorge V. Neville-Neil scp_offset = -(get_pc_str_offset() >> 2); 85fcb56067SGeorge V. Neville-Neil 86fcb56067SGeorge V. Neville-Neil while ((frame != NULL) && (depth < pcstack_limit)) { 87fcb56067SGeorge V. Neville-Neil db_addr_t scp; 88fcb56067SGeorge V. Neville-Neil #if 0 89fcb56067SGeorge V. Neville-Neil u_int32_t savecode; 90fcb56067SGeorge V. Neville-Neil int r; 91fcb56067SGeorge V. Neville-Neil u_int32_t *rp; 92fcb56067SGeorge V. Neville-Neil #endif 93fcb56067SGeorge V. Neville-Neil 94fcb56067SGeorge V. Neville-Neil /* 95fcb56067SGeorge V. Neville-Neil * In theory, the SCP isn't guaranteed to be in the function 96fcb56067SGeorge V. Neville-Neil * that generated the stack frame. We hope for the best. 97fcb56067SGeorge V. Neville-Neil */ 98fcb56067SGeorge V. Neville-Neil scp = frame[FR_SCP]; 99fcb56067SGeorge V. Neville-Neil 100fcb56067SGeorge V. Neville-Neil if (aframes > 0) { 101fcb56067SGeorge V. Neville-Neil aframes--; 102fcb56067SGeorge V. Neville-Neil if ((aframes == 0) && (caller != 0)) { 103fcb56067SGeorge V. Neville-Neil pcstack[depth++] = caller; 104fcb56067SGeorge V. Neville-Neil } 105fcb56067SGeorge V. Neville-Neil } 106fcb56067SGeorge V. Neville-Neil else { 107fcb56067SGeorge V. Neville-Neil pcstack[depth++] = scp; 108fcb56067SGeorge V. Neville-Neil } 109fcb56067SGeorge V. Neville-Neil 110fcb56067SGeorge V. Neville-Neil #if 0 111fcb56067SGeorge V. Neville-Neil savecode = ((u_int32_t *)scp)[scp_offset]; 112fcb56067SGeorge V. Neville-Neil if ((savecode & 0x0e100000) == 0x08000000) { 113fcb56067SGeorge V. Neville-Neil /* Looks like an STM */ 114fcb56067SGeorge V. Neville-Neil rp = frame - 4; 115fcb56067SGeorge V. Neville-Neil for (r = 10; r >= 0; r--) { 116fcb56067SGeorge V. Neville-Neil if (savecode & (1 << r)) { 117fcb56067SGeorge V. Neville-Neil /* register r == *rp-- */ 118fcb56067SGeorge V. Neville-Neil } 119fcb56067SGeorge V. Neville-Neil } 120fcb56067SGeorge V. Neville-Neil } 121fcb56067SGeorge V. Neville-Neil #endif 122fcb56067SGeorge V. Neville-Neil 123fcb56067SGeorge V. Neville-Neil /* 124fcb56067SGeorge V. Neville-Neil * Switch to next frame up 125fcb56067SGeorge V. Neville-Neil */ 126fcb56067SGeorge V. Neville-Neil if (frame[FR_RFP] == 0) 127fcb56067SGeorge V. Neville-Neil break; /* Top of stack */ 128fcb56067SGeorge V. Neville-Neil 129fcb56067SGeorge V. Neville-Neil lastframe = frame; 130fcb56067SGeorge V. Neville-Neil frame = (u_int32_t *)(frame[FR_RFP]); 131fcb56067SGeorge V. Neville-Neil 132fcb56067SGeorge V. Neville-Neil if (INKERNEL((int)frame)) { 133fcb56067SGeorge V. Neville-Neil /* staying in kernel */ 134fcb56067SGeorge V. Neville-Neil if (frame <= lastframe) { 135fcb56067SGeorge V. Neville-Neil /* bad frame pointer */ 136fcb56067SGeorge V. Neville-Neil break; 137fcb56067SGeorge V. Neville-Neil } 138fcb56067SGeorge V. Neville-Neil } 139fcb56067SGeorge V. Neville-Neil else 140fcb56067SGeorge V. Neville-Neil break; 141fcb56067SGeorge V. Neville-Neil } 142fcb56067SGeorge V. Neville-Neil 143fcb56067SGeorge V. Neville-Neil for (; depth < pcstack_limit; depth++) { 144fcb56067SGeorge V. Neville-Neil pcstack[depth] = 0; 145fcb56067SGeorge V. Neville-Neil } 146fcb56067SGeorge V. Neville-Neil } 147fcb56067SGeorge V. Neville-Neil 148fcb56067SGeorge V. Neville-Neil void 149fcb56067SGeorge V. Neville-Neil dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 150fcb56067SGeorge V. Neville-Neil { 151fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 152fcb56067SGeorge V. Neville-Neil } 153fcb56067SGeorge V. Neville-Neil 154fcb56067SGeorge V. Neville-Neil int 155fcb56067SGeorge V. Neville-Neil dtrace_getustackdepth(void) 156fcb56067SGeorge V. Neville-Neil { 157fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 158fcb56067SGeorge V. Neville-Neil return (0); 159fcb56067SGeorge V. Neville-Neil } 160fcb56067SGeorge V. Neville-Neil 161fcb56067SGeorge V. Neville-Neil void 162fcb56067SGeorge V. Neville-Neil dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 163fcb56067SGeorge V. Neville-Neil { 164fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 165fcb56067SGeorge V. Neville-Neil } 166fcb56067SGeorge V. Neville-Neil 167fcb56067SGeorge V. Neville-Neil /*ARGSUSED*/ 168fcb56067SGeorge V. Neville-Neil uint64_t 169fcb56067SGeorge V. Neville-Neil dtrace_getarg(int arg, int aframes) 170fcb56067SGeorge V. Neville-Neil { 171fcb56067SGeorge V. Neville-Neil /* struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/ 172fcb56067SGeorge V. Neville-Neil 173fcb56067SGeorge V. Neville-Neil return (0); 174fcb56067SGeorge V. Neville-Neil } 175fcb56067SGeorge V. Neville-Neil 176fcb56067SGeorge V. Neville-Neil int 177fcb56067SGeorge V. Neville-Neil dtrace_getstackdepth(int aframes) 178fcb56067SGeorge V. Neville-Neil { 179fcb56067SGeorge V. Neville-Neil u_int32_t *frame, *lastframe; 180fcb56067SGeorge V. Neville-Neil int scp_offset; 181fcb56067SGeorge V. Neville-Neil int depth = 1; 182fcb56067SGeorge V. Neville-Neil 183fcb56067SGeorge V. Neville-Neil frame = (u_int32_t *)__builtin_frame_address(0);; 184fcb56067SGeorge V. Neville-Neil lastframe = NULL; 185fcb56067SGeorge V. Neville-Neil scp_offset = -(get_pc_str_offset() >> 2); 186fcb56067SGeorge V. Neville-Neil 187fcb56067SGeorge V. Neville-Neil while (frame != NULL) { 188fcb56067SGeorge V. Neville-Neil db_addr_t scp; 189fcb56067SGeorge V. Neville-Neil #if 0 190fcb56067SGeorge V. Neville-Neil u_int32_t savecode; 191fcb56067SGeorge V. Neville-Neil int r; 192fcb56067SGeorge V. Neville-Neil u_int32_t *rp; 193fcb56067SGeorge V. Neville-Neil #endif 194fcb56067SGeorge V. Neville-Neil 195fcb56067SGeorge V. Neville-Neil /* 196fcb56067SGeorge V. Neville-Neil * In theory, the SCP isn't guaranteed to be in the function 197fcb56067SGeorge V. Neville-Neil * that generated the stack frame. We hope for the best. 198fcb56067SGeorge V. Neville-Neil */ 199fcb56067SGeorge V. Neville-Neil scp = frame[FR_SCP]; 200fcb56067SGeorge V. Neville-Neil 201fcb56067SGeorge V. Neville-Neil depth++; 202fcb56067SGeorge V. Neville-Neil 203fcb56067SGeorge V. Neville-Neil /* 204fcb56067SGeorge V. Neville-Neil * Switch to next frame up 205fcb56067SGeorge V. Neville-Neil */ 206fcb56067SGeorge V. Neville-Neil if (frame[FR_RFP] == 0) 207fcb56067SGeorge V. Neville-Neil break; /* Top of stack */ 208fcb56067SGeorge V. Neville-Neil 209fcb56067SGeorge V. Neville-Neil lastframe = frame; 210fcb56067SGeorge V. Neville-Neil frame = (u_int32_t *)(frame[FR_RFP]); 211fcb56067SGeorge V. Neville-Neil 212fcb56067SGeorge V. Neville-Neil if (INKERNEL((int)frame)) { 213fcb56067SGeorge V. Neville-Neil /* staying in kernel */ 214fcb56067SGeorge V. Neville-Neil if (frame <= lastframe) { 215fcb56067SGeorge V. Neville-Neil /* bad frame pointer */ 216fcb56067SGeorge V. Neville-Neil break; 217fcb56067SGeorge V. Neville-Neil } 218fcb56067SGeorge V. Neville-Neil } 219fcb56067SGeorge V. Neville-Neil else 220fcb56067SGeorge V. Neville-Neil break; 221fcb56067SGeorge V. Neville-Neil } 222fcb56067SGeorge V. Neville-Neil 223fcb56067SGeorge V. Neville-Neil if (depth < aframes) 224fcb56067SGeorge V. Neville-Neil return 0; 225fcb56067SGeorge V. Neville-Neil else 226fcb56067SGeorge V. Neville-Neil return depth - aframes; 227fcb56067SGeorge V. Neville-Neil 228fcb56067SGeorge V. Neville-Neil } 229fcb56067SGeorge V. Neville-Neil 230fcb56067SGeorge V. Neville-Neil ulong_t 231fcb56067SGeorge V. Neville-Neil dtrace_getreg(struct trapframe *rp, uint_t reg) 232fcb56067SGeorge V. Neville-Neil { 233fcb56067SGeorge V. Neville-Neil printf("IMPLEMENT ME: %s\n", __func__); 234fcb56067SGeorge V. Neville-Neil 235fcb56067SGeorge V. Neville-Neil return (0); 236fcb56067SGeorge V. Neville-Neil } 237fcb56067SGeorge V. Neville-Neil 238fcb56067SGeorge V. Neville-Neil static int 239fcb56067SGeorge V. Neville-Neil dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 240fcb56067SGeorge V. Neville-Neil { 241fcb56067SGeorge V. Neville-Neil 242fcb56067SGeorge V. Neville-Neil if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 243fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 244fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 245fcb56067SGeorge V. Neville-Neil return (0); 246fcb56067SGeorge V. Neville-Neil } 247fcb56067SGeorge V. Neville-Neil 248fcb56067SGeorge V. Neville-Neil return (1); 249fcb56067SGeorge V. Neville-Neil } 250fcb56067SGeorge V. Neville-Neil 251fcb56067SGeorge V. Neville-Neil void 252fcb56067SGeorge V. Neville-Neil dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 253fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 254fcb56067SGeorge V. Neville-Neil { 255fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 256fcb56067SGeorge V. Neville-Neil dtrace_copy(uaddr, kaddr, size); 257fcb56067SGeorge V. Neville-Neil } 258fcb56067SGeorge V. Neville-Neil 259fcb56067SGeorge V. Neville-Neil void 260fcb56067SGeorge V. Neville-Neil dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 261fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 262fcb56067SGeorge V. Neville-Neil { 263fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 264fcb56067SGeorge V. Neville-Neil dtrace_copy(kaddr, uaddr, size); 265fcb56067SGeorge V. Neville-Neil } 266fcb56067SGeorge V. Neville-Neil 267fcb56067SGeorge V. Neville-Neil void 268fcb56067SGeorge V. Neville-Neil dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 269fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 270fcb56067SGeorge V. Neville-Neil { 271fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 272fcb56067SGeorge V. Neville-Neil dtrace_copystr(uaddr, kaddr, size, flags); 273fcb56067SGeorge V. Neville-Neil } 274fcb56067SGeorge V. Neville-Neil 275fcb56067SGeorge V. Neville-Neil void 276fcb56067SGeorge V. Neville-Neil dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 277fcb56067SGeorge V. Neville-Neil volatile uint16_t *flags) 278fcb56067SGeorge V. Neville-Neil { 279fcb56067SGeorge V. Neville-Neil if (dtrace_copycheck(uaddr, kaddr, size)) 280fcb56067SGeorge V. Neville-Neil dtrace_copystr(kaddr, uaddr, size, flags); 281fcb56067SGeorge V. Neville-Neil } 282fcb56067SGeorge V. Neville-Neil 283fcb56067SGeorge V. Neville-Neil uint8_t 284fcb56067SGeorge V. Neville-Neil dtrace_fuword8(void *uaddr) 285fcb56067SGeorge V. Neville-Neil { 286fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 287fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 288fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 289fcb56067SGeorge V. Neville-Neil return (0); 290fcb56067SGeorge V. Neville-Neil } 291fcb56067SGeorge V. Neville-Neil return (dtrace_fuword8_nocheck(uaddr)); 292fcb56067SGeorge V. Neville-Neil } 293fcb56067SGeorge V. Neville-Neil 294fcb56067SGeorge V. Neville-Neil uint16_t 295fcb56067SGeorge V. Neville-Neil dtrace_fuword16(void *uaddr) 296fcb56067SGeorge V. Neville-Neil { 297fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 298fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 299fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 300fcb56067SGeorge V. Neville-Neil return (0); 301fcb56067SGeorge V. Neville-Neil } 302fcb56067SGeorge V. Neville-Neil return (dtrace_fuword16_nocheck(uaddr)); 303fcb56067SGeorge V. Neville-Neil } 304fcb56067SGeorge V. Neville-Neil 305fcb56067SGeorge V. Neville-Neil uint32_t 306fcb56067SGeorge V. Neville-Neil dtrace_fuword32(void *uaddr) 307fcb56067SGeorge V. Neville-Neil { 308fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 309fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 310fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 311fcb56067SGeorge V. Neville-Neil return (0); 312fcb56067SGeorge V. Neville-Neil } 313fcb56067SGeorge V. Neville-Neil return (dtrace_fuword32_nocheck(uaddr)); 314fcb56067SGeorge V. Neville-Neil } 315fcb56067SGeorge V. Neville-Neil 316fcb56067SGeorge V. Neville-Neil uint64_t 317fcb56067SGeorge V. Neville-Neil dtrace_fuword64(void *uaddr) 318fcb56067SGeorge V. Neville-Neil { 319fcb56067SGeorge V. Neville-Neil if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 320fcb56067SGeorge V. Neville-Neil DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 321fcb56067SGeorge V. Neville-Neil cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 322fcb56067SGeorge V. Neville-Neil return (0); 323fcb56067SGeorge V. Neville-Neil } 324fcb56067SGeorge V. Neville-Neil return (dtrace_fuword64_nocheck(uaddr)); 325fcb56067SGeorge V. Neville-Neil } 326fcb56067SGeorge V. Neville-Neil 327fcb56067SGeorge V. Neville-Neil #define __with_interrupts_disabled(expr) \ 328fcb56067SGeorge V. Neville-Neil do { \ 329fcb56067SGeorge V. Neville-Neil u_int cpsr_save, tmp; \ 330fcb56067SGeorge V. Neville-Neil \ 331fcb56067SGeorge V. Neville-Neil __asm __volatile( \ 332fcb56067SGeorge V. Neville-Neil "mrs %0, cpsr;" \ 333fcb56067SGeorge V. Neville-Neil "orr %1, %0, %2;" \ 334fcb56067SGeorge V. Neville-Neil "msr cpsr_fsxc, %1;" \ 335fcb56067SGeorge V. Neville-Neil : "=r" (cpsr_save), "=r" (tmp) \ 336fcb56067SGeorge V. Neville-Neil : "I" (PSR_I | PSR_F) \ 337fcb56067SGeorge V. Neville-Neil : "cc" ); \ 338fcb56067SGeorge V. Neville-Neil (expr); \ 339fcb56067SGeorge V. Neville-Neil __asm __volatile( \ 340fcb56067SGeorge V. Neville-Neil "msr cpsr_fsxc, %0" \ 341fcb56067SGeorge V. Neville-Neil : /* no output */ \ 342fcb56067SGeorge V. Neville-Neil : "r" (cpsr_save) \ 343fcb56067SGeorge V. Neville-Neil : "cc" ); \ 344fcb56067SGeorge V. Neville-Neil } while(0) 345fcb56067SGeorge V. Neville-Neil 346fcb56067SGeorge V. Neville-Neil uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 347fcb56067SGeorge V. Neville-Neil { 348fcb56067SGeorge V. Neville-Neil return atomic_cmpset_32((uint32_t*)target, (uint32_t)cmp, (uint32_t)new); 349fcb56067SGeorge V. Neville-Neil 350fcb56067SGeorge V. Neville-Neil } 351fcb56067SGeorge V. Neville-Neil 352fcb56067SGeorge V. Neville-Neil void * dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new) 353fcb56067SGeorge V. Neville-Neil { 354fcb56067SGeorge V. Neville-Neil return (void*)dtrace_cas32((uint32_t*)target, (uint32_t)cmp, (uint32_t)new); 355fcb56067SGeorge V. Neville-Neil } 356fcb56067SGeorge V. Neville-Neil 357