1/* 2 * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <asm_macros.S> 8 9 .globl spin_lock 10 .globl spin_unlock 11 12#if ARM_ARCH_AT_LEAST(8, 0) 13/* 14 * According to the ARMv8-A Architecture Reference Manual, "when the global 15 * monitor for a PE changes from Exclusive Access state to Open Access state, 16 * an event is generated.". This applies to both AArch32 and AArch64 modes of 17 * ARMv8-A. As a result, no explicit SEV with unlock is required. 18 */ 19#define COND_SEV() 20#else 21#define COND_SEV() sev 22#endif 23 24/* 25 * Function: spin_lock 26 * ------------------- 27 * Acquires a spinlock by continuously attempting to set it. 28 * Will block (spin) until the lock is successfully acquired. 29 * 30 * Arguments: 31 * r0 - Pointer to the spinlock variable (uint32_t *lock) 32 * 33 * Return: 34 * None 35 * 36 * Description: 37 * Blocks until the lock is acquired using LDREX/STREX with WFE for wait. 38 */ 39func spin_lock 40 mov r2, #1 411: 42 ldrex r1, [r0] 43 cmp r1, #0 44 wfene 45 strexeq r1, r2, [r0] 46 cmpeq r1, #0 47 bne 1b 48 dmb 49 bx lr 50endfunc spin_lock 51 52/* 53 * Function: spin_trylock 54 * ---------------------- 55 * Attempts to acquire the spinlock once without blocking. 56 * 57 * Arguments: 58 * r0 - Pointer to the spinlock variable (uint32_t *lock) 59 * 60 * Return: 61 * r0 - 1 if lock was successfully acquired 62 * 0 if lock was already held 63 * 64 * Description: 65 * Tries once to acquire the lock using LDREX/STREX. 66 */ 67func spin_trylock 68 mov r2, #1 69 ldrex r1, [r0] 70 cmp r1, #0 71 strexeq r1, r2, [r0] 72 cmpeq r1, #0 73 dmb 74 moveq r0, #1 75 movne r0, #0 76 bx lr 77endfunc spin_trylock 78 79/* 80 * Function: spin_unlock 81 * --------------------- 82 * Releases the spinlock by clearing its value. 83 * 84 * Arguments: 85 * r0 - Pointer to the spinlock variable (uint32_t *lock) 86 * 87 * Return: 88 * None 89 * 90 * Description: 91 * Releases the lock using store-release and sends SEV. 92 */ 93func spin_unlock 94 mov r1, #0 95 stl r1, [r0] 96 COND_SEV() 97 bx lr 98endfunc spin_unlock 99