xref: /kvm-unit-tests/lib/x86/atomic.h (revision dca3f4c041143c8e8dc70c6890a19a5730310230)
1c865f654SCornelia Huck #ifndef _X86_ATOMIC_H_
2c865f654SCornelia Huck #define _X86_ATOMIC_H_
3584afc90SJason Wang 
4ae21b795SPeter Xu #include "asm-generic/atomic.h"
5ae21b795SPeter Xu 
6*36fb9e84SSean Christopherson #include "libcflat.h"
7*36fb9e84SSean Christopherson 
8584afc90SJason Wang typedef struct {
9584afc90SJason Wang 	volatile int counter;
10584afc90SJason Wang } atomic_t;
11584afc90SJason Wang 
12584afc90SJason Wang #ifdef __i386__
13584afc90SJason Wang 
14584afc90SJason Wang /**
15584afc90SJason Wang  * atomic_read - read atomic variable
16584afc90SJason Wang  * @v: pointer of type atomic_t
17584afc90SJason Wang  *
18584afc90SJason Wang  * Atomically reads the value of @v.
19584afc90SJason Wang  */
atomic_read(const atomic_t * v)20584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
21584afc90SJason Wang {
22584afc90SJason Wang 	return v->counter;
23584afc90SJason Wang }
24584afc90SJason Wang 
25584afc90SJason Wang /**
26584afc90SJason Wang  * atomic_set - set atomic variable
27584afc90SJason Wang  * @v: pointer of type atomic_t
28584afc90SJason Wang  * @i: required value
29584afc90SJason Wang  *
30584afc90SJason Wang  * Atomically sets the value of @v to @i.
31584afc90SJason Wang  */
atomic_set(atomic_t * v,int i)32584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
33584afc90SJason Wang {
34584afc90SJason Wang 	v->counter = i;
35584afc90SJason Wang }
36584afc90SJason Wang 
37584afc90SJason Wang /**
38584afc90SJason Wang  * atomic_inc - increment atomic variable
39584afc90SJason Wang  * @v: pointer of type atomic_t
40584afc90SJason Wang  *
41584afc90SJason Wang  * Atomically increments @v by 1.
42584afc90SJason Wang  */
atomic_inc(atomic_t * v)43584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
44584afc90SJason Wang {
45584afc90SJason Wang 	asm volatile("lock incl %0"
46584afc90SJason Wang 		     : "+m" (v->counter));
47584afc90SJason Wang }
48584afc90SJason Wang 
49584afc90SJason Wang /**
50584afc90SJason Wang  * atomic_dec - decrement atomic variable
51584afc90SJason Wang  * @v: pointer of type atomic_t
52584afc90SJason Wang  *
53584afc90SJason Wang  * Atomically decrements @v by 1.
54584afc90SJason Wang  */
atomic_dec(atomic_t * v)55584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
56584afc90SJason Wang {
57584afc90SJason Wang 	asm volatile("lock decl %0"
58584afc90SJason Wang 		     : "+m" (v->counter));
59584afc90SJason Wang }
60584afc90SJason Wang 
61584afc90SJason Wang typedef struct {
62584afc90SJason Wang 	u64 __attribute__((aligned(8))) counter;
63584afc90SJason Wang } atomic64_t;
64584afc90SJason Wang 
65584afc90SJason Wang #define ATOMIC64_INIT(val)	{ (val) }
66584afc90SJason Wang 
67584afc90SJason Wang /**
68584afc90SJason Wang  * atomic64_read - read atomic64 variable
69584afc90SJason Wang  * @ptr:      pointer to type atomic64_t
70584afc90SJason Wang  *
71584afc90SJason Wang  * Atomically reads the value of @ptr and returns it.
72584afc90SJason Wang  */
atomic64_read(atomic64_t * ptr)73584afc90SJason Wang static inline u64 atomic64_read(atomic64_t *ptr)
74584afc90SJason Wang {
75584afc90SJason Wang 	u64 res;
76584afc90SJason Wang 
77584afc90SJason Wang 	/*
78584afc90SJason Wang 	 * Note, we inline this atomic64_t primitive because
79584afc90SJason Wang 	 * it only clobbers EAX/EDX and leaves the others
80584afc90SJason Wang 	 * untouched. We also (somewhat subtly) rely on the
81584afc90SJason Wang 	 * fact that cmpxchg8b returns the current 64-bit value
82584afc90SJason Wang 	 * of the memory location we are touching:
83584afc90SJason Wang 	 */
84584afc90SJason Wang 	asm volatile("mov %%ebx, %%eax\n\t"
85584afc90SJason Wang                      "mov %%ecx, %%edx\n\t"
86584afc90SJason Wang                      "lock cmpxchg8b %1\n"
87584afc90SJason Wang                      : "=&A" (res)
88584afc90SJason Wang                      : "m" (*ptr)
89584afc90SJason Wang                      );
90584afc90SJason Wang 	return res;
91584afc90SJason Wang }
92584afc90SJason Wang 
93584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
94584afc90SJason Wang 
95584afc90SJason Wang #elif defined(__x86_64__)
96584afc90SJason Wang 
97584afc90SJason Wang /**
98584afc90SJason Wang  * atomic_read - read atomic variable
99584afc90SJason Wang  * @v: pointer of type atomic_t
100584afc90SJason Wang  *
101584afc90SJason Wang  * Atomically reads the value of @v.
102584afc90SJason Wang  */
atomic_read(const atomic_t * v)103584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
104584afc90SJason Wang {
105584afc90SJason Wang 	return v->counter;
106584afc90SJason Wang }
107584afc90SJason Wang 
108584afc90SJason Wang /**
109584afc90SJason Wang  * atomic_set - set atomic variable
110584afc90SJason Wang  * @v: pointer of type atomic_t
111584afc90SJason Wang  * @i: required value
112584afc90SJason Wang  *
113584afc90SJason Wang  * Atomically sets the value of @v to @i.
114584afc90SJason Wang  */
atomic_set(atomic_t * v,int i)115584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
116584afc90SJason Wang {
117584afc90SJason Wang 	v->counter = i;
118584afc90SJason Wang }
119584afc90SJason Wang 
120584afc90SJason Wang /**
121584afc90SJason Wang  * atomic_inc - increment atomic variable
122584afc90SJason Wang  * @v: pointer of type atomic_t
123584afc90SJason Wang  *
124584afc90SJason Wang  * Atomically increments @v by 1.
125584afc90SJason Wang  */
atomic_inc(atomic_t * v)126584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
127584afc90SJason Wang {
128584afc90SJason Wang 	asm volatile("lock incl %0"
129584afc90SJason Wang 		     : "=m" (v->counter)
130584afc90SJason Wang 		     : "m" (v->counter));
131584afc90SJason Wang }
132584afc90SJason Wang 
133584afc90SJason Wang /**
134584afc90SJason Wang  * atomic_dec - decrement atomic variable
135584afc90SJason Wang  * @v: pointer of type atomic_t
136584afc90SJason Wang  *
137584afc90SJason Wang  * Atomically decrements @v by 1.
138584afc90SJason Wang  */
atomic_dec(atomic_t * v)139584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
140584afc90SJason Wang {
141584afc90SJason Wang 	asm volatile("lock decl %0"
142584afc90SJason Wang 		     : "=m" (v->counter)
143584afc90SJason Wang 		     : "m" (v->counter));
144584afc90SJason Wang }
145584afc90SJason Wang 
146584afc90SJason Wang typedef struct {
147584afc90SJason Wang 	long long counter;
148584afc90SJason Wang } atomic64_t;
149584afc90SJason Wang 
150584afc90SJason Wang #define ATOMIC64_INIT(i)	{ (i) }
151584afc90SJason Wang 
152584afc90SJason Wang /**
153584afc90SJason Wang  * atomic64_read - read atomic64 variable
154584afc90SJason Wang  * @v: pointer of type atomic64_t
155584afc90SJason Wang  *
156584afc90SJason Wang  * Atomically reads the value of @v.
157584afc90SJason Wang  * Doesn't imply a read memory barrier.
158584afc90SJason Wang  */
atomic64_read(const atomic64_t * v)159584afc90SJason Wang static inline long atomic64_read(const atomic64_t *v)
160584afc90SJason Wang {
161584afc90SJason Wang 	return v->counter;
162584afc90SJason Wang }
163584afc90SJason Wang 
164584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
165584afc90SJason Wang 
166584afc90SJason Wang #endif
167584afc90SJason Wang 
168584afc90SJason Wang #endif
169