1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2016 Red Hat, Inc.
4 * Author: Michael S. Tsirkin <mst@redhat.com>
6 * Common macros and functions for ring benchmarking.
18 #if defined(__x86_64__) || defined(__i386__)
19 #include "x86intrin.h"
21 static inline void wait_cycles(unsigned long long cycles
)
26 while (__rdtsc() - t
< cycles
) {}
29 #define VMEXIT_CYCLES 500
30 #define VMENTRY_CYCLES 500
32 #elif defined(__s390x__)
33 static inline void wait_cycles(unsigned long long cycles
)
35 asm volatile("0: brctg %0,0b" : : "d" (cycles
));
39 #define VMEXIT_CYCLES 200
40 #define VMENTRY_CYCLES 200
43 static inline void wait_cycles(unsigned long long cycles
)
47 #define VMEXIT_CYCLES 0
48 #define VMENTRY_CYCLES 0
51 static inline void vmexit(void)
56 wait_cycles(VMEXIT_CYCLES
);
58 static inline void vmentry(void)
63 wait_cycles(VMENTRY_CYCLES
);
66 /* implemented by ring */
67 void alloc_ring(void);
69 int add_inbuf(unsigned, void *, void *);
70 void *get_buf(unsigned *, void **);
74 void kick_available();
79 bool use_buf(unsigned *, void **);
82 /* implemented by main */
85 void wait_for_kick(void);
87 void wait_for_call(void);
89 extern unsigned ring_size
;
91 /* Compiler barrier - similar to what Linux uses */
92 #define barrier() asm volatile("" ::: "memory")
94 /* Is there a portable way to do this? */
95 #if defined(__x86_64__) || defined(__i386__)
96 #define cpu_relax() asm ("rep; nop" ::: "memory")
97 #elif defined(__s390x__)
98 #define cpu_relax() barrier()
99 #elif defined(__aarch64__)
100 #define cpu_relax() asm ("yield" ::: "memory")
102 #define cpu_relax() assert(0)
105 extern bool do_relax
;
107 static inline void busy_wait(void)
112 /* prevent compiler from removing busy loops */
116 #if defined(__x86_64__) || defined(__i386__)
117 #define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
118 #elif defined(__aarch64__)
119 #define smp_mb() asm volatile("dmb ish" ::: "memory")
122 * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
123 * with other __ATOMIC_SEQ_CST calls.
125 #define smp_mb() __sync_synchronize()
129 * This abuses the atomic builtins for thread fences, and
130 * adds a compiler barrier.
132 #define smp_release() do { \
134 __atomic_thread_fence(__ATOMIC_RELEASE); \
137 #define smp_acquire() do { \
138 __atomic_thread_fence(__ATOMIC_ACQUIRE); \
142 #if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
143 #define smp_wmb() barrier()
144 #elif defined(__aarch64__)
145 #define smp_wmb() asm volatile("dmb ishst" ::: "memory")
147 #define smp_wmb() smp_release()
150 #ifndef __always_inline
151 #define __always_inline inline __attribute__((always_inline))
154 static __always_inline
155 void __read_once_size(const volatile void *p
, void *res
, int size
)
158 case 1: *(unsigned char *)res
= *(volatile unsigned char *)p
; break;
159 case 2: *(unsigned short *)res
= *(volatile unsigned short *)p
; break;
160 case 4: *(unsigned int *)res
= *(volatile unsigned int *)p
; break;
161 case 8: *(unsigned long long *)res
= *(volatile unsigned long long *)p
; break;
164 __builtin_memcpy((void *)res
, (const void *)p
, size
);
169 static __always_inline
void __write_once_size(volatile void *p
, void *res
, int size
)
172 case 1: *(volatile unsigned char *)p
= *(unsigned char *)res
; break;
173 case 2: *(volatile unsigned short *)p
= *(unsigned short *)res
; break;
174 case 4: *(volatile unsigned int *)p
= *(unsigned int *)res
; break;
175 case 8: *(volatile unsigned long long *)p
= *(unsigned long long *)res
; break;
178 __builtin_memcpy((void *)p
, (const void *)res
, size
);
184 #define READ_ONCE(x) \
186 union { typeof(x) __val; char __c[1]; } __u; \
187 __read_once_size(&(x), __u.__c, sizeof(x)); \
188 smp_mb(); /* Enforce dependency ordering from x */ \
192 #define READ_ONCE(x) \
194 union { typeof(x) __val; char __c[1]; } __u; \
195 __read_once_size(&(x), __u.__c, sizeof(x)); \
200 #define WRITE_ONCE(x, val) \
202 union { typeof(x) __val; char __c[1]; } __u = \
203 { .__val = (typeof(x)) (val) }; \
204 __write_once_size(&(x), __u.__c, sizeof(x)); \