Merge remote-tracking branch 'remotes/kraxel/tags/pull-ui-20161028-1' into staging
[qemu/ar7.git] / hw / core / ptimer.c
blob3af82afe781014e3b8a780929c09753fc27e8c7a
1 /*
2 * General purpose implementation of a simple periodic countdown timer.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licensed under the GNU LGPL.
7 */
8 #include "qemu/osdep.h"
9 #include "hw/hw.h"
10 #include "qemu/timer.h"
11 #include "hw/ptimer.h"
12 #include "qemu/host-utils.h"
13 #include "sysemu/replay.h"
14 #include "sysemu/qtest.h"
16 #define DELTA_ADJUST 1
17 #define DELTA_NO_ADJUST -1
19 struct ptimer_state
21 uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
22 uint64_t limit;
23 uint64_t delta;
24 uint32_t period_frac;
25 int64_t period;
26 int64_t last_event;
27 int64_t next_event;
28 uint8_t policy_mask;
29 QEMUBH *bh;
30 QEMUTimer *timer;
33 /* Use a bottom-half routine to avoid reentrancy issues. */
34 static void ptimer_trigger(ptimer_state *s)
36 if (s->bh) {
37 replay_bh_schedule_event(s->bh);
41 static void ptimer_reload(ptimer_state *s, int delta_adjust)
43 uint32_t period_frac = s->period_frac;
44 uint64_t period = s->period;
45 uint64_t delta = s->delta;
47 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
48 ptimer_trigger(s);
51 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
52 delta = s->delta = s->limit;
55 if (s->period == 0) {
56 if (!qtest_enabled()) {
57 fprintf(stderr, "Timer with period zero, disabling\n");
59 timer_del(s->timer);
60 s->enabled = 0;
61 return;
64 if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
65 if (delta_adjust != DELTA_NO_ADJUST) {
66 delta += delta_adjust;
70 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_CONTINUOUS_TRIGGER)) {
71 if (s->enabled == 1 && s->limit == 0) {
72 delta = 1;
76 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
77 if (delta_adjust != DELTA_NO_ADJUST) {
78 delta = 1;
82 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
83 if (s->enabled == 1 && s->limit != 0) {
84 delta = 1;
88 if (delta == 0) {
89 if (!qtest_enabled()) {
90 fprintf(stderr, "Timer with delta zero, disabling\n");
92 timer_del(s->timer);
93 s->enabled = 0;
94 return;
98 * Artificially limit timeout rate to something
99 * achievable under QEMU. Otherwise, QEMU spends all
100 * its time generating timer interrupts, and there
101 * is no forward progress.
102 * About ten microseconds is the fastest that really works
103 * on the current generation of host machines.
106 if (s->enabled == 1 && (delta * period < 10000) && !use_icount) {
107 period = 10000 / delta;
108 period_frac = 0;
111 s->last_event = s->next_event;
112 s->next_event = s->last_event + delta * period;
113 if (period_frac) {
114 s->next_event += ((int64_t)period_frac * delta) >> 32;
116 timer_mod(s->timer, s->next_event);
119 static void ptimer_tick(void *opaque)
121 ptimer_state *s = (ptimer_state *)opaque;
122 bool trigger = true;
124 if (s->enabled == 2) {
125 s->delta = 0;
126 s->enabled = 0;
127 } else {
128 int delta_adjust = DELTA_ADJUST;
130 if (s->delta == 0 || s->limit == 0) {
131 /* If a "continuous trigger" policy is not used and limit == 0,
132 we should error out. delta == 0 means that this tick is
133 caused by a "no immediate reload" policy, so it shouldn't
134 be adjusted. */
135 delta_adjust = DELTA_NO_ADJUST;
138 if (!(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
139 /* Avoid re-trigger on deferred reload if "no immediate trigger"
140 policy isn't used. */
141 trigger = (delta_adjust == DELTA_ADJUST);
144 s->delta = s->limit;
146 ptimer_reload(s, delta_adjust);
149 if (trigger) {
150 ptimer_trigger(s);
154 uint64_t ptimer_get_count(ptimer_state *s)
156 uint64_t counter;
158 if (s->enabled && s->delta != 0) {
159 int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
160 int64_t next = s->next_event;
161 int64_t last = s->last_event;
162 bool expired = (now - next >= 0);
163 bool oneshot = (s->enabled == 2);
165 /* Figure out the current counter value. */
166 if (expired) {
167 /* Prevent timer underflowing if it should already have
168 triggered. */
169 counter = 0;
170 } else {
171 uint64_t rem;
172 uint64_t div;
173 int clz1, clz2;
174 int shift;
175 uint32_t period_frac = s->period_frac;
176 uint64_t period = s->period;
178 if (!oneshot && (s->delta * period < 10000) && !use_icount) {
179 period = 10000 / s->delta;
180 period_frac = 0;
183 /* We need to divide time by period, where time is stored in
184 rem (64-bit integer) and period is stored in period/period_frac
185 (64.32 fixed point).
187 Doing full precision division is hard, so scale values and
188 do a 64-bit division. The result should be rounded down,
189 so that the rounding error never causes the timer to go
190 backwards.
193 rem = next - now;
194 div = period;
196 clz1 = clz64(rem);
197 clz2 = clz64(div);
198 shift = clz1 < clz2 ? clz1 : clz2;
200 rem <<= shift;
201 div <<= shift;
202 if (shift >= 32) {
203 div |= ((uint64_t)period_frac << (shift - 32));
204 } else {
205 if (shift != 0)
206 div |= (period_frac >> (32 - shift));
207 /* Look at remaining bits of period_frac and round div up if
208 necessary. */
209 if ((uint32_t)(period_frac << shift))
210 div += 1;
212 counter = rem / div;
214 if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
215 /* Before wrapping around, timer should stay with counter = 0
216 for a one period. */
217 if (!oneshot && s->delta == s->limit) {
218 if (now == last) {
219 /* Counter == delta here, check whether it was
220 adjusted and if it was, then right now it is
221 that "one period". */
222 if (counter == s->limit + DELTA_ADJUST) {
223 return 0;
225 } else if (counter == s->limit) {
226 /* Since the counter is rounded down and now != last,
227 the counter == limit means that delta was adjusted
228 by +1 and right now it is that adjusted period. */
229 return 0;
235 if (s->policy_mask & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN) {
236 /* If now == last then delta == limit, i.e. the counter already
237 represents the correct value. It would be rounded down a 1ns
238 later. */
239 if (now != last) {
240 counter += 1;
243 } else {
244 counter = s->delta;
246 return counter;
249 void ptimer_set_count(ptimer_state *s, uint64_t count)
251 s->delta = count;
252 if (s->enabled) {
253 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
254 ptimer_reload(s, 0);
258 void ptimer_run(ptimer_state *s, int oneshot)
260 bool was_disabled = !s->enabled;
262 if (was_disabled && s->period == 0) {
263 if (!qtest_enabled()) {
264 fprintf(stderr, "Timer with period zero, disabling\n");
266 return;
268 s->enabled = oneshot ? 2 : 1;
269 if (was_disabled) {
270 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
271 ptimer_reload(s, 0);
275 /* Pause a timer. Note that this may cause it to "lose" time, even if it
276 is immediately restarted. */
277 void ptimer_stop(ptimer_state *s)
279 if (!s->enabled)
280 return;
282 s->delta = ptimer_get_count(s);
283 timer_del(s->timer);
284 s->enabled = 0;
287 /* Set counter increment interval in nanoseconds. */
288 void ptimer_set_period(ptimer_state *s, int64_t period)
290 s->delta = ptimer_get_count(s);
291 s->period = period;
292 s->period_frac = 0;
293 if (s->enabled) {
294 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
295 ptimer_reload(s, 0);
299 /* Set counter frequency in Hz. */
300 void ptimer_set_freq(ptimer_state *s, uint32_t freq)
302 s->delta = ptimer_get_count(s);
303 s->period = 1000000000ll / freq;
304 s->period_frac = (1000000000ll << 32) / freq;
305 if (s->enabled) {
306 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307 ptimer_reload(s, 0);
311 /* Set the initial countdown value. If reload is nonzero then also set
312 count = limit. */
313 void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
315 s->limit = limit;
316 if (reload)
317 s->delta = limit;
318 if (s->enabled && reload) {
319 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
320 ptimer_reload(s, 0);
324 uint64_t ptimer_get_limit(ptimer_state *s)
326 return s->limit;
329 const VMStateDescription vmstate_ptimer = {
330 .name = "ptimer",
331 .version_id = 1,
332 .minimum_version_id = 1,
333 .fields = (VMStateField[]) {
334 VMSTATE_UINT8(enabled, ptimer_state),
335 VMSTATE_UINT64(limit, ptimer_state),
336 VMSTATE_UINT64(delta, ptimer_state),
337 VMSTATE_UINT32(period_frac, ptimer_state),
338 VMSTATE_INT64(period, ptimer_state),
339 VMSTATE_INT64(last_event, ptimer_state),
340 VMSTATE_INT64(next_event, ptimer_state),
341 VMSTATE_TIMER_PTR(timer, ptimer_state),
342 VMSTATE_END_OF_LIST()
346 ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
348 ptimer_state *s;
350 s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
351 s->bh = bh;
352 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
353 s->policy_mask = policy_mask;
354 return s;