1#ifndef QEMU_TIMER_H
2#define QEMU_TIMER_H
3
4#include "qemu-common.h"
5#include "main-loop.h"
6#include "notify.h"
7#include <time.h>
8#include <sys/time.h>
9
10#ifdef _WIN32
11#include <windows.h>
12#endif
13
14
15
16#define SCALE_MS 1000000
17#define SCALE_US 1000
18#define SCALE_NS 1
19
20typedef struct QEMUClock QEMUClock;
21typedef void QEMUTimerCB(void *opaque);
22
23
24
25
26
27extern QEMUClock *rt_clock;
28
29
30
31
32extern QEMUClock *vm_clock;
33
34
35
36
37
38
39extern QEMUClock *host_clock;
40
41int64_t qemu_get_clock_ns(QEMUClock *clock);
42int64_t qemu_clock_has_timers(QEMUClock *clock);
43int64_t qemu_clock_expired(QEMUClock *clock);
44int64_t qemu_clock_deadline(QEMUClock *clock);
45void qemu_clock_enable(QEMUClock *clock, int enabled);
46void qemu_clock_warp(QEMUClock *clock);
47
48void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
49void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
50 Notifier *notifier);
51
52QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
53 QEMUTimerCB *cb, void *opaque);
54void qemu_free_timer(QEMUTimer *ts);
55void qemu_del_timer(QEMUTimer *ts);
56void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
57void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
58int qemu_timer_pending(QEMUTimer *ts);
59int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
60uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
61
62void qemu_run_all_timers(void);
63int qemu_alarm_pending(void);
64void configure_alarms(char const *opt);
65int qemu_calculate_timeout(void);
66void init_clocks(void);
67int init_timer_alarm(void);
68
69int64_t cpu_get_ticks(void);
70void cpu_enable_ticks(void);
71void cpu_disable_ticks(void);
72
73static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
74 void *opaque)
75{
76 return qemu_new_timer(clock, SCALE_NS, cb, opaque);
77}
78
79static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
80 void *opaque)
81{
82 return qemu_new_timer(clock, SCALE_MS, cb, opaque);
83}
84
85static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
86{
87 return qemu_get_clock_ns(clock) / SCALE_MS;
88}
89
90static inline int64_t get_ticks_per_sec(void)
91{
92 return 1000000000LL;
93}
94
95
96static inline int64_t get_clock_realtime(void)
97{
98 struct timeval tv;
99
100 gettimeofday(&tv, NULL);
101 return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
102}
103
104
105
106
107#ifdef _WIN32
108extern int64_t clock_freq;
109
110static inline int64_t get_clock(void)
111{
112 LARGE_INTEGER ti;
113 QueryPerformanceCounter(&ti);
114 return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
115}
116
117#else
118
119extern int use_rt_clock;
120
121static inline int64_t get_clock(void)
122{
123#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
124 || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
125 if (use_rt_clock) {
126 struct timespec ts;
127 clock_gettime(CLOCK_MONOTONIC, &ts);
128 return ts.tv_sec * 1000000000LL + ts.tv_nsec;
129 } else
130#endif
131 {
132
133
134 return get_clock_realtime();
135 }
136}
137#endif
138
139void qemu_get_timer(QEMUFile *f, QEMUTimer *ts);
140void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
141
142
143typedef struct ptimer_state ptimer_state;
144typedef void (*ptimer_cb)(void *opaque);
145
146ptimer_state *ptimer_init(QEMUBH *bh);
147void ptimer_set_period(ptimer_state *s, int64_t period);
148void ptimer_set_freq(ptimer_state *s, uint32_t freq);
149void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload);
150uint64_t ptimer_get_count(ptimer_state *s);
151void ptimer_set_count(ptimer_state *s, uint64_t count);
152void ptimer_run(ptimer_state *s, int oneshot);
153void ptimer_stop(ptimer_state *s);
154
155
156int64_t cpu_get_icount(void);
157int64_t cpu_get_clock(void);
158
159
160
161
162#if defined(_ARCH_PPC)
163
164static inline int64_t cpu_get_real_ticks(void)
165{
166 int64_t retval;
167#ifdef _ARCH_PPC64
168
169
170
171 __asm__ __volatile__ ("mftb %0\n\t"
172 "cmpwi %0,0\n\t"
173 "beq- $-8"
174 : "=r" (retval));
175#else
176
177 unsigned long junk;
178 __asm__ __volatile__ ("mfspr %1,269\n\t"
179 "mfspr %L0,268\n\t"
180 "mfspr %0,269\n\t"
181 "cmpw %0,%1\n\t"
182 "bne $-16"
183 : "=r" (retval), "=r" (junk));
184#endif
185 return retval;
186}
187
188#elif defined(__i386__)
189
190static inline int64_t cpu_get_real_ticks(void)
191{
192 int64_t val;
193 asm volatile ("rdtsc" : "=A" (val));
194 return val;
195}
196
197#elif defined(__x86_64__)
198
199static inline int64_t cpu_get_real_ticks(void)
200{
201 uint32_t low,high;
202 int64_t val;
203 asm volatile("rdtsc" : "=a" (low), "=d" (high));
204 val = high;
205 val <<= 32;
206 val |= low;
207 return val;
208}
209
210#elif defined(__hppa__)
211
212static inline int64_t cpu_get_real_ticks(void)
213{
214 int val;
215 asm volatile ("mfctl %%cr16, %0" : "=r"(val));
216 return val;
217}
218
219#elif defined(__ia64)
220
221static inline int64_t cpu_get_real_ticks(void)
222{
223 int64_t val;
224 asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
225 return val;
226}
227
228#elif defined(__s390__)
229
230static inline int64_t cpu_get_real_ticks(void)
231{
232 int64_t val;
233 asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
234 return val;
235}
236
237#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
238
239static inline int64_t cpu_get_real_ticks (void)
240{
241#if defined(_LP64)
242 uint64_t rval;
243 asm volatile("rd %%tick,%0" : "=r"(rval));
244 return rval;
245#else
246 union {
247 uint64_t i64;
248 struct {
249 uint32_t high;
250 uint32_t low;
251 } i32;
252 } rval;
253 asm volatile("rd %%tick,%1; srlx %1,32,%0"
254 : "=r"(rval.i32.high), "=r"(rval.i32.low));
255 return rval.i64;
256#endif
257}
258
259#elif defined(__mips__) && \
260 ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
261
262
263
264
265
266
267#define MIPS_RDHWR(rd, value) { \
268 __asm__ __volatile__ (".set push\n\t" \
269 ".set mips32r2\n\t" \
270 "rdhwr %0, "rd"\n\t" \
271 ".set pop" \
272 : "=r" (value)); \
273 }
274
275static inline int64_t cpu_get_real_ticks(void)
276{
277
278 uint32_t count;
279 static uint32_t cyc_per_count = 0;
280
281 if (!cyc_per_count) {
282 MIPS_RDHWR("$3", cyc_per_count);
283 }
284
285 MIPS_RDHWR("$2", count);
286 return (int64_t)(count * cyc_per_count);
287}
288
289#elif defined(__alpha__)
290
291static inline int64_t cpu_get_real_ticks(void)
292{
293 uint64_t cc;
294 uint32_t cur, ofs;
295
296 asm volatile("rpcc %0" : "=r"(cc));
297 cur = cc;
298 ofs = cc >> 32;
299 return cur - ofs;
300}
301
302#else
303
304
305
306static inline int64_t cpu_get_real_ticks (void)
307{
308 static int64_t ticks = 0;
309 return ticks++;
310}
311#endif
312
313#ifdef CONFIG_PROFILER
314static inline int64_t profile_getclock(void)
315{
316 return cpu_get_real_ticks();
317}
318
319extern int64_t qemu_time, qemu_time_start;
320extern int64_t tlb_flush_time;
321extern int64_t dev_time;
322#endif
323
324#endif
325