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_gpio-test.c (14364B)


      1/*
      2 * QTest testcase for the Nuvoton NPCM7xx GPIO modules.
      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 "libqtest-single.h"
     19
     20#define NR_GPIO_DEVICES (8)
     21#define GPIO(x)         (0xf0010000 + (x) * 0x1000)
     22#define GPIO_IRQ(x)     (116 + (x))
     23
     24/* GPIO registers */
     25#define GP_N_TLOCK1     0x00
     26#define GP_N_DIN        0x04 /* Data IN */
     27#define GP_N_POL        0x08 /* Polarity */
     28#define GP_N_DOUT       0x0c /* Data OUT */
     29#define GP_N_OE         0x10 /* Output Enable */
     30#define GP_N_OTYP       0x14
     31#define GP_N_MP         0x18
     32#define GP_N_PU         0x1c /* Pull-up */
     33#define GP_N_PD         0x20 /* Pull-down */
     34#define GP_N_DBNC       0x24 /* Debounce */
     35#define GP_N_EVTYP      0x28 /* Event Type */
     36#define GP_N_EVBE       0x2c /* Event Both Edge */
     37#define GP_N_OBL0       0x30
     38#define GP_N_OBL1       0x34
     39#define GP_N_OBL2       0x38
     40#define GP_N_OBL3       0x3c
     41#define GP_N_EVEN       0x40 /* Event Enable */
     42#define GP_N_EVENS      0x44 /* Event Set (enable) */
     43#define GP_N_EVENC      0x48 /* Event Clear (disable) */
     44#define GP_N_EVST       0x4c /* Event Status */
     45#define GP_N_SPLCK      0x50
     46#define GP_N_MPLCK      0x54
     47#define GP_N_IEM        0x58 /* Input Enable */
     48#define GP_N_OSRC       0x5c
     49#define GP_N_ODSC       0x60
     50#define GP_N_DOS        0x68 /* Data OUT Set */
     51#define GP_N_DOC        0x6c /* Data OUT Clear */
     52#define GP_N_OES        0x70 /* Output Enable Set */
     53#define GP_N_OEC        0x74 /* Output Enable Clear */
     54#define GP_N_TLOCK2     0x7c
     55
     56static void gpio_unlock(int n)
     57{
     58    if (readl(GPIO(n) + GP_N_TLOCK1) != 0) {
     59        writel(GPIO(n) + GP_N_TLOCK2, 0xc0de1248);
     60        writel(GPIO(n) + GP_N_TLOCK1, 0xc0defa73);
     61    }
     62}
     63
     64/* Restore the GPIO controller to a sensible default state. */
     65static void gpio_reset(int n)
     66{
     67    gpio_unlock(0);
     68
     69    writel(GPIO(n) + GP_N_EVEN, 0x00000000);
     70    writel(GPIO(n) + GP_N_EVST, 0xffffffff);
     71    writel(GPIO(n) + GP_N_POL, 0x00000000);
     72    writel(GPIO(n) + GP_N_DOUT, 0x00000000);
     73    writel(GPIO(n) + GP_N_OE, 0x00000000);
     74    writel(GPIO(n) + GP_N_OTYP, 0x00000000);
     75    writel(GPIO(n) + GP_N_PU, 0xffffffff);
     76    writel(GPIO(n) + GP_N_PD, 0x00000000);
     77    writel(GPIO(n) + GP_N_IEM, 0xffffffff);
     78}
     79
     80static void test_dout_to_din(void)
     81{
     82    gpio_reset(0);
     83
     84    /* When output is enabled, DOUT should be reflected on DIN. */
     85    writel(GPIO(0) + GP_N_OE, 0xffffffff);
     86    /* PU and PD shouldn't have any impact on DIN. */
     87    writel(GPIO(0) + GP_N_PU, 0xffff0000);
     88    writel(GPIO(0) + GP_N_PD, 0x0000ffff);
     89    writel(GPIO(0) + GP_N_DOUT, 0x12345678);
     90    g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x12345678);
     91    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x12345678);
     92}
     93
     94static void test_pullup_pulldown(void)
     95{
     96    gpio_reset(0);
     97
     98    /*
     99     * When output is disabled, and PD is the inverse of PU, PU should be
    100     * reflected on DIN. If PD is not the inverse of PU, the state of DIN is
    101     * undefined, so we don't test that.
    102     */
    103    writel(GPIO(0) + GP_N_OE, 0x00000000);
    104    /* DOUT shouldn't have any impact on DIN. */
    105    writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
    106    writel(GPIO(0) + GP_N_PU, 0x23456789);
    107    writel(GPIO(0) + GP_N_PD, ~0x23456789U);
    108    g_assert_cmphex(readl(GPIO(0) + GP_N_PU), ==, 0x23456789);
    109    g_assert_cmphex(readl(GPIO(0) + GP_N_PD), ==, ~0x23456789U);
    110    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x23456789);
    111}
    112
    113static void test_output_enable(void)
    114{
    115    gpio_reset(0);
    116
    117    /*
    118     * With all pins weakly pulled down, and DOUT all-ones, OE should be
    119     * reflected on DIN.
    120     */
    121    writel(GPIO(0) + GP_N_DOUT, 0xffffffff);
    122    writel(GPIO(0) + GP_N_PU, 0x00000000);
    123    writel(GPIO(0) + GP_N_PD, 0xffffffff);
    124    writel(GPIO(0) + GP_N_OE, 0x3456789a);
    125    g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3456789a);
    126    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3456789a);
    127
    128    writel(GPIO(0) + GP_N_OEC, 0x00030002);
    129    g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x34547898);
    130    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x34547898);
    131
    132    writel(GPIO(0) + GP_N_OES, 0x0000f001);
    133    g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3454f899);
    134    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3454f899);
    135}
    136
    137static void test_open_drain(void)
    138{
    139    gpio_reset(0);
    140
    141    /*
    142     * Upper half of DOUT drives a 1 only if the corresponding bit in OTYP is
    143     * not set. If OTYP is set, DIN is determined by PU/PD. Lower half of
    144     * DOUT always drives a 0 regardless of OTYP; PU/PD have no effect.  When
    145     * OE is 0, output is determined by PU/PD; OTYP has no effect.
    146     */
    147    writel(GPIO(0) + GP_N_OTYP, 0x456789ab);
    148    writel(GPIO(0) + GP_N_OE, 0xf0f0f0f0);
    149    writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
    150    writel(GPIO(0) + GP_N_PU, 0xff00ff00);
    151    writel(GPIO(0) + GP_N_PD, 0x00ff00ff);
    152    g_assert_cmphex(readl(GPIO(0) + GP_N_OTYP), ==, 0x456789ab);
    153    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff900f00);
    154}
    155
    156static void test_polarity(void)
    157{
    158    gpio_reset(0);
    159
    160    /*
    161     * In push-pull mode, DIN should reflect DOUT because the signal is
    162     * inverted in both directions.
    163     */
    164    writel(GPIO(0) + GP_N_OTYP, 0x00000000);
    165    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    166    writel(GPIO(0) + GP_N_DOUT, 0x56789abc);
    167    writel(GPIO(0) + GP_N_POL, 0x6789abcd);
    168    g_assert_cmphex(readl(GPIO(0) + GP_N_POL), ==, 0x6789abcd);
    169    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x56789abc);
    170
    171    /*
    172     * When turning off the drivers, DIN should reflect the inverse of the
    173     * pulled-up lines.
    174     */
    175    writel(GPIO(0) + GP_N_OE, 0x00000000);
    176    writel(GPIO(0) + GP_N_POL, 0xffffffff);
    177    writel(GPIO(0) + GP_N_PU, 0x789abcde);
    178    writel(GPIO(0) + GP_N_PD, ~0x789abcdeU);
    179    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, ~0x789abcdeU);
    180
    181    /*
    182     * In open-drain mode, DOUT=1 will appear to drive the pin high (since DIN
    183     * is inverted), while DOUT=0 will leave the pin floating.
    184     */
    185    writel(GPIO(0) + GP_N_OTYP, 0xffffffff);
    186    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    187    writel(GPIO(0) + GP_N_PU, 0xffff0000);
    188    writel(GPIO(0) + GP_N_PD, 0x0000ffff);
    189    writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
    190    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff00ffff);
    191}
    192
    193static void test_input_mask(void)
    194{
    195    gpio_reset(0);
    196
    197    /* IEM=0 forces the input to zero before polarity inversion. */
    198    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    199    writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
    200    writel(GPIO(0) + GP_N_POL, 0xffff0000);
    201    writel(GPIO(0) + GP_N_IEM, 0x87654321);
    202    g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff9a4300);
    203}
    204
    205static void test_temp_lock(void)
    206{
    207    gpio_reset(0);
    208
    209    writel(GPIO(0) + GP_N_DOUT, 0x98765432);
    210
    211    /* Make sure we're unlocked initially. */
    212    g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
    213    /* Writing any value to TLOCK1 will lock. */
    214    writel(GPIO(0) + GP_N_TLOCK1, 0);
    215    g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
    216    writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
    217    g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
    218    /* Now, try to unlock. */
    219    gpio_unlock(0);
    220    g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
    221    writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
    222    g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
    223
    224    /* Try it again, but write TLOCK2 to lock. */
    225    writel(GPIO(0) + GP_N_TLOCK2, 0);
    226    g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
    227    writel(GPIO(0) + GP_N_DOUT, 0x98765432);
    228    g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
    229    /* Now, try to unlock. */
    230    gpio_unlock(0);
    231    g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
    232    writel(GPIO(0) + GP_N_DOUT, 0x98765432);
    233    g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
    234}
    235
    236static void test_events_level(void)
    237{
    238    gpio_reset(0);
    239
    240    writel(GPIO(0) + GP_N_EVTYP, 0x00000000);
    241    writel(GPIO(0) + GP_N_DOUT, 0xba987654);
    242    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    243    writel(GPIO(0) + GP_N_EVST, 0xffffffff);
    244
    245    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
    246    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    247    writel(GPIO(0) + GP_N_DOUT, 0x00000000);
    248    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
    249    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    250    writel(GPIO(0) + GP_N_EVST, 0x00007654);
    251    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba980000);
    252    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    253    writel(GPIO(0) + GP_N_EVST, 0xba980000);
    254    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
    255    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    256}
    257
    258static void test_events_rising_edge(void)
    259{
    260    gpio_reset(0);
    261
    262    writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
    263    writel(GPIO(0) + GP_N_EVBE, 0x00000000);
    264    writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
    265    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    266    writel(GPIO(0) + GP_N_EVST, 0xffffffff);
    267
    268    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
    269    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    270    writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
    271    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x0000ff00);
    272    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    273    writel(GPIO(0) + GP_N_DOUT, 0x00ff0000);
    274    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
    275    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    276    writel(GPIO(0) + GP_N_EVST, 0x0000f000);
    277    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ff0f00);
    278    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    279    writel(GPIO(0) + GP_N_EVST, 0x00ff0f00);
    280    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
    281    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    282}
    283
    284static void test_events_both_edges(void)
    285{
    286    gpio_reset(0);
    287
    288    writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
    289    writel(GPIO(0) + GP_N_EVBE, 0xffffffff);
    290    writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
    291    writel(GPIO(0) + GP_N_OE, 0xffffffff);
    292    writel(GPIO(0) + GP_N_EVST, 0xffffffff);
    293
    294    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
    295    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    296    writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
    297    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
    298    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    299    writel(GPIO(0) + GP_N_DOUT, 0xef00ff08);
    300    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ffff08);
    301    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    302    writel(GPIO(0) + GP_N_EVST, 0x0000f000);
    303    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ff0f08);
    304    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    305    writel(GPIO(0) + GP_N_EVST, 0x10ff0f08);
    306    g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
    307    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
    308}
    309
    310static void test_gpion_irq(gconstpointer test_data)
    311{
    312    intptr_t n = (intptr_t)test_data;
    313
    314    gpio_reset(n);
    315
    316    writel(GPIO(n) + GP_N_EVTYP, 0x00000000);
    317    writel(GPIO(n) + GP_N_DOUT, 0x00000000);
    318    writel(GPIO(n) + GP_N_OE, 0xffffffff);
    319    writel(GPIO(n) + GP_N_EVST, 0xffffffff);
    320    writel(GPIO(n) + GP_N_EVEN, 0x00000000);
    321
    322    /* Trigger an event; interrupts are masked. */
    323    g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00000000);
    324    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    325    writel(GPIO(n) + GP_N_DOS, 0x00008000);
    326    g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00008000);
    327    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    328
    329    /* Unmask all event interrupts; verify that the interrupt fired. */
    330    writel(GPIO(n) + GP_N_EVEN, 0xffffffff);
    331    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    332
    333    /* Clear the current bit, set a new bit, irq stays asserted. */
    334    writel(GPIO(n) + GP_N_DOC, 0x00008000);
    335    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    336    writel(GPIO(n) + GP_N_DOS, 0x00000200);
    337    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    338    writel(GPIO(n) + GP_N_EVST, 0x00008000);
    339    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    340
    341    /* Mask/unmask the event that's currently active. */
    342    writel(GPIO(n) + GP_N_EVENC, 0x00000200);
    343    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    344    writel(GPIO(n) + GP_N_EVENS, 0x00000200);
    345    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    346
    347    /* Clear the input and the status bit, irq is deasserted. */
    348    writel(GPIO(n) + GP_N_DOC, 0x00000200);
    349    g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    350    writel(GPIO(n) + GP_N_EVST, 0x00000200);
    351    g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
    352}
    353
    354int main(int argc, char **argv)
    355{
    356    int ret;
    357    int i;
    358
    359    g_test_init(&argc, &argv, NULL);
    360    g_test_set_nonfatal_assertions();
    361
    362    qtest_add_func("/npcm7xx_gpio/dout_to_din", test_dout_to_din);
    363    qtest_add_func("/npcm7xx_gpio/pullup_pulldown", test_pullup_pulldown);
    364    qtest_add_func("/npcm7xx_gpio/output_enable", test_output_enable);
    365    qtest_add_func("/npcm7xx_gpio/open_drain", test_open_drain);
    366    qtest_add_func("/npcm7xx_gpio/polarity", test_polarity);
    367    qtest_add_func("/npcm7xx_gpio/input_mask", test_input_mask);
    368    qtest_add_func("/npcm7xx_gpio/temp_lock", test_temp_lock);
    369    qtest_add_func("/npcm7xx_gpio/events/level", test_events_level);
    370    qtest_add_func("/npcm7xx_gpio/events/rising_edge", test_events_rising_edge);
    371    qtest_add_func("/npcm7xx_gpio/events/both_edges", test_events_both_edges);
    372
    373    for (i = 0; i < NR_GPIO_DEVICES; i++) {
    374        g_autofree char *test_name =
    375            g_strdup_printf("/npcm7xx_gpio/gpio[%d]/irq", i);
    376        qtest_add_data_func(test_name, (void *)(intptr_t)i, test_gpion_irq);
    377    }
    378
    379    qtest_start("-machine npcm750-evb");
    380    qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
    381    ret = g_test_run();
    382    qtest_end();
    383
    384    return ret;
    385}