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

nrf51_timer.c (11583B)


      1/*
      2 * nRF51 System-on-Chip Timer peripheral
      3 *
      4 * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
      5 * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
      6 *
      7 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
      8 * Copyright (c) 2019 Red Hat, Inc.
      9 *
     10 * This code is licensed under the GPL version 2 or later.  See
     11 * the COPYING file in the top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "qemu/log.h"
     16#include "qemu/module.h"
     17#include "hw/arm/nrf51.h"
     18#include "hw/irq.h"
     19#include "hw/timer/nrf51_timer.h"
     20#include "hw/qdev-properties.h"
     21#include "migration/vmstate.h"
     22#include "trace.h"
     23
     24#define TIMER_CLK_FREQ 16000000UL
     25
     26static uint32_t const bitwidths[] = {16, 8, 24, 32};
     27
     28static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns)
     29{
     30    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
     31
     32    return muldiv64(ns, freq, NANOSECONDS_PER_SECOND);
     33}
     34
     35static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks)
     36{
     37    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
     38
     39    return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq);
     40}
     41
     42/* Returns number of ticks since last call */
     43static uint32_t update_counter(NRF51TimerState *s, int64_t now)
     44{
     45    uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
     46
     47    s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
     48    s->update_counter_ns = now;
     49    return ticks;
     50}
     51
     52/* Assumes s->counter is up-to-date */
     53static void rearm_timer(NRF51TimerState *s, int64_t now)
     54{
     55    int64_t min_ns = INT64_MAX;
     56    size_t i;
     57
     58    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
     59        int64_t delta_ns;
     60
     61        if (s->events_compare[i]) {
     62            continue; /* already expired, ignore it for now */
     63        }
     64
     65        if (s->cc[i] <= s->counter) {
     66            delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) -
     67                                      s->counter + s->cc[i]);
     68        } else {
     69            delta_ns = ticks_to_ns(s, s->cc[i] - s->counter);
     70        }
     71
     72        if (delta_ns < min_ns) {
     73            min_ns = delta_ns;
     74        }
     75    }
     76
     77    if (min_ns != INT64_MAX) {
     78        timer_mod_ns(&s->timer, now + min_ns);
     79    }
     80}
     81
     82static void update_irq(NRF51TimerState *s)
     83{
     84    bool flag = false;
     85    size_t i;
     86
     87    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
     88        flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1);
     89    }
     90    qemu_set_irq(s->irq, flag);
     91}
     92
     93static void timer_expire(void *opaque)
     94{
     95    NRF51TimerState *s = NRF51_TIMER(opaque);
     96    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     97    uint32_t cc_remaining[NRF51_TIMER_REG_COUNT];
     98    bool should_stop = false;
     99    uint32_t ticks;
    100    size_t i;
    101
    102    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
    103        if (s->cc[i] > s->counter) {
    104            cc_remaining[i] = s->cc[i] - s->counter;
    105        } else {
    106            cc_remaining[i] = BIT(bitwidths[s->bitmode]) -
    107                              s->counter + s->cc[i];
    108        }
    109    }
    110
    111    ticks = update_counter(s, now);
    112
    113    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
    114        if (cc_remaining[i] <= ticks) {
    115            s->events_compare[i] = 1;
    116
    117            if (s->shorts & BIT(i)) {
    118                s->timer_start_ns = now;
    119                s->update_counter_ns = s->timer_start_ns;
    120                s->counter = 0;
    121            }
    122
    123            should_stop |= s->shorts & BIT(i + 8);
    124        }
    125    }
    126
    127    update_irq(s);
    128
    129    if (should_stop) {
    130        s->running = false;
    131        timer_del(&s->timer);
    132    } else {
    133        rearm_timer(s, now);
    134    }
    135}
    136
    137static void counter_compare(NRF51TimerState *s)
    138{
    139    uint32_t counter = s->counter;
    140    size_t i;
    141
    142    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
    143        if (counter == s->cc[i]) {
    144            s->events_compare[i] = 1;
    145
    146            if (s->shorts & BIT(i)) {
    147                s->counter = 0;
    148            }
    149        }
    150    }
    151}
    152
    153static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size)
    154{
    155    NRF51TimerState *s = NRF51_TIMER(opaque);
    156    uint64_t r = 0;
    157
    158    switch (offset) {
    159    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
    160        r = s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4];
    161        break;
    162    case NRF51_TIMER_REG_SHORTS:
    163        r = s->shorts;
    164        break;
    165    case NRF51_TIMER_REG_INTENSET:
    166        r = s->inten;
    167        break;
    168    case NRF51_TIMER_REG_INTENCLR:
    169        r = s->inten;
    170        break;
    171    case NRF51_TIMER_REG_MODE:
    172        r = s->mode;
    173        break;
    174    case NRF51_TIMER_REG_BITMODE:
    175        r = s->bitmode;
    176        break;
    177    case NRF51_TIMER_REG_PRESCALER:
    178        r = s->prescaler;
    179        break;
    180    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
    181        r = s->cc[(offset - NRF51_TIMER_REG_CC0) / 4];
    182        break;
    183    default:
    184        qemu_log_mask(LOG_GUEST_ERROR,
    185                "%s: bad read offset 0x%" HWADDR_PRIx "\n",
    186                      __func__, offset);
    187    }
    188
    189    trace_nrf51_timer_read(s->id, offset, r, size);
    190
    191    return r;
    192}
    193
    194static void nrf51_timer_write(void *opaque, hwaddr offset,
    195                       uint64_t value, unsigned int size)
    196{
    197    NRF51TimerState *s = NRF51_TIMER(opaque);
    198    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    199    size_t idx;
    200
    201    trace_nrf51_timer_write(s->id, offset, value, size);
    202
    203    switch (offset) {
    204    case NRF51_TIMER_TASK_START:
    205        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_TIMER) {
    206            s->running = true;
    207            s->timer_start_ns = now - ticks_to_ns(s, s->counter);
    208            s->update_counter_ns = s->timer_start_ns;
    209            rearm_timer(s, now);
    210        }
    211        break;
    212    case NRF51_TIMER_TASK_STOP:
    213    case NRF51_TIMER_TASK_SHUTDOWN:
    214        if (value == NRF51_TRIGGER_TASK) {
    215            s->running = false;
    216            timer_del(&s->timer);
    217        }
    218        break;
    219    case NRF51_TIMER_TASK_COUNT:
    220        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) {
    221            s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]);
    222            counter_compare(s);
    223        }
    224        break;
    225    case NRF51_TIMER_TASK_CLEAR:
    226        if (value == NRF51_TRIGGER_TASK) {
    227            s->timer_start_ns = now;
    228            s->update_counter_ns = s->timer_start_ns;
    229            s->counter = 0;
    230            if (s->running) {
    231                rearm_timer(s, now);
    232            }
    233        }
    234        break;
    235    case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3:
    236        if (value == NRF51_TRIGGER_TASK) {
    237            if (s->running) {
    238                timer_expire(s); /* update counter and all state */
    239            }
    240
    241            idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4;
    242            s->cc[idx] = s->counter;
    243            trace_nrf51_timer_set_count(s->id, idx, s->counter);
    244        }
    245        break;
    246    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
    247        if (value == NRF51_EVENT_CLEAR) {
    248            s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0;
    249
    250            if (s->running) {
    251                timer_expire(s); /* update counter and all state */
    252            }
    253        }
    254        break;
    255    case NRF51_TIMER_REG_SHORTS:
    256        s->shorts = value & NRF51_TIMER_REG_SHORTS_MASK;
    257        break;
    258    case NRF51_TIMER_REG_INTENSET:
    259        s->inten |= value & NRF51_TIMER_REG_INTEN_MASK;
    260        break;
    261    case NRF51_TIMER_REG_INTENCLR:
    262        s->inten &= ~(value & NRF51_TIMER_REG_INTEN_MASK);
    263        break;
    264    case NRF51_TIMER_REG_MODE:
    265        s->mode = value;
    266        break;
    267    case NRF51_TIMER_REG_BITMODE:
    268        if (s->mode == NRF51_TIMER_TIMER && s->running) {
    269            qemu_log_mask(LOG_GUEST_ERROR,
    270                    "%s: erroneous change of BITMODE while timer is running\n",
    271                    __func__);
    272        }
    273        s->bitmode = value & NRF51_TIMER_REG_BITMODE_MASK;
    274        break;
    275    case NRF51_TIMER_REG_PRESCALER:
    276        if (s->mode == NRF51_TIMER_TIMER && s->running) {
    277            qemu_log_mask(LOG_GUEST_ERROR,
    278                "%s: erroneous change of PRESCALER while timer is running\n",
    279                __func__);
    280        }
    281        s->prescaler = value & NRF51_TIMER_REG_PRESCALER_MASK;
    282        break;
    283    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
    284        if (s->running) {
    285            timer_expire(s); /* update counter */
    286        }
    287
    288        idx = (offset - NRF51_TIMER_REG_CC0) / 4;
    289        s->cc[idx] = value % BIT(bitwidths[s->bitmode]);
    290
    291        if (s->running) {
    292            rearm_timer(s, now);
    293        }
    294        break;
    295    default:
    296        qemu_log_mask(LOG_GUEST_ERROR,
    297                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
    298                      __func__, offset);
    299    }
    300
    301    update_irq(s);
    302}
    303
    304static const MemoryRegionOps rng_ops = {
    305    .read =  nrf51_timer_read,
    306    .write = nrf51_timer_write,
    307    .endianness = DEVICE_LITTLE_ENDIAN,
    308    .impl.min_access_size = 4,
    309    .impl.max_access_size = 4,
    310};
    311
    312static void nrf51_timer_init(Object *obj)
    313{
    314    NRF51TimerState *s = NRF51_TIMER(obj);
    315    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    316
    317    memory_region_init_io(&s->iomem, obj, &rng_ops, s,
    318                          TYPE_NRF51_TIMER, NRF51_PERIPHERAL_SIZE);
    319    sysbus_init_mmio(sbd, &s->iomem);
    320    sysbus_init_irq(sbd, &s->irq);
    321
    322    timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s);
    323}
    324
    325static void nrf51_timer_reset(DeviceState *dev)
    326{
    327    NRF51TimerState *s = NRF51_TIMER(dev);
    328
    329    timer_del(&s->timer);
    330    s->timer_start_ns = 0x00;
    331    s->update_counter_ns = 0x00;
    332    s->counter = 0x00;
    333    s->running = false;
    334
    335    memset(s->events_compare, 0x00, sizeof(s->events_compare));
    336    memset(s->cc, 0x00, sizeof(s->cc));
    337
    338    s->shorts = 0x00;
    339    s->inten = 0x00;
    340    s->mode = 0x00;
    341    s->bitmode = 0x00;
    342    s->prescaler = 0x00;
    343}
    344
    345static int nrf51_timer_post_load(void *opaque, int version_id)
    346{
    347    NRF51TimerState *s = NRF51_TIMER(opaque);
    348
    349    if (s->running && s->mode == NRF51_TIMER_TIMER) {
    350        timer_expire(s);
    351    }
    352    return 0;
    353}
    354
    355static const VMStateDescription vmstate_nrf51_timer = {
    356    .name = TYPE_NRF51_TIMER,
    357    .version_id = 1,
    358    .post_load = nrf51_timer_post_load,
    359    .fields = (VMStateField[]) {
    360        VMSTATE_TIMER(timer, NRF51TimerState),
    361        VMSTATE_INT64(timer_start_ns, NRF51TimerState),
    362        VMSTATE_INT64(update_counter_ns, NRF51TimerState),
    363        VMSTATE_UINT32(counter, NRF51TimerState),
    364        VMSTATE_BOOL(running, NRF51TimerState),
    365        VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState,
    366                            NRF51_TIMER_REG_COUNT),
    367        VMSTATE_UINT32_ARRAY(cc, NRF51TimerState, NRF51_TIMER_REG_COUNT),
    368        VMSTATE_UINT32(shorts, NRF51TimerState),
    369        VMSTATE_UINT32(inten, NRF51TimerState),
    370        VMSTATE_UINT32(mode, NRF51TimerState),
    371        VMSTATE_UINT32(bitmode, NRF51TimerState),
    372        VMSTATE_UINT32(prescaler, NRF51TimerState),
    373        VMSTATE_END_OF_LIST()
    374    }
    375};
    376
    377static Property nrf51_timer_properties[] = {
    378    DEFINE_PROP_UINT8("id", NRF51TimerState, id, 0),
    379    DEFINE_PROP_END_OF_LIST(),
    380};
    381
    382static void nrf51_timer_class_init(ObjectClass *klass, void *data)
    383{
    384    DeviceClass *dc = DEVICE_CLASS(klass);
    385
    386    dc->reset = nrf51_timer_reset;
    387    dc->vmsd = &vmstate_nrf51_timer;
    388    device_class_set_props(dc, nrf51_timer_properties);
    389}
    390
    391static const TypeInfo nrf51_timer_info = {
    392    .name = TYPE_NRF51_TIMER,
    393    .parent = TYPE_SYS_BUS_DEVICE,
    394    .instance_size = sizeof(NRF51TimerState),
    395    .instance_init = nrf51_timer_init,
    396    .class_init = nrf51_timer_class_init
    397};
    398
    399static void nrf51_timer_register_types(void)
    400{
    401    type_register_static(&nrf51_timer_info);
    402}
    403
    404type_init(nrf51_timer_register_types)