xref: /openbmc/qemu/hw/core/ptimer.c (revision dc5bd18f)
1 /*
2  * General purpose implementation of a simple periodic countdown timer.
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  *
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"
15 #include "block/aio.h"
16 #include "sysemu/cpus.h"
17 
18 #define DELTA_ADJUST     1
19 #define DELTA_NO_ADJUST -1
20 
21 struct ptimer_state
22 {
23     uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot.  */
24     uint64_t limit;
25     uint64_t delta;
26     uint32_t period_frac;
27     int64_t period;
28     int64_t last_event;
29     int64_t next_event;
30     uint8_t policy_mask;
31     QEMUBH *bh;
32     QEMUTimer *timer;
33 };
34 
35 /* Use a bottom-half routine to avoid reentrancy issues.  */
36 static void ptimer_trigger(ptimer_state *s)
37 {
38     if (s->bh) {
39         replay_bh_schedule_event(s->bh);
40     }
41 }
42 
43 static void ptimer_reload(ptimer_state *s, int delta_adjust)
44 {
45     uint32_t period_frac = s->period_frac;
46     uint64_t period = s->period;
47     uint64_t delta = s->delta;
48 
49     if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
50         ptimer_trigger(s);
51     }
52 
53     if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
54         delta = s->delta = s->limit;
55     }
56 
57     if (s->period == 0) {
58         if (!qtest_enabled()) {
59             fprintf(stderr, "Timer with period zero, disabling\n");
60         }
61         timer_del(s->timer);
62         s->enabled = 0;
63         return;
64     }
65 
66     if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
67         if (delta_adjust != DELTA_NO_ADJUST) {
68             delta += delta_adjust;
69         }
70     }
71 
72     if (delta == 0 && (s->policy_mask & PTIMER_POLICY_CONTINUOUS_TRIGGER)) {
73         if (s->enabled == 1 && s->limit == 0) {
74             delta = 1;
75         }
76     }
77 
78     if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
79         if (delta_adjust != DELTA_NO_ADJUST) {
80             delta = 1;
81         }
82     }
83 
84     if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
85         if (s->enabled == 1 && s->limit != 0) {
86             delta = 1;
87         }
88     }
89 
90     if (delta == 0) {
91         if (!qtest_enabled()) {
92             fprintf(stderr, "Timer with delta zero, disabling\n");
93         }
94         timer_del(s->timer);
95         s->enabled = 0;
96         return;
97     }
98 
99     /*
100      * Artificially limit timeout rate to something
101      * achievable under QEMU.  Otherwise, QEMU spends all
102      * its time generating timer interrupts, and there
103      * is no forward progress.
104      * About ten microseconds is the fastest that really works
105      * on the current generation of host machines.
106      */
107 
108     if (s->enabled == 1 && (delta * period < 10000) && !use_icount) {
109         period = 10000 / delta;
110         period_frac = 0;
111     }
112 
113     s->last_event = s->next_event;
114     s->next_event = s->last_event + delta * period;
115     if (period_frac) {
116         s->next_event += ((int64_t)period_frac * delta) >> 32;
117     }
118     timer_mod(s->timer, s->next_event);
119 }
120 
121 static void ptimer_tick(void *opaque)
122 {
123     ptimer_state *s = (ptimer_state *)opaque;
124     bool trigger = true;
125 
126     if (s->enabled == 2) {
127         s->delta = 0;
128         s->enabled = 0;
129     } else {
130         int delta_adjust = DELTA_ADJUST;
131 
132         if (s->delta == 0 || s->limit == 0) {
133             /* If a "continuous trigger" policy is not used and limit == 0,
134                we should error out. delta == 0 means that this tick is
135                caused by a "no immediate reload" policy, so it shouldn't
136                be adjusted.  */
137             delta_adjust = DELTA_NO_ADJUST;
138         }
139 
140         if (!(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
141             /* Avoid re-trigger on deferred reload if "no immediate trigger"
142                policy isn't used.  */
143             trigger = (delta_adjust == DELTA_ADJUST);
144         }
145 
146         s->delta = s->limit;
147 
148         ptimer_reload(s, delta_adjust);
149     }
150 
151     if (trigger) {
152         ptimer_trigger(s);
153     }
154 }
155 
156 uint64_t ptimer_get_count(ptimer_state *s)
157 {
158     uint64_t counter;
159 
160     if (s->enabled && s->delta != 0) {
161         int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
162         int64_t next = s->next_event;
163         int64_t last = s->last_event;
164         bool expired = (now - next >= 0);
165         bool oneshot = (s->enabled == 2);
166 
167         /* Figure out the current counter value.  */
168         if (expired) {
169             /* Prevent timer underflowing if it should already have
170                triggered.  */
171             counter = 0;
172         } else {
173             uint64_t rem;
174             uint64_t div;
175             int clz1, clz2;
176             int shift;
177             uint32_t period_frac = s->period_frac;
178             uint64_t period = s->period;
179 
180             if (!oneshot && (s->delta * period < 10000) && !use_icount) {
181                 period = 10000 / s->delta;
182                 period_frac = 0;
183             }
184 
185             /* We need to divide time by period, where time is stored in
186                rem (64-bit integer) and period is stored in period/period_frac
187                (64.32 fixed point).
188 
189                Doing full precision division is hard, so scale values and
190                do a 64-bit division.  The result should be rounded down,
191                so that the rounding error never causes the timer to go
192                backwards.
193             */
194 
195             rem = next - now;
196             div = period;
197 
198             clz1 = clz64(rem);
199             clz2 = clz64(div);
200             shift = clz1 < clz2 ? clz1 : clz2;
201 
202             rem <<= shift;
203             div <<= shift;
204             if (shift >= 32) {
205                 div |= ((uint64_t)period_frac << (shift - 32));
206             } else {
207                 if (shift != 0)
208                     div |= (period_frac >> (32 - shift));
209                 /* Look at remaining bits of period_frac and round div up if
210                    necessary.  */
211                 if ((uint32_t)(period_frac << shift))
212                     div += 1;
213             }
214             counter = rem / div;
215 
216             if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
217                 /* Before wrapping around, timer should stay with counter = 0
218                    for a one period.  */
219                 if (!oneshot && s->delta == s->limit) {
220                     if (now == last) {
221                         /* Counter == delta here, check whether it was
222                            adjusted and if it was, then right now it is
223                            that "one period".  */
224                         if (counter == s->limit + DELTA_ADJUST) {
225                             return 0;
226                         }
227                     } else if (counter == s->limit) {
228                         /* Since the counter is rounded down and now != last,
229                            the counter == limit means that delta was adjusted
230                            by +1 and right now it is that adjusted period.  */
231                         return 0;
232                     }
233                 }
234             }
235         }
236 
237         if (s->policy_mask & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN) {
238             /* If now == last then delta == limit, i.e. the counter already
239                represents the correct value. It would be rounded down a 1ns
240                later.  */
241             if (now != last) {
242                 counter += 1;
243             }
244         }
245     } else {
246         counter = s->delta;
247     }
248     return counter;
249 }
250 
251 void ptimer_set_count(ptimer_state *s, uint64_t count)
252 {
253     s->delta = count;
254     if (s->enabled) {
255         s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
256         ptimer_reload(s, 0);
257     }
258 }
259 
260 void ptimer_run(ptimer_state *s, int oneshot)
261 {
262     bool was_disabled = !s->enabled;
263 
264     if (was_disabled && s->period == 0) {
265         if (!qtest_enabled()) {
266             fprintf(stderr, "Timer with period zero, disabling\n");
267         }
268         return;
269     }
270     s->enabled = oneshot ? 2 : 1;
271     if (was_disabled) {
272         s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
273         ptimer_reload(s, 0);
274     }
275 }
276 
277 /* Pause a timer.  Note that this may cause it to "lose" time, even if it
278    is immediately restarted.  */
279 void ptimer_stop(ptimer_state *s)
280 {
281     if (!s->enabled)
282         return;
283 
284     s->delta = ptimer_get_count(s);
285     timer_del(s->timer);
286     s->enabled = 0;
287 }
288 
289 /* Set counter increment interval in nanoseconds.  */
290 void ptimer_set_period(ptimer_state *s, int64_t period)
291 {
292     s->delta = ptimer_get_count(s);
293     s->period = period;
294     s->period_frac = 0;
295     if (s->enabled) {
296         s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
297         ptimer_reload(s, 0);
298     }
299 }
300 
301 /* Set counter frequency in Hz.  */
302 void ptimer_set_freq(ptimer_state *s, uint32_t freq)
303 {
304     s->delta = ptimer_get_count(s);
305     s->period = 1000000000ll / freq;
306     s->period_frac = (1000000000ll << 32) / freq;
307     if (s->enabled) {
308         s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
309         ptimer_reload(s, 0);
310     }
311 }
312 
313 /* Set the initial countdown value.  If reload is nonzero then also set
314    count = limit.  */
315 void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
316 {
317     s->limit = limit;
318     if (reload)
319         s->delta = limit;
320     if (s->enabled && reload) {
321         s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
322         ptimer_reload(s, 0);
323     }
324 }
325 
326 uint64_t ptimer_get_limit(ptimer_state *s)
327 {
328     return s->limit;
329 }
330 
331 const VMStateDescription vmstate_ptimer = {
332     .name = "ptimer",
333     .version_id = 1,
334     .minimum_version_id = 1,
335     .fields = (VMStateField[]) {
336         VMSTATE_UINT8(enabled, ptimer_state),
337         VMSTATE_UINT64(limit, ptimer_state),
338         VMSTATE_UINT64(delta, ptimer_state),
339         VMSTATE_UINT32(period_frac, ptimer_state),
340         VMSTATE_INT64(period, ptimer_state),
341         VMSTATE_INT64(last_event, ptimer_state),
342         VMSTATE_INT64(next_event, ptimer_state),
343         VMSTATE_TIMER_PTR(timer, ptimer_state),
344         VMSTATE_END_OF_LIST()
345     }
346 };
347 
348 ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
349 {
350     ptimer_state *s;
351 
352     s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
353     s->bh = bh;
354     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
355     s->policy_mask = policy_mask;
356     return s;
357 }
358 
359 void ptimer_free(ptimer_state *s)
360 {
361     qemu_bh_delete(s->bh);
362     timer_free(s->timer);
363     g_free(s);
364 }
365