cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qemu-timer.c (18728B)


      1/*
      2 * QEMU System Emulator
      3 *
      4 * Copyright (c) 2003-2008 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/main-loop.h"
     27#include "qemu/timer.h"
     28#include "qemu/lockable.h"
     29#include "sysemu/cpu-timers.h"
     30#include "sysemu/replay.h"
     31#include "sysemu/cpus.h"
     32
     33#ifdef CONFIG_POSIX
     34#include <pthread.h>
     35#endif
     36
     37#ifdef CONFIG_PPOLL
     38#include <poll.h>
     39#endif
     40
     41#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
     42#include <sys/prctl.h>
     43#endif
     44
     45/***********************************************************/
     46/* timers */
     47
     48typedef struct QEMUClock {
     49    /* We rely on BQL to protect the timerlists */
     50    QLIST_HEAD(, QEMUTimerList) timerlists;
     51
     52    QEMUClockType type;
     53    bool enabled;
     54} QEMUClock;
     55
     56QEMUTimerListGroup main_loop_tlg;
     57static QEMUClock qemu_clocks[QEMU_CLOCK_MAX];
     58
     59/* A QEMUTimerList is a list of timers attached to a clock. More
     60 * than one QEMUTimerList can be attached to each clock, for instance
     61 * used by different AioContexts / threads. Each clock also has
     62 * a list of the QEMUTimerLists associated with it, in order that
     63 * reenabling the clock can call all the notifiers.
     64 */
     65
     66struct QEMUTimerList {
     67    QEMUClock *clock;
     68    QemuMutex active_timers_lock;
     69    QEMUTimer *active_timers;
     70    QLIST_ENTRY(QEMUTimerList) list;
     71    QEMUTimerListNotifyCB *notify_cb;
     72    void *notify_opaque;
     73
     74    /* lightweight method to mark the end of timerlist's running */
     75    QemuEvent timers_done_ev;
     76};
     77
     78/**
     79 * qemu_clock_ptr:
     80 * @type: type of clock
     81 *
     82 * Translate a clock type into a pointer to QEMUClock object.
     83 *
     84 * Returns: a pointer to the QEMUClock object
     85 */
     86static inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
     87{
     88    return &qemu_clocks[type];
     89}
     90
     91static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
     92{
     93    return timer_head && (timer_head->expire_time <= current_time);
     94}
     95
     96QEMUTimerList *timerlist_new(QEMUClockType type,
     97                             QEMUTimerListNotifyCB *cb,
     98                             void *opaque)
     99{
    100    QEMUTimerList *timer_list;
    101    QEMUClock *clock = qemu_clock_ptr(type);
    102
    103    timer_list = g_malloc0(sizeof(QEMUTimerList));
    104    qemu_event_init(&timer_list->timers_done_ev, true);
    105    timer_list->clock = clock;
    106    timer_list->notify_cb = cb;
    107    timer_list->notify_opaque = opaque;
    108    qemu_mutex_init(&timer_list->active_timers_lock);
    109    QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
    110    return timer_list;
    111}
    112
    113void timerlist_free(QEMUTimerList *timer_list)
    114{
    115    assert(!timerlist_has_timers(timer_list));
    116    if (timer_list->clock) {
    117        QLIST_REMOVE(timer_list, list);
    118    }
    119    qemu_mutex_destroy(&timer_list->active_timers_lock);
    120    g_free(timer_list);
    121}
    122
    123static void qemu_clock_init(QEMUClockType type, QEMUTimerListNotifyCB *notify_cb)
    124{
    125    QEMUClock *clock = qemu_clock_ptr(type);
    126
    127    /* Assert that the clock of type TYPE has not been initialized yet. */
    128    assert(main_loop_tlg.tl[type] == NULL);
    129
    130    clock->type = type;
    131    clock->enabled = (type == QEMU_CLOCK_VIRTUAL ? false : true);
    132    QLIST_INIT(&clock->timerlists);
    133    main_loop_tlg.tl[type] = timerlist_new(type, notify_cb, NULL);
    134}
    135
    136bool qemu_clock_use_for_deadline(QEMUClockType type)
    137{
    138    return !(icount_enabled() && (type == QEMU_CLOCK_VIRTUAL));
    139}
    140
    141void qemu_clock_notify(QEMUClockType type)
    142{
    143    QEMUTimerList *timer_list;
    144    QEMUClock *clock = qemu_clock_ptr(type);
    145    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
    146        timerlist_notify(timer_list);
    147    }
    148}
    149
    150/* Disabling the clock will wait for related timerlists to stop
    151 * executing qemu_run_timers.  Thus, this functions should not
    152 * be used from the callback of a timer that is based on @clock.
    153 * Doing so would cause a deadlock.
    154 *
    155 * Caller should hold BQL.
    156 */
    157void qemu_clock_enable(QEMUClockType type, bool enabled)
    158{
    159    QEMUClock *clock = qemu_clock_ptr(type);
    160    QEMUTimerList *tl;
    161    bool old = clock->enabled;
    162    clock->enabled = enabled;
    163    if (enabled && !old) {
    164        qemu_clock_notify(type);
    165    } else if (!enabled && old) {
    166        QLIST_FOREACH(tl, &clock->timerlists, list) {
    167            qemu_event_wait(&tl->timers_done_ev);
    168        }
    169    }
    170}
    171
    172bool timerlist_has_timers(QEMUTimerList *timer_list)
    173{
    174    return !!qatomic_read(&timer_list->active_timers);
    175}
    176
    177bool qemu_clock_has_timers(QEMUClockType type)
    178{
    179    return timerlist_has_timers(
    180        main_loop_tlg.tl[type]);
    181}
    182
    183bool timerlist_expired(QEMUTimerList *timer_list)
    184{
    185    int64_t expire_time;
    186
    187    if (!qatomic_read(&timer_list->active_timers)) {
    188        return false;
    189    }
    190
    191    WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
    192        if (!timer_list->active_timers) {
    193            return false;
    194        }
    195        expire_time = timer_list->active_timers->expire_time;
    196    }
    197
    198    return expire_time <= qemu_clock_get_ns(timer_list->clock->type);
    199}
    200
    201bool qemu_clock_expired(QEMUClockType type)
    202{
    203    return timerlist_expired(
    204        main_loop_tlg.tl[type]);
    205}
    206
    207/*
    208 * As above, but return -1 for no deadline, and do not cap to 2^32
    209 * as we know the result is always positive.
    210 */
    211
    212int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
    213{
    214    int64_t delta;
    215    int64_t expire_time;
    216
    217    if (!qatomic_read(&timer_list->active_timers)) {
    218        return -1;
    219    }
    220
    221    if (!timer_list->clock->enabled) {
    222        return -1;
    223    }
    224
    225    /* The active timers list may be modified before the caller uses our return
    226     * value but ->notify_cb() is called when the deadline changes.  Therefore
    227     * the caller should notice the change and there is no race condition.
    228     */
    229    WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
    230        if (!timer_list->active_timers) {
    231            return -1;
    232        }
    233        expire_time = timer_list->active_timers->expire_time;
    234    }
    235
    236    delta = expire_time - qemu_clock_get_ns(timer_list->clock->type);
    237
    238    if (delta <= 0) {
    239        return 0;
    240    }
    241
    242    return delta;
    243}
    244
    245/* Calculate the soonest deadline across all timerlists attached
    246 * to the clock. This is used for the icount timeout so we
    247 * ignore whether or not the clock should be used in deadline
    248 * calculations.
    249 */
    250int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
    251{
    252    int64_t deadline = -1;
    253    int64_t delta;
    254    int64_t expire_time;
    255    QEMUTimer *ts;
    256    QEMUTimerList *timer_list;
    257    QEMUClock *clock = qemu_clock_ptr(type);
    258
    259    if (!clock->enabled) {
    260        return -1;
    261    }
    262
    263    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
    264        qemu_mutex_lock(&timer_list->active_timers_lock);
    265        ts = timer_list->active_timers;
    266        /* Skip all external timers */
    267        while (ts && (ts->attributes & ~attr_mask)) {
    268            ts = ts->next;
    269        }
    270        if (!ts) {
    271            qemu_mutex_unlock(&timer_list->active_timers_lock);
    272            continue;
    273        }
    274        expire_time = ts->expire_time;
    275        qemu_mutex_unlock(&timer_list->active_timers_lock);
    276
    277        delta = expire_time - qemu_clock_get_ns(type);
    278        if (delta <= 0) {
    279            delta = 0;
    280        }
    281        deadline = qemu_soonest_timeout(deadline, delta);
    282    }
    283    return deadline;
    284}
    285
    286QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list)
    287{
    288    return timer_list->clock->type;
    289}
    290
    291QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
    292{
    293    return main_loop_tlg.tl[type];
    294}
    295
    296void timerlist_notify(QEMUTimerList *timer_list)
    297{
    298    if (timer_list->notify_cb) {
    299        timer_list->notify_cb(timer_list->notify_opaque, timer_list->clock->type);
    300    } else {
    301        qemu_notify_event();
    302    }
    303}
    304
    305/* Transition function to convert a nanosecond timeout to ms
    306 * This is used where a system does not support ppoll
    307 */
    308int qemu_timeout_ns_to_ms(int64_t ns)
    309{
    310    int64_t ms;
    311    if (ns < 0) {
    312        return -1;
    313    }
    314
    315    if (!ns) {
    316        return 0;
    317    }
    318
    319    /* Always round up, because it's better to wait too long than to wait too
    320     * little and effectively busy-wait
    321     */
    322    ms = DIV_ROUND_UP(ns, SCALE_MS);
    323
    324    /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
    325    return MIN(ms, INT32_MAX);
    326}
    327
    328
    329/* qemu implementation of g_poll which uses a nanosecond timeout but is
    330 * otherwise identical to g_poll
    331 */
    332int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
    333{
    334#ifdef CONFIG_PPOLL
    335    if (timeout < 0) {
    336        return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
    337    } else {
    338        struct timespec ts;
    339        int64_t tvsec = timeout / 1000000000LL;
    340        /* Avoid possibly overflowing and specifying a negative number of
    341         * seconds, which would turn a very long timeout into a busy-wait.
    342         */
    343        if (tvsec > (int64_t)INT32_MAX) {
    344            tvsec = INT32_MAX;
    345        }
    346        ts.tv_sec = tvsec;
    347        ts.tv_nsec = timeout % 1000000000LL;
    348        return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
    349    }
    350#else
    351    return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
    352#endif
    353}
    354
    355
    356void timer_init_full(QEMUTimer *ts,
    357                     QEMUTimerListGroup *timer_list_group, QEMUClockType type,
    358                     int scale, int attributes,
    359                     QEMUTimerCB *cb, void *opaque)
    360{
    361    if (!timer_list_group) {
    362        timer_list_group = &main_loop_tlg;
    363    }
    364    ts->timer_list = timer_list_group->tl[type];
    365    ts->cb = cb;
    366    ts->opaque = opaque;
    367    ts->scale = scale;
    368    ts->attributes = attributes;
    369    ts->expire_time = -1;
    370}
    371
    372void timer_deinit(QEMUTimer *ts)
    373{
    374    assert(ts->expire_time == -1);
    375    ts->timer_list = NULL;
    376}
    377
    378static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
    379{
    380    QEMUTimer **pt, *t;
    381
    382    ts->expire_time = -1;
    383    pt = &timer_list->active_timers;
    384    for(;;) {
    385        t = *pt;
    386        if (!t)
    387            break;
    388        if (t == ts) {
    389            qatomic_set(pt, t->next);
    390            break;
    391        }
    392        pt = &t->next;
    393    }
    394}
    395
    396static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
    397                                QEMUTimer *ts, int64_t expire_time)
    398{
    399    QEMUTimer **pt, *t;
    400
    401    /* add the timer in the sorted list */
    402    pt = &timer_list->active_timers;
    403    for (;;) {
    404        t = *pt;
    405        if (!timer_expired_ns(t, expire_time)) {
    406            break;
    407        }
    408        pt = &t->next;
    409    }
    410    ts->expire_time = MAX(expire_time, 0);
    411    ts->next = *pt;
    412    qatomic_set(pt, ts);
    413
    414    return pt == &timer_list->active_timers;
    415}
    416
    417static void timerlist_rearm(QEMUTimerList *timer_list)
    418{
    419    /* Interrupt execution to force deadline recalculation.  */
    420    if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
    421        icount_start_warp_timer();
    422    }
    423    timerlist_notify(timer_list);
    424}
    425
    426/* stop a timer, but do not dealloc it */
    427void timer_del(QEMUTimer *ts)
    428{
    429    QEMUTimerList *timer_list = ts->timer_list;
    430
    431    if (timer_list) {
    432        qemu_mutex_lock(&timer_list->active_timers_lock);
    433        timer_del_locked(timer_list, ts);
    434        qemu_mutex_unlock(&timer_list->active_timers_lock);
    435    }
    436}
    437
    438/* modify the current timer so that it will be fired when current_time
    439   >= expire_time. The corresponding callback will be called. */
    440void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
    441{
    442    QEMUTimerList *timer_list = ts->timer_list;
    443    bool rearm;
    444
    445    qemu_mutex_lock(&timer_list->active_timers_lock);
    446    timer_del_locked(timer_list, ts);
    447    rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
    448    qemu_mutex_unlock(&timer_list->active_timers_lock);
    449
    450    if (rearm) {
    451        timerlist_rearm(timer_list);
    452    }
    453}
    454
    455/* modify the current timer so that it will be fired when current_time
    456   >= expire_time or the current deadline, whichever comes earlier.
    457   The corresponding callback will be called. */
    458void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time)
    459{
    460    QEMUTimerList *timer_list = ts->timer_list;
    461    bool rearm;
    462
    463    WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
    464        if (ts->expire_time == -1 || ts->expire_time > expire_time) {
    465            if (ts->expire_time != -1) {
    466                timer_del_locked(timer_list, ts);
    467            }
    468            rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
    469        } else {
    470            rearm = false;
    471        }
    472    }
    473    if (rearm) {
    474        timerlist_rearm(timer_list);
    475    }
    476}
    477
    478void timer_mod(QEMUTimer *ts, int64_t expire_time)
    479{
    480    timer_mod_ns(ts, expire_time * ts->scale);
    481}
    482
    483void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
    484{
    485    timer_mod_anticipate_ns(ts, expire_time * ts->scale);
    486}
    487
    488bool timer_pending(QEMUTimer *ts)
    489{
    490    return ts->expire_time >= 0;
    491}
    492
    493bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
    494{
    495    return timer_expired_ns(timer_head, current_time * timer_head->scale);
    496}
    497
    498bool timerlist_run_timers(QEMUTimerList *timer_list)
    499{
    500    QEMUTimer *ts;
    501    int64_t current_time;
    502    bool progress = false;
    503    QEMUTimerCB *cb;
    504    void *opaque;
    505
    506    if (!qatomic_read(&timer_list->active_timers)) {
    507        return false;
    508    }
    509
    510    qemu_event_reset(&timer_list->timers_done_ev);
    511    if (!timer_list->clock->enabled) {
    512        goto out;
    513    }
    514
    515    switch (timer_list->clock->type) {
    516    case QEMU_CLOCK_REALTIME:
    517        break;
    518    default:
    519    case QEMU_CLOCK_VIRTUAL:
    520        break;
    521    case QEMU_CLOCK_HOST:
    522        if (!replay_checkpoint(CHECKPOINT_CLOCK_HOST)) {
    523            goto out;
    524        }
    525        break;
    526    case QEMU_CLOCK_VIRTUAL_RT:
    527        if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL_RT)) {
    528            goto out;
    529        }
    530        break;
    531    }
    532
    533    /*
    534     * Extract expired timers from active timers list and process them.
    535     *
    536     * In rr mode we need "filtered" checkpointing for virtual clock.  The
    537     * checkpoint must be recorded/replayed before processing any non-EXTERNAL timer,
    538     * and that must only be done once since the clock value stays the same. Because
    539     * non-EXTERNAL timers may appear in the timers list while it being processed,
    540     * the checkpoint can be issued at a time until no timers are left and we are
    541     * done".
    542     */
    543    current_time = qemu_clock_get_ns(timer_list->clock->type);
    544    qemu_mutex_lock(&timer_list->active_timers_lock);
    545    while ((ts = timer_list->active_timers)) {
    546        if (!timer_expired_ns(ts, current_time)) {
    547            /* No expired timers left.  The checkpoint can be skipped
    548             * if no timers fired or they were all external.
    549             */
    550            break;
    551        }
    552        /* Checkpoint for virtual clock is redundant in cases where
    553         * it's being triggered with only non-EXTERNAL timers, because
    554         * these timers don't change guest state directly.
    555         */
    556        if (replay_mode != REPLAY_MODE_NONE
    557            && timer_list->clock->type == QEMU_CLOCK_VIRTUAL
    558            && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)
    559            && !replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) {
    560            qemu_mutex_unlock(&timer_list->active_timers_lock);
    561            goto out;
    562        }
    563
    564        /* remove timer from the list before calling the callback */
    565        timer_list->active_timers = ts->next;
    566        ts->next = NULL;
    567        ts->expire_time = -1;
    568        cb = ts->cb;
    569        opaque = ts->opaque;
    570
    571        /* run the callback (the timer list can be modified) */
    572        qemu_mutex_unlock(&timer_list->active_timers_lock);
    573        cb(opaque);
    574        qemu_mutex_lock(&timer_list->active_timers_lock);
    575
    576        progress = true;
    577    }
    578    qemu_mutex_unlock(&timer_list->active_timers_lock);
    579
    580out:
    581    qemu_event_set(&timer_list->timers_done_ev);
    582    return progress;
    583}
    584
    585bool qemu_clock_run_timers(QEMUClockType type)
    586{
    587    return timerlist_run_timers(main_loop_tlg.tl[type]);
    588}
    589
    590void timerlistgroup_init(QEMUTimerListGroup *tlg,
    591                         QEMUTimerListNotifyCB *cb, void *opaque)
    592{
    593    QEMUClockType type;
    594    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    595        tlg->tl[type] = timerlist_new(type, cb, opaque);
    596    }
    597}
    598
    599void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
    600{
    601    QEMUClockType type;
    602    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    603        timerlist_free(tlg->tl[type]);
    604    }
    605}
    606
    607bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
    608{
    609    QEMUClockType type;
    610    bool progress = false;
    611    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    612        progress |= timerlist_run_timers(tlg->tl[type]);
    613    }
    614    return progress;
    615}
    616
    617int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
    618{
    619    int64_t deadline = -1;
    620    QEMUClockType type;
    621    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    622        if (qemu_clock_use_for_deadline(type)) {
    623            deadline = qemu_soonest_timeout(deadline,
    624                                            timerlist_deadline_ns(tlg->tl[type]));
    625        }
    626    }
    627    return deadline;
    628}
    629
    630int64_t qemu_clock_get_ns(QEMUClockType type)
    631{
    632    switch (type) {
    633    case QEMU_CLOCK_REALTIME:
    634        return get_clock();
    635    default:
    636    case QEMU_CLOCK_VIRTUAL:
    637        return cpus_get_virtual_clock();
    638    case QEMU_CLOCK_HOST:
    639        return REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime());
    640    case QEMU_CLOCK_VIRTUAL_RT:
    641        return REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT, cpu_get_clock());
    642    }
    643}
    644
    645void init_clocks(QEMUTimerListNotifyCB *notify_cb)
    646{
    647    QEMUClockType type;
    648    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    649        qemu_clock_init(type, notify_cb);
    650    }
    651
    652#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
    653    prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
    654#endif
    655}
    656
    657uint64_t timer_expire_time_ns(QEMUTimer *ts)
    658{
    659    return timer_pending(ts) ? ts->expire_time : -1;
    660}
    661
    662bool qemu_clock_run_all_timers(void)
    663{
    664    bool progress = false;
    665    QEMUClockType type;
    666
    667    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
    668        if (qemu_clock_use_for_deadline(type)) {
    669            progress |= qemu_clock_run_timers(type);
    670        }
    671    }
    672
    673    return progress;
    674}