pcie_aer: support configurable AER capa version
[qemu.git] / hw / core / ptimer.c
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
16 #define DELTA_ADJUST 1
17 #define DELTA_NO_ADJUST -1
18
19 struct ptimer_state
20 {
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;
31 };
32
33 /* Use a bottom-half routine to avoid reentrancy issues. */
34 static void ptimer_trigger(ptimer_state *s)
35 {
36 if (s->bh) {
37 replay_bh_schedule_event(s->bh);
38 }
39 }
40
41 static void ptimer_reload(ptimer_state *s, int delta_adjust)
42 {
43 uint32_t period_frac = s->period_frac;
44 uint64_t period = s->period;
45 uint64_t delta = s->delta;
46
47 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
48 ptimer_trigger(s);
49 }
50
51 if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
52 delta = s->delta = s->limit;
53 }
54
55 if (s->period == 0) {
56 if (!qtest_enabled()) {
57 fprintf(stderr, "Timer with period zero, disabling\n");
58 }
59 timer_del(s->timer);
60 s->enabled = 0;
61 return;
62 }
63
64 if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
65 if (delta_adjust != DELTA_NO_ADJUST) {
66 delta += delta_adjust;
67 }
68 }
69
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
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
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
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
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
106 if (s->enabled == 1 && (delta * period < 10000) && !use_icount) {
107 period = 10000 / delta;
108 period_frac = 0;
109 }
110
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;
115 }
116 timer_mod(s->timer, s->next_event);
117 }
118
119 static void ptimer_tick(void *opaque)
120 {
121 ptimer_state *s = (ptimer_state *)opaque;
122 bool trigger = true;
123
124 if (s->enabled == 2) {
125 s->delta = 0;
126 s->enabled = 0;
127 } else {
128 int delta_adjust = DELTA_ADJUST;
129
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;
136 }
137
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
146 ptimer_reload(s, delta_adjust);
147 }
148
149 if (trigger) {
150 ptimer_trigger(s);
151 }
152 }
153
154 uint64_t ptimer_get_count(ptimer_state *s)
155 {
156 uint64_t counter;
157
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);
164
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;
177
178 if (!oneshot && (s->delta * period < 10000) && !use_icount) {
179 period = 10000 / s->delta;
180 period_frac = 0;
181 }
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).
186
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 */
192
193 rem = next - now;
194 div = period;
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) {
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;
211 }
212 counter = rem / div;
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 }
233 }
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 }
243 } else {
244 counter = s->delta;
245 }
246 return counter;
247 }
248
249 void ptimer_set_count(ptimer_state *s, uint64_t count)
250 {
251 s->delta = count;
252 if (s->enabled) {
253 s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
254 ptimer_reload(s, 0);
255 }
256 }
257
258 void ptimer_run(ptimer_state *s, int oneshot)
259 {
260 bool was_disabled = !s->enabled;
261
262 if (was_disabled && s->period == 0) {
263 if (!qtest_enabled()) {
264 fprintf(stderr, "Timer with period zero, disabling\n");
265 }
266 return;
267 }
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);
272 }
273 }
274
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)
278 {
279 if (!s->enabled)
280 return;
281
282 s->delta = ptimer_get_count(s);
283 timer_del(s->timer);
284 s->enabled = 0;
285 }
286
287 /* Set counter increment interval in nanoseconds. */
288 void ptimer_set_period(ptimer_state *s, int64_t period)
289 {
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);
296 }
297 }
298
299 /* Set counter frequency in Hz. */
300 void ptimer_set_freq(ptimer_state *s, uint32_t freq)
301 {
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);
308 }
309 }
310
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)
314 {
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);
321 }
322 }
323
324 uint64_t ptimer_get_limit(ptimer_state *s)
325 {
326 return s->limit;
327 }
328
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()
343 }
344 };
345
346 ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
347 {
348 ptimer_state *s;
349
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;
355 }