Merge tag 'spi-nor/for-4.11-v2' of git://github.com/spi-nor/linux
[linux-2.6-block.git] / tools / virtio / ringtest / main.h
CommitLineData
481eaec3
MT
1/*
2 * Copyright (C) 2016 Red Hat, Inc.
3 * Author: Michael S. Tsirkin <mst@redhat.com>
4 * This work is licensed under the terms of the GNU GPL, version 2.
5 *
6 * Common macros and functions for ring benchmarking.
7 */
8#ifndef MAIN_H
9#define MAIN_H
10
11#include <stdbool.h>
12
13extern bool do_exit;
14
15#if defined(__x86_64__) || defined(__i386__)
16#include "x86intrin.h"
17
18static inline void wait_cycles(unsigned long long cycles)
19{
20 unsigned long long t;
21
22 t = __rdtsc();
23 while (__rdtsc() - t < cycles) {}
24}
25
26#define VMEXIT_CYCLES 500
27#define VMENTRY_CYCLES 500
28
47a4c49a
HP
29#elif defined(__s390x__)
30static inline void wait_cycles(unsigned long long cycles)
31{
32 asm volatile("0: brctg %0,0b" : : "d" (cycles));
33}
34
35/* tweak me */
36#define VMEXIT_CYCLES 200
37#define VMENTRY_CYCLES 200
38
481eaec3
MT
39#else
40static inline void wait_cycles(unsigned long long cycles)
41{
42 _Exit(5);
43}
44#define VMEXIT_CYCLES 0
45#define VMENTRY_CYCLES 0
46#endif
47
48static inline void vmexit(void)
49{
50 if (!do_exit)
51 return;
52
53 wait_cycles(VMEXIT_CYCLES);
54}
55static inline void vmentry(void)
56{
57 if (!do_exit)
58 return;
59
60 wait_cycles(VMENTRY_CYCLES);
61}
62
63/* implemented by ring */
64void alloc_ring(void);
65/* guest side */
66int add_inbuf(unsigned, void *, void *);
67void *get_buf(unsigned *, void **);
68void disable_call();
d3c3589b 69bool used_empty();
481eaec3
MT
70bool enable_call();
71void kick_available();
481eaec3
MT
72/* host side */
73void disable_kick();
d3c3589b 74bool avail_empty();
481eaec3
MT
75bool enable_kick();
76bool use_buf(unsigned *, void **);
77void call_used();
481eaec3
MT
78
79/* implemented by main */
80extern bool do_sleep;
81void kick(void);
82void wait_for_kick(void);
83void call(void);
84void wait_for_call(void);
85
86extern unsigned ring_size;
87
88/* Compiler barrier - similar to what Linux uses */
89#define barrier() asm volatile("" ::: "memory")
90
91/* Is there a portable way to do this? */
92#if defined(__x86_64__) || defined(__i386__)
93#define cpu_relax() asm ("rep; nop" ::: "memory")
47a4c49a
HP
94#elif defined(__s390x__)
95#define cpu_relax() barrier()
481eaec3
MT
96#else
97#define cpu_relax() assert(0)
98#endif
99
100extern bool do_relax;
101
102static inline void busy_wait(void)
103{
104 if (do_relax)
105 cpu_relax();
106 else
107 /* prevent compiler from removing busy loops */
108 barrier();
109}
110
111/*
112 * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
113 * with other __ATOMIC_SEQ_CST calls.
114 */
115#define smp_mb() __sync_synchronize()
116
117/*
118 * This abuses the atomic builtins for thread fences, and
119 * adds a compiler barrier.
120 */
121#define smp_release() do { \
122 barrier(); \
123 __atomic_thread_fence(__ATOMIC_RELEASE); \
124} while (0)
125
126#define smp_acquire() do { \
127 __atomic_thread_fence(__ATOMIC_ACQUIRE); \
128 barrier(); \
129} while (0)
130
131#endif