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