diff options
author | Peter Maydell | 2020-12-10 12:48:25 +0100 |
---|---|---|
committer | Peter Maydell | 2020-12-10 12:48:25 +0100 |
commit | 180834dcb8277a687b62f035b477abfd5a1ff978 (patch) | |
tree | 435634a8ba46ac2177b86a5d1c12b23a467a7974 /tests | |
parent | Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (diff) | |
parent | hw/arm/armv7m: Correct typo in QOM object name (diff) | |
download | qemu-180834dcb8277a687b62f035b477abfd5a1ff978.tar.gz qemu-180834dcb8277a687b62f035b477abfd5a1ff978.tar.xz qemu-180834dcb8277a687b62f035b477abfd5a1ff978.zip |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201210' into staging
target-arm queue:
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
* Various minor code cleanups
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
* Implement more pieces of ARMv8.1M support
# gpg: Signature made Thu 10 Dec 2020 11:46:43 GMT
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20201210: (36 commits)
hw/arm/armv7m: Correct typo in QOM object name
hw/intc/armv7m_nvic: Implement read/write for RAS register block
target/arm: Implement M-profile "minimal RAS implementation"
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
target/arm: Implement CCR_S.TRD behaviour for SG insns
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
target/arm: Implement new v8.1M NOCP check for exception return
target/arm: Implement v8.1M REVIDR register
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
target/arm: Implement FPCXT_S fp system register
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
target/arm: Use new FPCR_NZCV_MASK constant
target/arm: Implement M-profile FPSCR_nzcvqc
target/arm: Implement VLDR/VSTR system register
target/arm: Move general-use constant expanders up in translate.c
target/arm: Refactor M-profile VMSR/VMRS handling
target/arm: Enforce M-profile VMRS/VMSR register restrictions
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/qtest/meson.build | 1 | ||||
-rw-r--r-- | tests/qtest/npcm7xx_rng-test.c | 12 | ||||
-rw-r--r-- | tests/qtest/xlnx-can-test.c | 360 |
3 files changed, 373 insertions, 0 deletions
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c19f1c8503..4ca83ce605 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -156,6 +156,7 @@ qtests_aarch64 = \ ['arm-cpu-features', 'numa-test', 'boot-serial-test', + 'xlnx-can-test', 'migration-test'] qtests_s390x = \ diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c index c614968ffc..797f832e53 100644 --- a/tests/qtest/npcm7xx_rng-test.c +++ b/tests/qtest/npcm7xx_rng-test.c @@ -20,6 +20,7 @@ #include "libqtest-single.h" #include "qemu/bitops.h" +#include "qemu-common.h" #define RNG_BASE_ADDR 0xf000b000 @@ -36,6 +37,13 @@ /* Number of bits to collect for randomness tests. */ #define TEST_INPUT_BITS (128) +static void dump_buf_if_failed(const uint8_t *buf, size_t size) +{ + if (g_test_failed()) { + qemu_hexdump(stderr, "", buf, size); + } +} + static void rng_writeb(unsigned int offset, uint8_t value) { writeb(RNG_BASE_ADDR + offset, value); @@ -188,6 +196,7 @@ static void test_continuous_monobit(void) } g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01); + dump_buf_if_failed(buf, sizeof(buf)); } /* @@ -209,6 +218,7 @@ static void test_continuous_runs(void) } g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01); + dump_buf_if_failed(buf.c, sizeof(buf)); } /* @@ -230,6 +240,7 @@ static void test_first_byte_monobit(void) } g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01); + dump_buf_if_failed(buf, sizeof(buf)); } /* @@ -254,6 +265,7 @@ static void test_first_byte_runs(void) } g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01); + dump_buf_if_failed(buf.c, sizeof(buf)); } int main(int argc, char **argv) diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c new file mode 100644 index 0000000000..3d1120005b --- /dev/null +++ b/tests/qtest/xlnx-can-test.c @@ -0,0 +1,360 @@ +/* + * QTests for the Xilinx ZynqMP CAN controller. + * + * Copyright (c) 2020 Xilinx Inc. + * + * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "libqos/libqtest.h" + +/* Base address. */ +#define CAN0_BASE_ADDR 0xFF060000 +#define CAN1_BASE_ADDR 0xFF070000 + +/* Register addresses. */ +#define R_SRR_OFFSET 0x00 +#define R_MSR_OFFSET 0x04 +#define R_SR_OFFSET 0x18 +#define R_ISR_OFFSET 0x1C +#define R_ICR_OFFSET 0x24 +#define R_TXID_OFFSET 0x30 +#define R_TXDLC_OFFSET 0x34 +#define R_TXDATA1_OFFSET 0x38 +#define R_TXDATA2_OFFSET 0x3C +#define R_RXID_OFFSET 0x50 +#define R_RXDLC_OFFSET 0x54 +#define R_RXDATA1_OFFSET 0x58 +#define R_RXDATA2_OFFSET 0x5C +#define R_AFR 0x60 +#define R_AFMR1 0x64 +#define R_AFIR1 0x68 +#define R_AFMR2 0x6C +#define R_AFIR2 0x70 +#define R_AFMR3 0x74 +#define R_AFIR3 0x78 +#define R_AFMR4 0x7C +#define R_AFIR4 0x80 + +/* CAN modes. */ +#define CONFIG_MODE 0x00 +#define NORMAL_MODE 0x00 +#define LOOPBACK_MODE 0x02 +#define SNOOP_MODE 0x04 +#define SLEEP_MODE 0x01 +#define ENABLE_CAN (1 << 1) +#define STATUS_NORMAL_MODE (1 << 3) +#define STATUS_LOOPBACK_MODE (1 << 1) +#define STATUS_SNOOP_MODE (1 << 12) +#define STATUS_SLEEP_MODE (1 << 2) +#define ISR_TXOK (1 << 1) +#define ISR_RXOK (1 << 4) + +static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx, + uint8_t can_timestamp) +{ + uint16_t size = 0; + uint8_t len = 4; + + while (size < len) { + if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) { + g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp); + } else { + g_assert_cmpint(buf_rx[size], ==, buf_tx[size]); + } + + size++; + } +} + +static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx) +{ + uint32_t int_status; + + /* Read the interrupt on CAN rx. */ + int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK; + + g_assert_cmpint(int_status, ==, ISR_RXOK); + + /* Read the RX register data for CAN. */ + buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET); + buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET); + buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET); + buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET); + + /* Clear the RX interrupt. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK); +} + +static void send_data(QTestState *qts, uint64_t can_base_addr, + const uint32_t *buf_tx) +{ + uint32_t int_status; + + /* Write the TX register data for CAN. */ + qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]); + qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]); + qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]); + qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]); + + /* Read the interrupt on CAN for tx. */ + int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK; + + g_assert_cmpint(int_status, ==, ISR_TXOK); + + /* Clear the interrupt for tx. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK); +} + +/* + * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0 + * initiate the data transfer to can-bus, CAN1 receives the data. Test compares + * the data sent from CAN0 with received on CAN1. + */ +static void test_can_bus(void) +{ + const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status = 0; + uint8_t can_timestamp = 1; + + QTestState *qts = qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=canbus0" + " -machine xlnx-zcu102.canbus0=canbus0" + " -machine xlnx-zcu102.canbus1=canbus0" + ); + + /* Configure the CAN0 and CAN1. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 and CAN1 are in normal mode. */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* + * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of + * each CAN0 and CAN1 are compared with RX register data for respective CAN. + */ +static void test_can_loopback(void) +{ + uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status = 0; + + QTestState *qts = qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=canbus0" + " -machine xlnx-zcu102.canbus0=canbus0" + " -machine xlnx-zcu102.canbus1=canbus0" + ); + + /* Configure the CAN0 in loopback mode. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + /* Check here if CAN0 is set in loopback mode. */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + + g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + read_data(qts, CAN0_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, 0); + + /* Configure the CAN1 in loopback mode. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + /* Check here if CAN1 is set in loopback mode. */ + status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + + g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, 0); + + qtest_quit(qts); +} + +/* + * Enable filters for CAN1. This will filter incoming messages with ID. In this + * test message will pass through filter 2. + */ +static void test_can_filter(void) +{ + uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status = 0; + uint8_t can_timestamp = 1; + + QTestState *qts = qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=canbus0" + " -machine xlnx-zcu102.canbus0=canbus0" + " -machine xlnx-zcu102.canbus1=canbus0" + ); + + /* Configure the CAN0 and CAN1. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 and CAN1 are in normal mode. */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + /* Set filter for CAN1 for incoming messages. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234); + + qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */ +static void test_can_sleepmode(void) +{ + uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status = 0; + uint8_t can_timestamp = 1; + + QTestState *qts = qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=canbus0" + " -machine xlnx-zcu102.canbus0=canbus0" + " -machine xlnx-zcu102.canbus1=canbus0" + ); + + /* Configure the CAN0. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_SLEEP_MODE); + + status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + + /* + * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode. + * Check the CAN0 status now. It should exit the sleep mode and receive the + * incoming data. + */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + read_data(qts, CAN0_BASE_ADDR, buf_rx); + + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */ +static void test_can_snoopmode(void) +{ + uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status = 0; + uint8_t can_timestamp = 1; + + QTestState *qts = qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=canbus0" + " -machine xlnx-zcu102.canbus0=canbus0" + " -machine xlnx-zcu102.canbus1=canbus0" + ); + + /* Configure the CAN0. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */ + status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_SNOOP_MODE); + + status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + + read_data(qts, CAN0_BASE_ADDR, buf_rx); + + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/net/can/can_bus", test_can_bus); + qtest_add_func("/net/can/can_loopback", test_can_loopback); + qtest_add_func("/net/can/can_filter", test_can_filter); + qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode); + qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode); + + return g_test_run(); +} |