xref: /kvm-unit-tests/lib/arm64/spinlock.c (revision 23fb3b171aa1259d7f6f79b50d9930f289bbcb36)
1573687f8SAndrew Jones /*
2573687f8SAndrew Jones  * spinlocks
3573687f8SAndrew Jones  *
4573687f8SAndrew Jones  * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5573687f8SAndrew Jones  *
6573687f8SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
7573687f8SAndrew Jones  */
8573687f8SAndrew Jones #include <asm/spinlock.h>
9573687f8SAndrew Jones #include <asm/barrier.h>
10573687f8SAndrew Jones #include <asm/mmu.h>
11573687f8SAndrew Jones 
12573687f8SAndrew Jones void spin_lock(struct spinlock *lock)
13573687f8SAndrew Jones {
14573687f8SAndrew Jones 	u32 val, fail;
15573687f8SAndrew Jones 
16573687f8SAndrew Jones 	if (!mmu_enabled()) {
17573687f8SAndrew Jones 		lock->v = 1;
18*23fb3b17SAndrew Jones 		smp_mb();
19573687f8SAndrew Jones 		return;
20573687f8SAndrew Jones 	}
21573687f8SAndrew Jones 
22573687f8SAndrew Jones 	do {
23573687f8SAndrew Jones 		asm volatile(
24573687f8SAndrew Jones 		"1:	ldaxr	%w0, [%2]\n"
25573687f8SAndrew Jones 		"	cbnz	%w0, 1b\n"
26573687f8SAndrew Jones 		"	mov	%0, #1\n"
27573687f8SAndrew Jones 		"	stxr	%w1, %w0, [%2]\n"
28573687f8SAndrew Jones 		: "=&r" (val), "=&r" (fail)
29573687f8SAndrew Jones 		: "r" (&lock->v)
30573687f8SAndrew Jones 		: "cc" );
31573687f8SAndrew Jones 	} while (fail);
32573687f8SAndrew Jones 	smp_mb();
33573687f8SAndrew Jones }
34573687f8SAndrew Jones 
35573687f8SAndrew Jones void spin_unlock(struct spinlock *lock)
36573687f8SAndrew Jones {
37*23fb3b17SAndrew Jones 	smp_mb();
38573687f8SAndrew Jones 	if (mmu_enabled())
39573687f8SAndrew Jones 		asm volatile("stlrh wzr, [%0]" :: "r" (&lock->v));
40573687f8SAndrew Jones 	else
41573687f8SAndrew Jones 		lock->v = 0;
42573687f8SAndrew Jones }
43