xref: /kvm-unit-tests/lib/arm64/spinlock.c (revision 573687f8ae790b2e434330aef68c53abfe45e86a)
1*573687f8SAndrew Jones /*
2*573687f8SAndrew Jones  * spinlocks
3*573687f8SAndrew Jones  *
4*573687f8SAndrew Jones  * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5*573687f8SAndrew Jones  *
6*573687f8SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
7*573687f8SAndrew Jones  */
8*573687f8SAndrew Jones #include <asm/spinlock.h>
9*573687f8SAndrew Jones #include <asm/barrier.h>
10*573687f8SAndrew Jones #include <asm/mmu.h>
11*573687f8SAndrew Jones 
12*573687f8SAndrew Jones void spin_lock(struct spinlock *lock)
13*573687f8SAndrew Jones {
14*573687f8SAndrew Jones 	u32 val, fail;
15*573687f8SAndrew Jones 
16*573687f8SAndrew Jones 	smp_mb();
17*573687f8SAndrew Jones 
18*573687f8SAndrew Jones 	if (!mmu_enabled()) {
19*573687f8SAndrew Jones 		lock->v = 1;
20*573687f8SAndrew Jones 		return;
21*573687f8SAndrew Jones 	}
22*573687f8SAndrew Jones 
23*573687f8SAndrew Jones 	do {
24*573687f8SAndrew Jones 		asm volatile(
25*573687f8SAndrew Jones 		"1:	ldaxr	%w0, [%2]\n"
26*573687f8SAndrew Jones 		"	cbnz	%w0, 1b\n"
27*573687f8SAndrew Jones 		"	mov	%0, #1\n"
28*573687f8SAndrew Jones 		"	stxr	%w1, %w0, [%2]\n"
29*573687f8SAndrew Jones 		: "=&r" (val), "=&r" (fail)
30*573687f8SAndrew Jones 		: "r" (&lock->v)
31*573687f8SAndrew Jones 		: "cc" );
32*573687f8SAndrew Jones 	} while (fail);
33*573687f8SAndrew Jones 	smp_mb();
34*573687f8SAndrew Jones }
35*573687f8SAndrew Jones 
36*573687f8SAndrew Jones void spin_unlock(struct spinlock *lock)
37*573687f8SAndrew Jones {
38*573687f8SAndrew Jones 	if (mmu_enabled())
39*573687f8SAndrew Jones 		asm volatile("stlrh wzr, [%0]" :: "r" (&lock->v));
40*573687f8SAndrew Jones 	else
41*573687f8SAndrew Jones 		lock->v = 0;
42*573687f8SAndrew Jones 	smp_mb();
43*573687f8SAndrew Jones }
44