]> git.proxmox.com Git - mirror_qemu.git/blame - hw/core/ptimer.c
migrate: Introduce a 'dc->vmsd' check to avoid segfault for --only-migratable
[mirror_qemu.git] / hw / core / ptimer.c
CommitLineData
5fafdf24 1/*
423f0742
PB
2 * General purpose implementation of a simple periodic countdown timer.
3 *
4 * Copyright (c) 2007 CodeSourcery.
5 *
8e31bf38 6 * This code is licensed under the GNU LGPL.
423f0742 7 */
18c86e2b 8#include "qemu/osdep.h"
83c9f4ca 9#include "hw/hw.h"
1de7afc9 10#include "qemu/timer.h"
83c9f4ca 11#include "hw/ptimer.h"
1de7afc9 12#include "qemu/host-utils.h"
8a354bd9 13#include "sysemu/replay.h"
2a8b5870 14#include "sysemu/qtest.h"
423f0742 15
22471b8a
DO
16#define DELTA_ADJUST 1
17#define DELTA_NO_ADJUST -1
2b5c0322 18
423f0742
PB
19struct ptimer_state
20{
852f771e 21 uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
8d05ea8a
BS
22 uint64_t limit;
23 uint64_t delta;
423f0742
PB
24 uint32_t period_frac;
25 int64_t period;
26 int64_t last_event;
27 int64_t next_event;
e7ea81c3 28 uint8_t policy_mask;
423f0742
PB
29 QEMUBH *bh;
30 QEMUTimer *timer;
31};
32
33/* Use a bottom-half routine to avoid reentrancy issues. */
34static void ptimer_trigger(ptimer_state *s)
35{
36 if (s->bh) {
8a354bd9 37 replay_bh_schedule_event(s->bh);
423f0742
PB
38 }
39}
40
2b5c0322 41static void ptimer_reload(ptimer_state *s, int delta_adjust)
423f0742 42{
e91171e3
DO
43 uint32_t period_frac = s->period_frac;
44 uint64_t period = s->period;
2b5c0322 45 uint64_t delta = s->delta;
e91171e3 46
22471b8a 47 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
423f0742 48 ptimer_trigger(s);
22471b8a
DO
49 }
50
3f6e6a13 51 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
2b5c0322 52 delta = s->delta = s->limit;
423f0742 53 }
ef0a9984
DO
54
55 if (s->period == 0) {
2a8b5870
DO
56 if (!qtest_enabled()) {
57 fprintf(stderr, "Timer with period zero, disabling\n");
58 }
780d23e5 59 timer_del(s->timer);
423f0742
PB
60 s->enabled = 0;
61 return;
62 }
63
2b5c0322 64 if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
22471b8a
DO
65 if (delta_adjust != DELTA_NO_ADJUST) {
66 delta += delta_adjust;
67 }
2b5c0322
DO
68 }
69
ef0a9984
DO
70 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_CONTINUOUS_TRIGGER)) {
71 if (s->enabled == 1 && s->limit == 0) {
72 delta = 1;
73 }
74 }
75
22471b8a
DO
76 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
77 if (delta_adjust != DELTA_NO_ADJUST) {
78 delta = 1;
79 }
80 }
81
3f6e6a13
DO
82 if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
83 if (s->enabled == 1 && s->limit != 0) {
84 delta = 1;
85 }
86 }
87
ef0a9984
DO
88 if (delta == 0) {
89 if (!qtest_enabled()) {
90 fprintf(stderr, "Timer with delta zero, disabling\n");
91 }
92 timer_del(s->timer);
93 s->enabled = 0;
94 return;
95 }
96
e91171e3
DO
97 /*
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.
104 */
105
2b5c0322
DO
106 if (s->enabled == 1 && (delta * period < 10000) && !use_icount) {
107 period = 10000 / delta;
e91171e3
DO
108 period_frac = 0;
109 }
110
423f0742 111 s->last_event = s->next_event;
2b5c0322 112 s->next_event = s->last_event + delta * period;
e91171e3 113 if (period_frac) {
2b5c0322 114 s->next_event += ((int64_t)period_frac * delta) >> 32;
423f0742 115 }
bc72ad67 116 timer_mod(s->timer, s->next_event);
423f0742
PB
117}
118
119static void ptimer_tick(void *opaque)
120{
121 ptimer_state *s = (ptimer_state *)opaque;
3f6e6a13
DO
122 bool trigger = true;
123
423f0742 124 if (s->enabled == 2) {
3f6e6a13 125 s->delta = 0;
423f0742
PB
126 s->enabled = 0;
127 } else {
ef0a9984
DO
128 int delta_adjust = DELTA_ADJUST;
129
3f6e6a13 130 if (s->delta == 0 || s->limit == 0) {
ef0a9984 131 /* If a "continuous trigger" policy is not used and limit == 0,
3f6e6a13
DO
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. */
22471b8a 135 delta_adjust = DELTA_NO_ADJUST;
ef0a9984
DO
136 }
137
3f6e6a13
DO
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);
142 }
143
144 s->delta = s->limit;
145
ef0a9984 146 ptimer_reload(s, delta_adjust);
423f0742 147 }
3f6e6a13
DO
148
149 if (trigger) {
150 ptimer_trigger(s);
151 }
423f0742
PB
152}
153
8d05ea8a 154uint64_t ptimer_get_count(ptimer_state *s)
423f0742 155{
8d05ea8a 156 uint64_t counter;
423f0742 157
ef0a9984 158 if (s->enabled && s->delta != 0) {
5a50307b
DO
159 int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
160 int64_t next = s->next_event;
2b5c0322 161 int64_t last = s->last_event;
5a50307b
DO
162 bool expired = (now - next >= 0);
163 bool oneshot = (s->enabled == 2);
164
423f0742 165 /* Figure out the current counter value. */
56215da3 166 if (expired) {
423f0742
PB
167 /* Prevent timer underflowing if it should already have
168 triggered. */
169 counter = 0;
170 } else {
8d05ea8a
BS
171 uint64_t rem;
172 uint64_t div;
d0a981b2
PB
173 int clz1, clz2;
174 int shift;
e91171e3
DO
175 uint32_t period_frac = s->period_frac;
176 uint64_t period = s->period;
177
5a50307b 178 if (!oneshot && (s->delta * period < 10000) && !use_icount) {
e91171e3
DO
179 period = 10000 / s->delta;
180 period_frac = 0;
181 }
d0a981b2
PB
182
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).
2b5c0322 186
d0a981b2
PB
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.
191 */
423f0742 192
56215da3 193 rem = next - now;
e91171e3 194 div = period;
d0a981b2
PB
195
196 clz1 = clz64(rem);
197 clz2 = clz64(div);
198 shift = clz1 < clz2 ? clz1 : clz2;
199
200 rem <<= shift;
201 div <<= shift;
202 if (shift >= 32) {
e91171e3 203 div |= ((uint64_t)period_frac << (shift - 32));
d0a981b2
PB
204 } else {
205 if (shift != 0)
e91171e3 206 div |= (period_frac >> (32 - shift));
d0a981b2
PB
207 /* Look at remaining bits of period_frac and round div up if
208 necessary. */
e91171e3 209 if ((uint32_t)(period_frac << shift))
d0a981b2
PB
210 div += 1;
211 }
423f0742 212 counter = rem / div;
2b5c0322
DO
213
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;
224 }
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;
230 }
231 }
232 }
423f0742 233 }
5580ea45
DO
234
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;
241 }
242 }
423f0742
PB
243 } else {
244 counter = s->delta;
245 }
246 return counter;
247}
248
8d05ea8a 249void ptimer_set_count(ptimer_state *s, uint64_t count)
423f0742
PB
250{
251 s->delta = count;
252 if (s->enabled) {
bc72ad67 253 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2b5c0322 254 ptimer_reload(s, 0);
423f0742
PB
255 }
256}
257
258void ptimer_run(ptimer_state *s, int oneshot)
259{
869e92b5
DO
260 bool was_disabled = !s->enabled;
261
262 if (was_disabled && s->period == 0) {
2a8b5870
DO
263 if (!qtest_enabled()) {
264 fprintf(stderr, "Timer with period zero, disabling\n");
265 }
423f0742
PB
266 return;
267 }
268 s->enabled = oneshot ? 2 : 1;
869e92b5
DO
269 if (was_disabled) {
270 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2b5c0322 271 ptimer_reload(s, 0);
869e92b5 272 }
423f0742
PB
273}
274
8d05ea8a 275/* Pause a timer. Note that this may cause it to "lose" time, even if it
423f0742
PB
276 is immediately restarted. */
277void ptimer_stop(ptimer_state *s)
278{
279 if (!s->enabled)
280 return;
281
282 s->delta = ptimer_get_count(s);
bc72ad67 283 timer_del(s->timer);
423f0742
PB
284 s->enabled = 0;
285}
286
287/* Set counter increment interval in nanoseconds. */
288void ptimer_set_period(ptimer_state *s, int64_t period)
289{
7ef6e3cf 290 s->delta = ptimer_get_count(s);
423f0742
PB
291 s->period = period;
292 s->period_frac = 0;
8d05ea8a 293 if (s->enabled) {
bc72ad67 294 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2b5c0322 295 ptimer_reload(s, 0);
8d05ea8a 296 }
423f0742
PB
297}
298
299/* Set counter frequency in Hz. */
300void ptimer_set_freq(ptimer_state *s, uint32_t freq)
301{
7ef6e3cf 302 s->delta = ptimer_get_count(s);
423f0742
PB
303 s->period = 1000000000ll / freq;
304 s->period_frac = (1000000000ll << 32) / freq;
8d05ea8a 305 if (s->enabled) {
bc72ad67 306 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2b5c0322 307 ptimer_reload(s, 0);
8d05ea8a 308 }
423f0742
PB
309}
310
311/* Set the initial countdown value. If reload is nonzero then also set
312 count = limit. */
8d05ea8a 313void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
423f0742 314{
423f0742
PB
315 s->limit = limit;
316 if (reload)
317 s->delta = limit;
62ea5b0b 318 if (s->enabled && reload) {
bc72ad67 319 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2b5c0322 320 ptimer_reload(s, 0);
8d05ea8a
BS
321 }
322}
323
578c4b2f
DO
324uint64_t ptimer_get_limit(ptimer_state *s)
325{
326 return s->limit;
327}
328
852f771e 329const VMStateDescription vmstate_ptimer = {
55a6e51f 330 .name = "ptimer",
852f771e
JQ
331 .version_id = 1,
332 .minimum_version_id = 1,
35d08458 333 .fields = (VMStateField[]) {
852f771e
JQ
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),
e720677e 341 VMSTATE_TIMER_PTR(timer, ptimer_state),
852f771e
JQ
342 VMSTATE_END_OF_LIST()
343 }
55a6e51f
BS
344};
345
e7ea81c3 346ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
423f0742
PB
347{
348 ptimer_state *s;
349
7267c094 350 s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
423f0742 351 s->bh = bh;
bc72ad67 352 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
e7ea81c3 353 s->policy_mask = policy_mask;
423f0742
PB
354 return s;
355}