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/* 49void dtrace_membar_producer(void) 50*/ 51ENTRY(dtrace_membar_producer) 52 RET 53END(dtrace_membar_producer) 54 55/* 56void dtrace_membar_consumer(void) 57*/ 58ENTRY(dtrace_membar_consumer) 59 RET 60END(dtrace_membar_consumer) 61 62/* 63dtrace_icookie_t dtrace_interrupt_disable(void) 64*/ 65ENTRY(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 71END(dtrace_interrupt_disable) 72 73/* 74void dtrace_interrupt_enable(dtrace_icookie_t cookie) 75*/ 76ENTRY(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 83END(dtrace_interrupt_enable) 84 85/* 86uint8_t 87dtrace_fuword8_nocheck(void *addr) 88*/ 89ENTRY(dtrace_fuword8_nocheck) 90 ldrb r3, [r0] 91 mov r0, r3 92 RET 93END(dtrace_fuword8_nocheck) 94 95/* 96uint16_t 97dtrace_fuword16_nocheck(void *addr) 98*/ 99ENTRY(dtrace_fuword16_nocheck) 100 ldrh r3, [r0] 101 mov r0, r3 102 RET 103END(dtrace_fuword16_nocheck) 104 105/* 106uint32_t 107dtrace_fuword32_nocheck(void *addr) 108*/ 109ENTRY(dtrace_fuword32_nocheck) 110 ldr r3, [r0] 111 mov r0, r3 112 RET 113END(dtrace_fuword32_nocheck) 114 115/* 116uint64_t 117dtrace_fuword64_nocheck(void *addr) 118*/ 119ENTRY(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 135END(dtrace_fuword64_nocheck) 136 137/* 138void 139dtrace_copy(uintptr_t uaddr, uintptr_t kaddr, size_t size) 140*/ 141ENTRY(dtrace_copy) 142 stmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 143 teq r2, #0x00000000 144 mov r5, #0x00000000 145 beq 2f 146 1471: ldrb r4, [r0], #0x0001 148 add r5, r5, #0x00000001 149 strb r4, [r1], #0x0001 150 teqne r5, r2 151 bne 1b 152 1532: ldmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 154 RET 155END(dtrace_copy) 156 157/* 158void 159dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 160 volatile uint16_t *flags) 161XXX: Check for flags? 162*/ 163ENTRY(dtrace_copystr) 164 stmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 165 teq r2, #0x00000000 166 mov r5, #0x00000000 167 beq 2f 168 1691: 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 1762: ldmfd sp!, {r4-r5} /* stack is 8 byte aligned */ 177 RET 178END(dtrace_copystr) 179 180/* 181uintptr_t 182dtrace_caller(int aframes) 183*/ 184ENTRY(dtrace_caller) 185 mov r0, #-1 186 RET 187END(dtrace_caller) 188 189/* 190uint32_t 191dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 192 193void * 194dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new) 195*/ 196EENTRY(dtrace_casptr) 197ENTRY(dtrace_cas32) 198#if __ARM_ARCH >= 6 199 2001: 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 */ 2062: 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 2312: 232 msr cpsr_c, r3 233 ldmfd sp!, {r4, r5} 234 RET 235#endif 236END(dtrace_cas32) 237EEND(dtrace_casptr) 238