root/arch/arm/common/vlock.S

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

/* [<][>][^][v][top][bottom][index][help] */