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

xlnx-can-test.c (12963B)


      1/*
      2 * QTests for the Xilinx ZynqMP CAN controller.
      3 *
      4 * Copyright (c) 2020 Xilinx Inc.
      5 *
      6 * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
      7 *
      8 * Permission is hereby granted, free of charge, to any person obtaining a copy
      9 * of this software and associated documentation files (the "Software"), to deal
     10 * in the Software without restriction, including without limitation the rights
     11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12 * copies of the Software, and to permit persons to whom the Software is
     13 * furnished to do so, subject to the following conditions:
     14 *
     15 * The above copyright notice and this permission notice shall be included in
     16 * all copies or substantial portions of the Software.
     17 *
     18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     24 * THE SOFTWARE.
     25 */
     26
     27#include "qemu/osdep.h"
     28#include "libqos/libqtest.h"
     29
     30/* Base address. */
     31#define CAN0_BASE_ADDR          0xFF060000
     32#define CAN1_BASE_ADDR          0xFF070000
     33
     34/* Register addresses. */
     35#define R_SRR_OFFSET            0x00
     36#define R_MSR_OFFSET            0x04
     37#define R_SR_OFFSET             0x18
     38#define R_ISR_OFFSET            0x1C
     39#define R_ICR_OFFSET            0x24
     40#define R_TXID_OFFSET           0x30
     41#define R_TXDLC_OFFSET          0x34
     42#define R_TXDATA1_OFFSET        0x38
     43#define R_TXDATA2_OFFSET        0x3C
     44#define R_RXID_OFFSET           0x50
     45#define R_RXDLC_OFFSET          0x54
     46#define R_RXDATA1_OFFSET        0x58
     47#define R_RXDATA2_OFFSET        0x5C
     48#define R_AFR                   0x60
     49#define R_AFMR1                 0x64
     50#define R_AFIR1                 0x68
     51#define R_AFMR2                 0x6C
     52#define R_AFIR2                 0x70
     53#define R_AFMR3                 0x74
     54#define R_AFIR3                 0x78
     55#define R_AFMR4                 0x7C
     56#define R_AFIR4                 0x80
     57
     58/* CAN modes. */
     59#define CONFIG_MODE             0x00
     60#define NORMAL_MODE             0x00
     61#define LOOPBACK_MODE           0x02
     62#define SNOOP_MODE              0x04
     63#define SLEEP_MODE              0x01
     64#define ENABLE_CAN              (1 << 1)
     65#define STATUS_NORMAL_MODE      (1 << 3)
     66#define STATUS_LOOPBACK_MODE    (1 << 1)
     67#define STATUS_SNOOP_MODE       (1 << 12)
     68#define STATUS_SLEEP_MODE       (1 << 2)
     69#define ISR_TXOK                (1 << 1)
     70#define ISR_RXOK                (1 << 4)
     71
     72static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
     73                             uint8_t can_timestamp)
     74{
     75    uint16_t size = 0;
     76    uint8_t len = 4;
     77
     78    while (size < len) {
     79        if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET)  {
     80            g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
     81        } else {
     82            g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
     83        }
     84
     85        size++;
     86    }
     87}
     88
     89static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
     90{
     91    uint32_t int_status;
     92
     93    /* Read the interrupt on CAN rx. */
     94    int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
     95
     96    g_assert_cmpint(int_status, ==, ISR_RXOK);
     97
     98    /* Read the RX register data for CAN. */
     99    buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
    100    buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
    101    buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
    102    buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
    103
    104    /* Clear the RX interrupt. */
    105    qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
    106}
    107
    108static void send_data(QTestState *qts, uint64_t can_base_addr,
    109                      const uint32_t *buf_tx)
    110{
    111    uint32_t int_status;
    112
    113    /* Write the TX register data for CAN. */
    114    qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
    115    qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
    116    qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
    117    qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
    118
    119    /* Read the interrupt on CAN for tx. */
    120    int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
    121
    122    g_assert_cmpint(int_status, ==, ISR_TXOK);
    123
    124    /* Clear the interrupt for tx. */
    125    qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
    126}
    127
    128/*
    129 * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
    130 * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
    131 * the data sent from CAN0 with received on CAN1.
    132 */
    133static void test_can_bus(void)
    134{
    135    const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
    136    uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
    137    uint32_t status = 0;
    138    uint8_t can_timestamp = 1;
    139
    140    QTestState *qts = qtest_init("-machine xlnx-zcu102"
    141                " -object can-bus,id=canbus"
    142                " -machine canbus0=canbus"
    143                " -machine canbus1=canbus"
    144                );
    145
    146    /* Configure the CAN0 and CAN1. */
    147    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    148    qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    149    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    150    qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    151
    152    /* Check here if CAN0 and CAN1 are in normal mode. */
    153    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    154    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    155
    156    status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
    157    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    158
    159    send_data(qts, CAN0_BASE_ADDR, buf_tx);
    160
    161    read_data(qts, CAN1_BASE_ADDR, buf_rx);
    162    match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
    163
    164    qtest_quit(qts);
    165}
    166
    167/*
    168 * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
    169 * each CAN0 and CAN1 are compared with RX register data for respective CAN.
    170 */
    171static void test_can_loopback(void)
    172{
    173    uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
    174    uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
    175    uint32_t status = 0;
    176
    177    QTestState *qts = qtest_init("-machine xlnx-zcu102"
    178                " -object can-bus,id=canbus"
    179                " -machine canbus0=canbus"
    180                " -machine canbus1=canbus"
    181                );
    182
    183    /* Configure the CAN0 in loopback mode. */
    184    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
    185    qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
    186    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    187
    188    /* Check here if CAN0 is set in loopback mode. */
    189    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    190
    191    g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
    192
    193    send_data(qts, CAN0_BASE_ADDR, buf_tx);
    194    read_data(qts, CAN0_BASE_ADDR, buf_rx);
    195    match_rx_tx_data(buf_tx, buf_rx, 0);
    196
    197    /* Configure the CAN1 in loopback mode. */
    198    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
    199    qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
    200    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    201
    202    /* Check here if CAN1 is set in loopback mode. */
    203    status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
    204
    205    g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
    206
    207    send_data(qts, CAN1_BASE_ADDR, buf_tx);
    208    read_data(qts, CAN1_BASE_ADDR, buf_rx);
    209    match_rx_tx_data(buf_tx, buf_rx, 0);
    210
    211    qtest_quit(qts);
    212}
    213
    214/*
    215 * Enable filters for CAN1. This will filter incoming messages with ID. In this
    216 * test message will pass through filter 2.
    217 */
    218static void test_can_filter(void)
    219{
    220    uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
    221    uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
    222    uint32_t status = 0;
    223    uint8_t can_timestamp = 1;
    224
    225    QTestState *qts = qtest_init("-machine xlnx-zcu102"
    226                " -object can-bus,id=canbus"
    227                " -machine canbus0=canbus"
    228                " -machine canbus1=canbus"
    229                );
    230
    231    /* Configure the CAN0 and CAN1. */
    232    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    233    qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    234    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    235    qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    236
    237    /* Check here if CAN0 and CAN1 are in normal mode. */
    238    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    239    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    240
    241    status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
    242    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    243
    244    /* Set filter for CAN1 for incoming messages. */
    245    qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
    246    qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
    247    qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
    248    qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
    249    qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
    250    qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
    251    qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
    252    qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
    253    qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
    254
    255    qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
    256
    257    send_data(qts, CAN0_BASE_ADDR, buf_tx);
    258
    259    read_data(qts, CAN1_BASE_ADDR, buf_rx);
    260    match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
    261
    262    qtest_quit(qts);
    263}
    264
    265/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
    266static void test_can_sleepmode(void)
    267{
    268    uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
    269    uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
    270    uint32_t status = 0;
    271    uint8_t can_timestamp = 1;
    272
    273    QTestState *qts = qtest_init("-machine xlnx-zcu102"
    274                " -object can-bus,id=canbus"
    275                " -machine canbus0=canbus"
    276                " -machine canbus1=canbus"
    277                );
    278
    279    /* Configure the CAN0. */
    280    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
    281    qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
    282    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    283
    284    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    285    qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    286
    287    /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
    288    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    289    g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
    290
    291    status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
    292    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    293
    294    send_data(qts, CAN1_BASE_ADDR, buf_tx);
    295
    296    /*
    297     * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
    298     * Check the CAN0 status now. It should exit the sleep mode and receive the
    299     * incoming data.
    300     */
    301    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    302    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    303
    304    read_data(qts, CAN0_BASE_ADDR, buf_rx);
    305
    306    match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
    307
    308    qtest_quit(qts);
    309}
    310
    311/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
    312static void test_can_snoopmode(void)
    313{
    314    uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
    315    uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
    316    uint32_t status = 0;
    317    uint8_t can_timestamp = 1;
    318
    319    QTestState *qts = qtest_init("-machine xlnx-zcu102"
    320                " -object can-bus,id=canbus"
    321                " -machine canbus0=canbus"
    322                " -machine canbus1=canbus"
    323                );
    324
    325    /* Configure the CAN0. */
    326    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
    327    qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
    328    qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    329
    330    qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
    331    qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
    332
    333    /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
    334    status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
    335    g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
    336
    337    status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
    338    g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
    339
    340    send_data(qts, CAN1_BASE_ADDR, buf_tx);
    341
    342    read_data(qts, CAN0_BASE_ADDR, buf_rx);
    343
    344    match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
    345
    346    qtest_quit(qts);
    347}
    348
    349int main(int argc, char **argv)
    350{
    351    g_test_init(&argc, &argv, NULL);
    352
    353    qtest_add_func("/net/can/can_bus", test_can_bus);
    354    qtest_add_func("/net/can/can_loopback", test_can_loopback);
    355    qtest_add_func("/net/can/can_filter", test_can_filter);
    356    qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
    357    qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
    358
    359    return g_test_run();
    360}