/* SPDX-License-Identifier: GPL-2.0-only */1/*2* vlock.S - simple voting lock implementation for ARM3*4* Created by: Dave Martin, 2012-08-165* Copyright: (C) 2012-2013 Linaro Limited6*7* This algorithm is described in more detail in8* Documentation/arch/arm/vlocks.rst.9*/1011#include <linux/linkage.h>12#include "vlock.h"1314.arch armv7-a1516/* Select different code if voting flags can fit in a single word. */17#if VLOCK_VOTING_SIZE > 418#define FEW(x...)19#define MANY(x...) x20#else21#define FEW(x...) x22#define MANY(x...)23#endif2425@ voting lock for first-man coordination2627.macro voting_begin rbase:req, rcpu:req, rscratch:req28mov \rscratch, #129strb \rscratch, [\rbase, \rcpu]30dmb31.endm3233.macro voting_end rbase:req, rcpu:req, rscratch:req34dmb35mov \rscratch, #036strb \rscratch, [\rbase, \rcpu]37dsb st38sev39.endm4041/*42* The vlock structure must reside in Strongly-Ordered or Device memory.43* This implementation deliberately eliminates most of the barriers which44* would be required for other memory types, and assumes that independent45* writes to neighbouring locations within a cacheline do not interfere46* with one another.47*/4849@ r0: lock structure base50@ r1: CPU ID (0-based index within cluster)51ENTRY(vlock_trylock)52add r1, r1, #VLOCK_VOTING_OFFSET5354voting_begin r0, r1, r25556ldrb r2, [r0, #VLOCK_OWNER_OFFSET] @ check whether lock is held57cmp r2, #VLOCK_OWNER_NONE58bne trylock_fail @ fail if so5960@ Control dependency implies strb not observable before previous ldrb.6162strb r1, [r0, #VLOCK_OWNER_OFFSET] @ submit my vote6364voting_end r0, r1, r2 @ implies DMB6566@ Wait for the current round of voting to finish:6768MANY( mov r3, #VLOCK_VOTING_OFFSET )690:70MANY( ldr r2, [r0, r3] )71FEW( ldr r2, [r0, #VLOCK_VOTING_OFFSET] )72cmp r2, #073wfene74bne 0b75MANY( add r3, r3, #4 )76MANY( cmp r3, #VLOCK_VOTING_OFFSET + VLOCK_VOTING_SIZE )77MANY( bne 0b )7879@ Check who won:8081dmb82ldrb r2, [r0, #VLOCK_OWNER_OFFSET]83eor r0, r1, r2 @ zero if I won, else nonzero84bx lr8586trylock_fail:87voting_end r0, r1, r288mov r0, #1 @ nonzero indicates that I lost89bx lr90ENDPROC(vlock_trylock)9192@ r0: lock structure base93ENTRY(vlock_unlock)94dmb95mov r1, #VLOCK_OWNER_NONE96strb r1, [r0, #VLOCK_OWNER_OFFSET]97dsb st98sev99bx lr100ENDPROC(vlock_unlock)101102103