xref: /openbmc/linux/arch/arm/common/vlock.S (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
11802d0beSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
29762f12dSDave Martin/*
39762f12dSDave Martin * vlock.S - simple voting lock implementation for ARM
49762f12dSDave Martin *
59762f12dSDave Martin * Created by:	Dave Martin, 2012-08-16
69762f12dSDave Martin * Copyright:	(C) 2012-2013  Linaro Limited
79762f12dSDave Martin *
89762f12dSDave Martin * This algorithm is described in more detail in
9*e318b36eSJonathan Corbet * Documentation/arch/arm/vlocks.rst.
109762f12dSDave Martin */
119762f12dSDave Martin
129762f12dSDave Martin#include <linux/linkage.h>
139762f12dSDave Martin#include "vlock.h"
149762f12dSDave Martin
15a2faac39SNick Desaulniers.arch armv7-a
16a2faac39SNick Desaulniers
179762f12dSDave Martin/* Select different code if voting flags  can fit in a single word. */
189762f12dSDave Martin#if VLOCK_VOTING_SIZE > 4
199762f12dSDave Martin#define FEW(x...)
209762f12dSDave Martin#define MANY(x...) x
219762f12dSDave Martin#else
229762f12dSDave Martin#define FEW(x...) x
239762f12dSDave Martin#define MANY(x...)
249762f12dSDave Martin#endif
259762f12dSDave Martin
269762f12dSDave Martin@ voting lock for first-man coordination
279762f12dSDave Martin
289762f12dSDave Martin.macro voting_begin rbase:req, rcpu:req, rscratch:req
299762f12dSDave Martin	mov	\rscratch, #1
309762f12dSDave Martin	strb	\rscratch, [\rbase, \rcpu]
319762f12dSDave Martin	dmb
329762f12dSDave Martin.endm
339762f12dSDave Martin
349762f12dSDave Martin.macro voting_end rbase:req, rcpu:req, rscratch:req
359762f12dSDave Martin	dmb
369762f12dSDave Martin	mov	\rscratch, #0
379762f12dSDave Martin	strb	\rscratch, [\rbase, \rcpu]
3840a5c0b4SWill Deacon	dsb	st
399762f12dSDave Martin	sev
409762f12dSDave Martin.endm
419762f12dSDave Martin
429762f12dSDave Martin/*
439762f12dSDave Martin * The vlock structure must reside in Strongly-Ordered or Device memory.
449762f12dSDave Martin * This implementation deliberately eliminates most of the barriers which
459762f12dSDave Martin * would be required for other memory types, and assumes that independent
469762f12dSDave Martin * writes to neighbouring locations within a cacheline do not interfere
479762f12dSDave Martin * with one another.
489762f12dSDave Martin */
499762f12dSDave Martin
509762f12dSDave Martin@ r0: lock structure base
519762f12dSDave Martin@ r1: CPU ID (0-based index within cluster)
529762f12dSDave MartinENTRY(vlock_trylock)
539762f12dSDave Martin	add	r1, r1, #VLOCK_VOTING_OFFSET
549762f12dSDave Martin
559762f12dSDave Martin	voting_begin	r0, r1, r2
569762f12dSDave Martin
579762f12dSDave Martin	ldrb	r2, [r0, #VLOCK_OWNER_OFFSET]	@ check whether lock is held
589762f12dSDave Martin	cmp	r2, #VLOCK_OWNER_NONE
599762f12dSDave Martin	bne	trylock_fail			@ fail if so
609762f12dSDave Martin
619762f12dSDave Martin	@ Control dependency implies strb not observable before previous ldrb.
629762f12dSDave Martin
639762f12dSDave Martin	strb	r1, [r0, #VLOCK_OWNER_OFFSET]	@ submit my vote
649762f12dSDave Martin
659762f12dSDave Martin	voting_end	r0, r1, r2		@ implies DMB
669762f12dSDave Martin
679762f12dSDave Martin	@ Wait for the current round of voting to finish:
689762f12dSDave Martin
699762f12dSDave Martin MANY(	mov	r3, #VLOCK_VOTING_OFFSET			)
709762f12dSDave Martin0:
719762f12dSDave Martin MANY(	ldr	r2, [r0, r3]					)
729762f12dSDave Martin FEW(	ldr	r2, [r0, #VLOCK_VOTING_OFFSET]			)
739762f12dSDave Martin	cmp	r2, #0
749762f12dSDave Martin	wfene
759762f12dSDave Martin	bne	0b
769762f12dSDave Martin MANY(	add	r3, r3, #4					)
779762f12dSDave Martin MANY(	cmp	r3, #VLOCK_VOTING_OFFSET + VLOCK_VOTING_SIZE	)
789762f12dSDave Martin MANY(	bne	0b						)
799762f12dSDave Martin
809762f12dSDave Martin	@ Check who won:
819762f12dSDave Martin
829762f12dSDave Martin	dmb
839762f12dSDave Martin	ldrb	r2, [r0, #VLOCK_OWNER_OFFSET]
849762f12dSDave Martin	eor	r0, r1, r2			@ zero if I won, else nonzero
859762f12dSDave Martin	bx	lr
869762f12dSDave Martin
879762f12dSDave Martintrylock_fail:
889762f12dSDave Martin	voting_end	r0, r1, r2
899762f12dSDave Martin	mov	r0, #1				@ nonzero indicates that I lost
909762f12dSDave Martin	bx	lr
919762f12dSDave MartinENDPROC(vlock_trylock)
929762f12dSDave Martin
939762f12dSDave Martin@ r0: lock structure base
949762f12dSDave MartinENTRY(vlock_unlock)
959762f12dSDave Martin	dmb
969762f12dSDave Martin	mov	r1, #VLOCK_OWNER_NONE
979762f12dSDave Martin	strb	r1, [r0, #VLOCK_OWNER_OFFSET]
9840a5c0b4SWill Deacon	dsb	st
999762f12dSDave Martin	sev
1009762f12dSDave Martin	bx	lr
1019762f12dSDave MartinENDPROC(vlock_unlock)
102