Merge tag 'trace-v6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[linux-2.6-block.git] / arch / arm / common / vlock.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * vlock.S - simple voting lock implementation for ARM
4  *
5  * Created by:  Dave Martin, 2012-08-16
6  * Copyright:   (C) 2012-2013  Linaro Limited
7  *
8  * This algorithm is described in more detail in
9  * Documentation/arch/arm/vlocks.rst.
10  */
11
12 #include <linux/linkage.h>
13 #include "vlock.h"
14
15 .arch armv7-a
16
17 /* Select different code if voting flags  can fit in a single word. */
18 #if VLOCK_VOTING_SIZE > 4
19 #define FEW(x...)
20 #define MANY(x...) x
21 #else
22 #define FEW(x...) x
23 #define MANY(x...)
24 #endif
25
26 @ voting lock for first-man coordination
27
28 .macro voting_begin rbase:req, rcpu:req, rscratch:req
29         mov     \rscratch, #1
30         strb    \rscratch, [\rbase, \rcpu]
31         dmb
32 .endm
33
34 .macro voting_end rbase:req, rcpu:req, rscratch:req
35         dmb
36         mov     \rscratch, #0
37         strb    \rscratch, [\rbase, \rcpu]
38         dsb     st
39         sev
40 .endm
41
42 /*
43  * The vlock structure must reside in Strongly-Ordered or Device memory.
44  * This implementation deliberately eliminates most of the barriers which
45  * would be required for other memory types, and assumes that independent
46  * writes to neighbouring locations within a cacheline do not interfere
47  * with one another.
48  */
49
50 @ r0: lock structure base
51 @ r1: CPU ID (0-based index within cluster)
52 ENTRY(vlock_trylock)
53         add     r1, r1, #VLOCK_VOTING_OFFSET
54
55         voting_begin    r0, r1, r2
56
57         ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]   @ check whether lock is held
58         cmp     r2, #VLOCK_OWNER_NONE
59         bne     trylock_fail                    @ fail if so
60
61         @ Control dependency implies strb not observable before previous ldrb.
62
63         strb    r1, [r0, #VLOCK_OWNER_OFFSET]   @ submit my vote
64
65         voting_end      r0, r1, r2              @ implies DMB
66
67         @ Wait for the current round of voting to finish:
68
69  MANY(  mov     r3, #VLOCK_VOTING_OFFSET                        )
70 0:
71  MANY(  ldr     r2, [r0, r3]                                    )
72  FEW(   ldr     r2, [r0, #VLOCK_VOTING_OFFSET]                  )
73         cmp     r2, #0
74         wfene
75         bne     0b
76  MANY(  add     r3, r3, #4                                      )
77  MANY(  cmp     r3, #VLOCK_VOTING_OFFSET + VLOCK_VOTING_SIZE    )
78  MANY(  bne     0b                                              )
79
80         @ Check who won:
81
82         dmb
83         ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]
84         eor     r0, r1, r2                      @ zero if I won, else nonzero
85         bx      lr
86
87 trylock_fail:
88         voting_end      r0, r1, r2
89         mov     r0, #1                          @ nonzero indicates that I lost
90         bx      lr
91 ENDPROC(vlock_trylock)
92
93 @ r0: lock structure base
94 ENTRY(vlock_unlock)
95         dmb
96         mov     r1, #VLOCK_OWNER_NONE
97         strb    r1, [r0, #VLOCK_OWNER_OFFSET]
98         dsb     st
99         sev
100         bx      lr
101 ENDPROC(vlock_unlock)