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

npcm7xx_timer-test.c (17054B)


      1/*
      2 * QTest testcase for the Nuvoton NPCM7xx Timer
      3 *
      4 * Copyright 2020 Google LLC
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms of the GNU General Public License as published by the
      8 * Free Software Foundation; either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful, but WITHOUT
     12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     14 * for more details.
     15 */
     16
     17#include "qemu/osdep.h"
     18#include "qemu/timer.h"
     19#include "libqtest-single.h"
     20
     21#define TIM_REF_HZ      (25000000)
     22
     23/* Bits in TCSRx */
     24#define CEN             BIT(30)
     25#define IE              BIT(29)
     26#define MODE_ONESHOT    (0 << 27)
     27#define MODE_PERIODIC   (1 << 27)
     28#define CRST            BIT(26)
     29#define CACT            BIT(25)
     30#define PRESCALE(x)     (x)
     31
     32/* Registers shared between all timers in a module. */
     33#define TISR    0x18
     34#define WTCR    0x1c
     35# define WTCLK(x)       ((x) << 10)
     36
     37/* Power-on default; used to re-initialize timers before each test. */
     38#define TCSR_DEFAULT    PRESCALE(5)
     39
     40/* Register offsets for a timer within a timer block. */
     41typedef struct Timer {
     42    unsigned int tcsr_offset;
     43    unsigned int ticr_offset;
     44    unsigned int tdr_offset;
     45} Timer;
     46
     47/* A timer block containing 5 timers. */
     48typedef struct TimerBlock {
     49    int irq_base;
     50    uint64_t base_addr;
     51} TimerBlock;
     52
     53/* Testdata for testing a particular timer within a timer block. */
     54typedef struct TestData {
     55    const TimerBlock *tim;
     56    const Timer *timer;
     57} TestData;
     58
     59const TimerBlock timer_block[] = {
     60    {
     61        .irq_base   = 32,
     62        .base_addr  = 0xf0008000,
     63    },
     64    {
     65        .irq_base   = 37,
     66        .base_addr  = 0xf0009000,
     67    },
     68    {
     69        .irq_base   = 42,
     70        .base_addr  = 0xf000a000,
     71    },
     72};
     73
     74const Timer timer[] = {
     75    {
     76        .tcsr_offset    = 0x00,
     77        .ticr_offset    = 0x08,
     78        .tdr_offset     = 0x10,
     79    }, {
     80        .tcsr_offset    = 0x04,
     81        .ticr_offset    = 0x0c,
     82        .tdr_offset     = 0x14,
     83    }, {
     84        .tcsr_offset    = 0x20,
     85        .ticr_offset    = 0x28,
     86        .tdr_offset     = 0x30,
     87    }, {
     88        .tcsr_offset    = 0x24,
     89        .ticr_offset    = 0x2c,
     90        .tdr_offset     = 0x34,
     91    }, {
     92        .tcsr_offset    = 0x40,
     93        .ticr_offset    = 0x48,
     94        .tdr_offset     = 0x50,
     95    },
     96};
     97
     98/* Returns the index of the timer block. */
     99static int tim_index(const TimerBlock *tim)
    100{
    101    ptrdiff_t diff = tim - timer_block;
    102
    103    g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
    104
    105    return diff;
    106}
    107
    108/* Returns the index of a timer within a timer block. */
    109static int timer_index(const Timer *t)
    110{
    111    ptrdiff_t diff = t - timer;
    112
    113    g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
    114
    115    return diff;
    116}
    117
    118/* Returns the irq line for a given timer. */
    119static int tim_timer_irq(const TestData *td)
    120{
    121    return td->tim->irq_base + timer_index(td->timer);
    122}
    123
    124/* Register read/write accessors. */
    125
    126static void tim_write(const TestData *td,
    127                      unsigned int offset, uint32_t value)
    128{
    129    writel(td->tim->base_addr + offset, value);
    130}
    131
    132static uint32_t tim_read(const TestData *td, unsigned int offset)
    133{
    134    return readl(td->tim->base_addr + offset);
    135}
    136
    137static void tim_write_tcsr(const TestData *td, uint32_t value)
    138{
    139    tim_write(td, td->timer->tcsr_offset, value);
    140}
    141
    142static uint32_t tim_read_tcsr(const TestData *td)
    143{
    144    return tim_read(td, td->timer->tcsr_offset);
    145}
    146
    147static void tim_write_ticr(const TestData *td, uint32_t value)
    148{
    149    tim_write(td, td->timer->ticr_offset, value);
    150}
    151
    152static uint32_t tim_read_ticr(const TestData *td)
    153{
    154    return tim_read(td, td->timer->ticr_offset);
    155}
    156
    157static uint32_t tim_read_tdr(const TestData *td)
    158{
    159    return tim_read(td, td->timer->tdr_offset);
    160}
    161
    162/* Returns the number of nanoseconds to count the given number of cycles. */
    163static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
    164{
    165    return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
    166}
    167
    168/* Returns a bitmask corresponding to the timer under test. */
    169static uint32_t tim_timer_bit(const TestData *td)
    170{
    171    return BIT(timer_index(td->timer));
    172}
    173
    174/* Resets all timers to power-on defaults. */
    175static void tim_reset(const TestData *td)
    176{
    177    int i, j;
    178
    179    /* Reset all the timers, in case a previous test left a timer running. */
    180    for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
    181        for (j = 0; j < ARRAY_SIZE(timer); j++) {
    182            writel(timer_block[i].base_addr + timer[j].tcsr_offset,
    183                   CRST | TCSR_DEFAULT);
    184        }
    185        writel(timer_block[i].base_addr + TISR, -1);
    186    }
    187}
    188
    189/* Verifies the reset state of a timer. */
    190static void test_reset(gconstpointer test_data)
    191{
    192    const TestData *td = test_data;
    193
    194    tim_reset(td);
    195
    196    g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
    197    g_assert_cmphex(tim_read_ticr(td), ==, 0);
    198    g_assert_cmphex(tim_read_tdr(td), ==, 0);
    199    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    200    g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
    201}
    202
    203/* Verifies that CRST wins if both CEN and CRST are set. */
    204static void test_reset_overrides_enable(gconstpointer test_data)
    205{
    206    const TestData *td = test_data;
    207
    208    tim_reset(td);
    209
    210    /* CRST should force CEN to 0 */
    211    tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
    212
    213    g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
    214    g_assert_cmphex(tim_read_tdr(td), ==, 0);
    215    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    216}
    217
    218/* Verifies the behavior when CEN is set and then cleared. */
    219static void test_oneshot_enable_then_disable(gconstpointer test_data)
    220{
    221    const TestData *td = test_data;
    222
    223    tim_reset(td);
    224
    225    /* Enable the timer with zero initial count, then disable it again. */
    226    tim_write_tcsr(td, CEN | TCSR_DEFAULT);
    227    tim_write_tcsr(td, TCSR_DEFAULT);
    228
    229    g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
    230    g_assert_cmphex(tim_read_tdr(td), ==, 0);
    231    /* Timer interrupt flag should be set, but interrupts are not enabled. */
    232    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    233    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    234}
    235
    236/* Verifies that a one-shot timer fires when expected with prescaler 5. */
    237static void test_oneshot_ps5(gconstpointer test_data)
    238{
    239    const TestData *td = test_data;
    240    unsigned int count = 256;
    241    unsigned int ps = 5;
    242
    243    tim_reset(td);
    244
    245    tim_write_ticr(td, count);
    246    tim_write_tcsr(td, CEN | PRESCALE(ps));
    247    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    248    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    249
    250    clock_step(tim_calculate_step(count, ps) - 1);
    251
    252    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    253    g_assert_cmpuint(tim_read_tdr(td), <, count);
    254    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    255
    256    clock_step(1);
    257
    258    g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
    259    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    260    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    261    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    262
    263    /* Clear the interrupt flag. */
    264    tim_write(td, TISR, tim_timer_bit(td));
    265    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    266    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    267
    268    /* Verify that this isn't a periodic timer. */
    269    clock_step(2 * tim_calculate_step(count, ps));
    270    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    271    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    272}
    273
    274/* Verifies that a one-shot timer fires when expected with prescaler 0. */
    275static void test_oneshot_ps0(gconstpointer test_data)
    276{
    277    const TestData *td = test_data;
    278    unsigned int count = 1;
    279    unsigned int ps = 0;
    280
    281    tim_reset(td);
    282
    283    tim_write_ticr(td, count);
    284    tim_write_tcsr(td, CEN | PRESCALE(ps));
    285    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    286    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    287
    288    clock_step(tim_calculate_step(count, ps) - 1);
    289
    290    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    291    g_assert_cmpuint(tim_read_tdr(td), <, count);
    292    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    293
    294    clock_step(1);
    295
    296    g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
    297    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    298    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    299    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    300}
    301
    302/* Verifies that a one-shot timer fires when expected with highest prescaler. */
    303static void test_oneshot_ps255(gconstpointer test_data)
    304{
    305    const TestData *td = test_data;
    306    unsigned int count = (1U << 24) - 1;
    307    unsigned int ps = 255;
    308
    309    tim_reset(td);
    310
    311    tim_write_ticr(td, count);
    312    tim_write_tcsr(td, CEN | PRESCALE(ps));
    313    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    314    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    315
    316    clock_step(tim_calculate_step(count, ps) - 1);
    317
    318    g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
    319    g_assert_cmpuint(tim_read_tdr(td), <, count);
    320    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    321
    322    clock_step(1);
    323
    324    g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
    325    g_assert_cmpuint(tim_read_tdr(td), ==, count);
    326    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    327    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    328}
    329
    330/* Verifies that a oneshot timer fires an interrupt when expected. */
    331static void test_oneshot_interrupt(gconstpointer test_data)
    332{
    333    const TestData *td = test_data;
    334    unsigned int count = 256;
    335    unsigned int ps = 7;
    336
    337    tim_reset(td);
    338
    339    tim_write_ticr(td, count);
    340    tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
    341
    342    clock_step_next();
    343
    344    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    345    g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    346}
    347
    348/*
    349 * Verifies that the timer can be paused and later resumed, and it still fires
    350 * at the right moment.
    351 */
    352static void test_pause_resume(gconstpointer test_data)
    353{
    354    const TestData *td = test_data;
    355    unsigned int count = 256;
    356    unsigned int ps = 1;
    357
    358    tim_reset(td);
    359
    360    tim_write_ticr(td, count);
    361    tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
    362
    363    /* Pause the timer halfway to expiration. */
    364    clock_step(tim_calculate_step(count / 2, ps));
    365    tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
    366    g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
    367
    368    /* Counter should not advance during the following step. */
    369    clock_step(2 * tim_calculate_step(count, ps));
    370    g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
    371    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    372    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    373
    374    /* Resume the timer and run _almost_ to expiration. */
    375    tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
    376    clock_step(tim_calculate_step(count / 2, ps) - 1);
    377    g_assert_cmpuint(tim_read_tdr(td), <, count);
    378    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    379    g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    380
    381    /* Now, run the rest of the way and verify that the interrupt fires. */
    382    clock_step(1);
    383    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    384    g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    385}
    386
    387/* Verifies that the prescaler can be changed while the timer is runnin. */
    388static void test_prescaler_change(gconstpointer test_data)
    389{
    390    const TestData *td = test_data;
    391    unsigned int count = 256;
    392    unsigned int ps = 5;
    393
    394    tim_reset(td);
    395
    396    tim_write_ticr(td, count);
    397    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    398
    399    /* Run a quarter of the way, and change the prescaler. */
    400    clock_step(tim_calculate_step(count / 4, ps));
    401    g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
    402    ps = 2;
    403    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    404    /* The counter must not change. */
    405    g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
    406
    407    /* Run another quarter of the way, and change the prescaler again. */
    408    clock_step(tim_calculate_step(count / 4, ps));
    409    g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
    410    ps = 8;
    411    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    412    /* The counter must not change. */
    413    g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
    414
    415    /* Run another quarter of the way, and change the prescaler again. */
    416    clock_step(tim_calculate_step(count / 4, ps));
    417    g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
    418    ps = 0;
    419    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    420    /* The counter must not change. */
    421    g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
    422
    423    /* Run almost to expiration, and verify the timer didn't fire yet. */
    424    clock_step(tim_calculate_step(count / 4, ps) - 1);
    425    g_assert_cmpuint(tim_read_tdr(td), <, count);
    426    g_assert_cmphex(tim_read(td, TISR), ==, 0);
    427
    428    /* Now, run the rest of the way and verify that the timer fires. */
    429    clock_step(1);
    430    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    431}
    432
    433/* Verifies that a periodic timer automatically restarts after expiration. */
    434static void test_periodic_no_interrupt(gconstpointer test_data)
    435{
    436    const TestData *td = test_data;
    437    unsigned int count = 2;
    438    unsigned int ps = 3;
    439    int i;
    440
    441    tim_reset(td);
    442
    443    tim_write_ticr(td, count);
    444    tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
    445
    446    for (i = 0; i < 4; i++) {
    447        clock_step_next();
    448
    449        g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    450        g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    451
    452        tim_write(td, TISR, tim_timer_bit(td));
    453
    454        g_assert_cmphex(tim_read(td, TISR), ==, 0);
    455        g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    456    }
    457}
    458
    459/* Verifies that a periodict timer fires an interrupt every time it expires. */
    460static void test_periodic_interrupt(gconstpointer test_data)
    461{
    462    const TestData *td = test_data;
    463    unsigned int count = 65535;
    464    unsigned int ps = 2;
    465    int i;
    466
    467    tim_reset(td);
    468
    469    tim_write_ticr(td, count);
    470    tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
    471
    472    for (i = 0; i < 4; i++) {
    473        clock_step_next();
    474
    475        g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    476        g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    477
    478        tim_write(td, TISR, tim_timer_bit(td));
    479
    480        g_assert_cmphex(tim_read(td, TISR), ==, 0);
    481        g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
    482    }
    483}
    484
    485/*
    486 * Verifies that the timer behaves correctly when disabled right before and
    487 * exactly when it's supposed to expire.
    488 */
    489static void test_disable_on_expiration(gconstpointer test_data)
    490{
    491    const TestData *td = test_data;
    492    unsigned int count = 8;
    493    unsigned int ps = 255;
    494
    495    tim_reset(td);
    496
    497    tim_write_ticr(td, count);
    498    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    499
    500    clock_step(tim_calculate_step(count, ps) - 1);
    501
    502    tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
    503    tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
    504    clock_step(1);
    505    tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
    506    g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
    507}
    508
    509/*
    510 * Constructs a name that includes the timer block, timer and testcase name,
    511 * and adds the test to the test suite.
    512 */
    513static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
    514{
    515    g_autofree char *full_name = g_strdup_printf(
    516        "npcm7xx_timer/tim[%d]/timer[%d]/%s", tim_index(td->tim),
    517        timer_index(td->timer), name);
    518    qtest_add_data_func(full_name, td, fn);
    519}
    520
    521/* Convenience macro for adding a test with a predictable function name. */
    522#define add_test(name, td) tim_add_test(#name, td, test_##name)
    523
    524int main(int argc, char **argv)
    525{
    526    TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
    527    int ret;
    528    int i, j;
    529
    530    g_test_init(&argc, &argv, NULL);
    531    g_test_set_nonfatal_assertions();
    532
    533    for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
    534        for (j = 0; j < ARRAY_SIZE(timer); j++) {
    535            TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
    536            td->tim = &timer_block[i];
    537            td->timer = &timer[j];
    538
    539            add_test(reset, td);
    540            add_test(reset_overrides_enable, td);
    541            add_test(oneshot_enable_then_disable, td);
    542            add_test(oneshot_ps5, td);
    543            add_test(oneshot_ps0, td);
    544            add_test(oneshot_ps255, td);
    545            add_test(oneshot_interrupt, td);
    546            add_test(pause_resume, td);
    547            add_test(prescaler_change, td);
    548            add_test(periodic_no_interrupt, td);
    549            add_test(periodic_interrupt, td);
    550            add_test(disable_on_expiration, td);
    551        }
    552    }
    553
    554    qtest_start("-machine npcm750-evb");
    555    qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
    556    ret = g_test_run();
    557    qtest_end();
    558
    559    return ret;
    560}