| 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 | |
| 13 | |
| 14 |
|
| 15 | .arch armv7-a
|
| 16 |
|
| 17 | /* Select different code if voting flags can fit in a single word. */
|
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 |
|
| 26 | @ voting lock for first-man coordination
|
| 27 |
|
| 28 | .macro voting_begin rbase:req, rcpu:req, rscratch:req
|
| 29 | mov \rscratch, |
| 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, |
| 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, |
| 54 |
|
| 55 | voting_begin r0, r1, r2
|
| 56 |
|
| 57 | ldrb r2, [r0, |
| 58 | cmp r2, |
| 59 | bne trylock_fail @ fail if so
|
| 60 |
|
| 61 | @ Control dependency implies strb not observable before previous ldrb.
|
| 62 |
|
| 63 | strb r1, [r0, |
| 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, |
| 70 | 0:
|
| 71 | MANY( ldr r2, [r0, r3] )
|
| 72 | FEW( ldr r2, [r0, |
| 73 | cmp r2, |
| 74 | wfene
|
| 75 | bne 0b
|
| 76 | MANY( add r3, r3, |
| 77 | MANY( cmp r3, |
| 78 | MANY( bne 0b )
|
| 79 |
|
| 80 | @ Check who won:
|
| 81 |
|
| 82 | dmb
|
| 83 | ldrb r2, [r0, |
| 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, |
| 90 | bx lr
|
| 91 | ENDPROC(vlock_trylock)
|
| 92 |
|
| 93 | @ r0: lock structure base
|
| 94 | ENTRY(vlock_unlock)
|
| 95 | dmb
|
| 96 | mov r1, |
| 97 | strb r1, [r0, |
| 98 | dsb st
|
| 99 | sev
|
| 100 | bx lr
|
| 101 | ENDPROC(vlock_unlock)
|