1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 * 22 * $FreeBSD: head/sys/cddl/dev/dtrace/arm/dtrace_asm.S 308427 2016-11-07 20:02:18Z gonzo $ 23 */ 24 /* 25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #define _ASM 30 #define _LOCORE 31 32 #include <sys/cpuvar_defs.h> 33 #include <sys/dtrace.h> 34 35 #include <machine/asm.h> 36 #include <arm/armreg.h> 37 38 #define PSR_I I32_bit 39 #define PSR_F F32_bit 40 41 #ifdef __ARM_BIG_ENDIAN 42 #define __BIG_ENDIAN 1 43 #endif 44 45 #define EENTRY(x) ENTRY_NP(x) 46 #define EEND(x) /* nothing */ 47 48 /* 49 void dtrace_membar_producer(void) 50 */ 51 ENTRY(dtrace_membar_producer) 52 RET 53 END(dtrace_membar_producer) 54 55 /* 56 void dtrace_membar_consumer(void) 57 */ 58 ENTRY(dtrace_membar_consumer) 59 RET 60 END(dtrace_membar_consumer) 61 62 /* 63 dtrace_icookie_t dtrace_interrupt_disable(void) 64 */ 65 ENTRY(dtrace_interrupt_disable) 66 mrs r0, cpsr 67 mov r1, r0 68 orr r1, r1, #(PSR_I | PSR_F) 69 msr cpsr_c, r1 70 RET 71 END(dtrace_interrupt_disable) 72 73 /* 74 void dtrace_interrupt_enable(dtrace_icookie_t cookie) 75 */ 76 ENTRY(dtrace_interrupt_enable) 77 and r0, r0, #(PSR_I | PSR_F) 78 mrs r1, cpsr 79 bic r1, r1, #(PSR_I | PSR_F) 80 orr r1, r1, r0 81 msr cpsr_c, r1 82 RET 83 END(dtrace_interrupt_enable) 84 85 /* 86 uint8_t 87 dtrace_fuword8_nocheck(void *addr) 88 */ 89 ENTRY(dtrace_fuword8_nocheck) 90 ldrb r3, [r0] 91 mov r0, r3 92 RET 93 END(dtrace_fuword8_nocheck) 94 95 /* 96 uint16_t 97 dtrace_fuword16_nocheck(void *addr) 98 */ 99 ENTRY(dtrace_fuword16_nocheck) 100 ldrh r3, [r0] 101 mov r0, r3 102 RET 103 END(dtrace_fuword16_nocheck) 104 105 /* 106 uint32_t 107 dtrace_fuword32_nocheck(void *addr) 108 */ 109 ENTRY(dtrace_fuword32_nocheck) 110 ldr r3, [r0] 111 mov r0, r3 112 RET 113 END(dtrace_fuword32_nocheck) 114 115 /* 116 uint64_t 117 dtrace_fuword64_nocheck(void *addr) 118 */ 119 ENTRY(dtrace_fuword64_nocheck) 120 ldm r0, {r2, r3} 121 122 mov r0, r2 123 mov r1, r3 124 #if defined(__BIG_ENDIAN__) 125 /* big endian */ 126 mov r0, r3 127 mov r1, r2 128 #else 129 /* little endian */ 130 mov r0, r2 131 mov r1, r3 132 133 #endif 134 RET 135 END(dtrace_fuword64_nocheck) 136 137 /* 138 void 139 dtrace_copy(uintptr_t uaddr, uintptr_t kaddr, size_t size) 140 */ 141 ENTRY(dtrace_copy) 142 stmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 143 teq r2, #0x00000000 144 mov r5, #0x00000000 145 beq 2f 146 147 1: ldrb r4, [r0], #0x0001 148 add r5, r5, #0x00000001 149 strb r4, [r1], #0x0001 150 teqne r5, r2 151 bne 1b 152 153 2: ldmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 154 RET 155 END(dtrace_copy) 156 157 /* 158 void 159 dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 160 volatile uint16_t *flags) 161 XXX: Check for flags? 162 */ 163 ENTRY(dtrace_copystr) 164 stmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 165 teq r2, #0x00000000 166 mov r5, #0x00000000 167 beq 2f 168 169 1: ldrb r4, [r0], #0x0001 170 add r5, r5, #0x00000001 171 teq r4, #0x00000000 172 strb r4, [r1], #0x0001 173 teqne r5, r2 174 bne 1b 175 176 2: ldmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 177 RET 178 END(dtrace_copystr) 179 180 /* 181 uintptr_t 182 dtrace_caller(int aframes) 183 */ 184 ENTRY(dtrace_caller) 185 mov r0, #-1 186 RET 187 END(dtrace_caller) 188 189 /* 190 uint32_t 191 dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 192 193 void * 194 dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new) 195 */ 196 EENTRY(dtrace_casptr) 197 ENTRY(dtrace_cas32) 198 #if __ARM_ARCH >= 6 199 200 1: ldrex r3, [r0] /* Load target */ 201 cmp r3, r1 /* Check if *target == cmp */ 202 bne 2f /* No, return */ 203 strex ip, r2, [r0] /* Store new to target */ 204 cmp ip, #0 /* Did the store succeed? */ 205 bne 1b /* No, try again */ 206 2: mov r0, r3 /* Return the value loaded from target */ 207 RET 208 209 #else 210 211 /* 212 * We don't support MP on CPUs older than v6, so just disable interrupts 213 * and use non-atomic instructions. 214 */ 215 216 stmfd sp!, {r4, r5} 217 218 mrs r3, cpsr 219 mov r4, r3 220 orr r4, r4, #(PSR_I | PSR_F) 221 msr cpsr_c, r4 222 223 ldr r5, [r0] 224 cmp r5, r1 225 movne r0, r5 226 bne 2f 227 228 str r2, [r0] 229 mov r0, r5 230 231 2: 232 msr cpsr_c, r3 233 ldmfd sp!, {r4, r5} 234 RET 235 #endif 236 END(dtrace_cas32) 237 EEND(dtrace_casptr) 238