qemu/hw/core/ptimer.c
<<
>>
Prefs
   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
  19struct 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.  */
  34static void ptimer_trigger(ptimer_state *s)
  35{
  36    if (s->bh) {
  37        replay_bh_schedule_event(s->bh);
  38    }
  39}
  40
  41static 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
 119static 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
 154uint64_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
 249void 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
 258void 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.  */
 277void 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.  */
 288void 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.  */
 300void 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.  */
 313void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
 314{
 315    /*
 316     * Artificially limit timeout rate to something
 317     * achievable under QEMU.  Otherwise, QEMU spends all
 318     * its time generating timer interrupts, and there
 319     * is no forward progress.
 320     * About ten microseconds is the fastest that really works
 321     * on the current generation of host machines.
 322     */
 323
 324    if (!use_icount && limit * s->period < 10000 && s->period) {
 325        limit = 10000 / s->period;
 326    }
 327
 328    s->limit = limit;
 329    if (reload)
 330        s->delta = limit;
 331    if (s->enabled && reload) {
 332        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 333        ptimer_reload(s, 0);
 334    }
 335}
 336
 337uint64_t ptimer_get_limit(ptimer_state *s)
 338{
 339    return s->limit;
 340}
 341
 342const VMStateDescription vmstate_ptimer = {
 343    .name = "ptimer",
 344    .version_id = 1,
 345    .minimum_version_id = 1,
 346    .fields = (VMStateField[]) {
 347        VMSTATE_UINT8(enabled, ptimer_state),
 348        VMSTATE_UINT64(limit, ptimer_state),
 349        VMSTATE_UINT64(delta, ptimer_state),
 350        VMSTATE_UINT32(period_frac, ptimer_state),
 351        VMSTATE_INT64(period, ptimer_state),
 352        VMSTATE_INT64(last_event, ptimer_state),
 353        VMSTATE_INT64(next_event, ptimer_state),
 354        VMSTATE_TIMER_PTR(timer, ptimer_state),
 355        VMSTATE_END_OF_LIST()
 356    }
 357};
 358
 359ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
 360{
 361    ptimer_state *s;
 362
 363    s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
 364    s->bh = bh;
 365    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
 366    s->policy_mask = policy_mask;
 367    return s;
 368}
 369