xref: /kvm-unit-tests/lib/arm64/spinlock.c (revision d864b580863bc86c89f92936b115eb3303756f8a)
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  */
83c36da79SAndrew Jones #include <libcflat.h>
9573687f8SAndrew Jones #include <asm/spinlock.h>
10573687f8SAndrew Jones #include <asm/barrier.h>
11573687f8SAndrew Jones #include <asm/mmu.h>
12573687f8SAndrew Jones 
spin_lock(struct spinlock * lock)13573687f8SAndrew Jones void spin_lock(struct spinlock *lock)
14573687f8SAndrew Jones {
15573687f8SAndrew Jones 	u32 val, fail;
16573687f8SAndrew Jones 
17573687f8SAndrew Jones 	if (!mmu_enabled()) {
18573687f8SAndrew Jones 		lock->v = 1;
1923fb3b17SAndrew Jones 		smp_mb();
20573687f8SAndrew Jones 		return;
21573687f8SAndrew Jones 	}
22573687f8SAndrew Jones 
23573687f8SAndrew Jones 	do {
24573687f8SAndrew Jones 		asm volatile(
25573687f8SAndrew Jones 		"1:	ldaxr	%w0, [%2]\n"
26573687f8SAndrew Jones 		"	cbnz	%w0, 1b\n"
27*d864b580SThomas Huth 		"	mov	%w0, #1\n"
28573687f8SAndrew Jones 		"	stxr	%w1, %w0, [%2]\n"
29573687f8SAndrew Jones 		: "=&r" (val), "=&r" (fail)
30573687f8SAndrew Jones 		: "r" (&lock->v)
31573687f8SAndrew Jones 		: "cc" );
32573687f8SAndrew Jones 	} while (fail);
33573687f8SAndrew Jones 	smp_mb();
34573687f8SAndrew Jones }
35573687f8SAndrew Jones 
spin_unlock(struct spinlock * lock)36573687f8SAndrew Jones void spin_unlock(struct spinlock *lock)
37573687f8SAndrew Jones {
3823fb3b17SAndrew Jones 	smp_mb();
39573687f8SAndrew Jones 	if (mmu_enabled())
40573687f8SAndrew Jones 		asm volatile("stlrh wzr, [%0]" :: "r" (&lock->v));
41573687f8SAndrew Jones 	else
42573687f8SAndrew Jones 		lock->v = 0;
43573687f8SAndrew Jones }
44