diff options
author | Madhukar Pappireddy <madhukar.pappireddy@arm.com> | 2020-12-31 19:25:33 -0600 |
---|---|---|
committer | Madhukar Pappireddy <madhukar.pappireddy@arm.com> | 2021-04-30 09:31:53 -0500 |
commit | 172523b9ceadd0af9f6e8e4fb899cc7f354ff002 (patch) | |
tree | ef3d02c2953b208aa5e1c84a23bc58a117f27e9a | |
parent | c5b60fce76bd56739c909fa0d5ac53d482171c88 (diff) | |
download | tf-a-tests-172523b9ceadd0af9f6e8e4fb899cc7f354ff002.tar.gz |
Cactus test for exercising SMMUv3 driver to perform stage2 translation
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I498cb63aed497ab469a38e486a7943dd634e5b36
-rw-r--r-- | include/lib/mmio.h | 19 | ||||
-rw-r--r-- | include/runtime_services/cactus_test_cmds.h | 13 | ||||
-rw-r--r-- | plat/arm/fvp/include/platform_def.h | 6 | ||||
-rw-r--r-- | spm/cactus/cactus.mk | 1 | ||||
-rw-r--r-- | spm/cactus/cactus_main.c | 3 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/cactus_tests_smmuv3.c | 175 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/smmuv3_test_engine.h | 45 | ||||
-rw-r--r-- | spm/cactus/plat/arm/fvp/fdts/cactus.dts | 32 | ||||
-rw-r--r-- | spm/cactus/plat/arm/fvp/include/cactus_platform_def.h | 10 | ||||
-rw-r--r-- | tftf/tests/runtime_services/secure_service/test_spm_smmu.c | 38 | ||||
-rw-r--r-- | tftf/tests/tests-spm.mk | 1 | ||||
-rw-r--r-- | tftf/tests/tests-spm.xml | 5 |
12 files changed, 345 insertions, 3 deletions
diff --git a/include/lib/mmio.h b/include/lib/mmio.h index e8a7df02b..c788af334 100644 --- a/include/lib/mmio.h +++ b/include/lib/mmio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2021, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -24,16 +24,33 @@ static inline void mmio_write_32(uintptr_t addr, uint32_t value) *(volatile uint32_t*)addr = value; } +static inline void mmio_write32_offset(uintptr_t addr, uint32_t byte_off, + uint32_t data) +{ + mmio_write_32((uintptr_t)((uint8_t *)addr + byte_off), data); +} + static inline uint32_t mmio_read_32(uintptr_t addr) { return *(volatile uint32_t*)addr; } +static inline uint32_t mmio_read32_offset(uintptr_t addr, uint32_t byte_off) +{ + return mmio_read_32((uintptr_t)((uint8_t *)addr + byte_off)); +} + static inline void mmio_write_64(uintptr_t addr, uint64_t value) { *(volatile uint64_t*)addr = value; } +static inline void mmio_write64_offset(uintptr_t addr, uint32_t byte_off, + uint64_t data) +{ + mmio_write_64((uintptr_t)((uint8_t *)addr + byte_off), data); +} + static inline uint64_t mmio_read_64(uintptr_t addr) { return *(volatile uint64_t*)addr; diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h index d03a97fcb..483a7f493 100644 --- a/include/runtime_services/cactus_test_cmds.h +++ b/include/runtime_services/cactus_test_cmds.h @@ -299,4 +299,17 @@ static inline enum interrupt_pin cactus_get_interrupt_pin(smc_ret_values ret) return (enum interrupt_pin)ret.ret6; } +/** + * Request to initiate DMA transaction by upstream peripheral. + * + * The command id is the hex representation of the string "SMMU" + */ +#define CACTUS_DMA_SMMUv3_CMD (0x534d4d55) + +static inline smc_ret_values cactus_send_dma_cmd( + ffa_vm_id_t source, ffa_vm_id_t dest) +{ + return cactus_send_cmd(source, dest, CACTUS_DMA_SMMUv3_CMD, 0, 0, 0, + 0); +} #endif diff --git a/plat/arm/fvp/include/platform_def.h b/plat/arm/fvp/include/platform_def.h index ed456420d..3afc9b8bb 100644 --- a/plat/arm/fvp/include/platform_def.h +++ b/plat/arm/fvp/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * Copyright (c) 2018-2021, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -217,7 +217,11 @@ #define MAX_XLAT_TABLES 20 #define MAX_MMAP_REGIONS 50 #else +#if IMAGE_CACTUS +#define MAX_XLAT_TABLES 6 +#else #define MAX_XLAT_TABLES 5 +#endif #define MAX_MMAP_REGIONS 16 #endif diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk index a52120f1f..ae66c1de9 100644 --- a/spm/cactus/cactus.mk +++ b/spm/cactus/cactus.mk @@ -49,6 +49,7 @@ CACTUS_SOURCES := \ cactus_test_ffa.c \ cactus_test_interrupts.c \ cactus_test_memory_sharing.c \ + cactus_tests_smmuv3.c \ ) # TODO: Remove dependency on TFTF files. diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c index 45d2db039..ff3f61871 100644 --- a/spm/cactus/cactus_main.c +++ b/spm/cactus/cactus_main.c @@ -93,6 +93,9 @@ static const mmap_region_t cactus_mmap[] __attribute__((used)) = { /* PLAT_ARM_DEVICE0 area includes UART2 necessary to console */ MAP_REGION_FLAT(PLAT_ARM_DEVICE0_BASE, PLAT_ARM_DEVICE0_SIZE, MT_DEVICE | MT_RW), + /* scratch memory allocated to be used for running SMMU tests */ + MAP_REGION_FLAT(PLAT_CACTUS_MEMCPY_BASE, PLAT_CACTUS_MEMCPY_RANGE, + MT_MEMORY | MT_RW), {0} }; diff --git a/spm/cactus/cactus_tests/cactus_tests_smmuv3.c b/spm/cactus/cactus_tests/cactus_tests_smmuv3.c new file mode 100644 index 000000000..ce53dc64a --- /dev/null +++ b/spm/cactus/cactus_tests/cactus_tests_smmuv3.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include "cactus.h" +#include "cactus_message_loop.h" +#include <cactus_platform_def.h> +#include "cactus_test_cmds.h" +#include "cactus_tests.h" +#include <debug.h> +#include <ffa_helpers.h> +#include <mmio.h> +#include "smmuv3_test_engine.h" +#include <sp_helpers.h> +#include <spm_common.h> + +/* Source and target address for memcopy operation */ +#define MEMCPY_SOURCE_BASE PLAT_CACTUS_MEMCPY_BASE +#define MEMPCY_TOTAL_SIZE (PLAT_CACTUS_MEMCPY_RANGE / 2) +#define MEMCPY_TARGET_BASE (MEMCPY_SOURCE_BASE + MEMPCY_TOTAL_SIZE) + +/* Miscellaneous */ +#define NO_SUBSTREAMID (0xFFFFFFFFU) +#define TRANSFER_SIZE (MEMPCY_TOTAL_SIZE / FRAME_COUNT) +#define LOOP_COUNT (5000U) + +static bool run_smmuv3_test(void) +{ + uint64_t source_addr, cpy_range, target_addr; + uint64_t begin_addr, end_addr, dest_addr; + uint32_t status; + unsigned int i, f, attempts; + + /* + * The test engine's MEMCPY command copies data from the region in + * range [begin, end_incl] to the region with base address as udata. + * In this test, we configure the test engine to initiate memcpy from + * scratch page located at MEMCPY_SOURCE_BASE to the page located at + * address MEMCPY_TARGET_BASE + */ + + VERBOSE("CACTUS: Running SMMUv3 test\n"); + + source_addr = MEMCPY_SOURCE_BASE; + cpy_range = MEMPCY_TOTAL_SIZE; + target_addr = MEMCPY_TARGET_BASE; + uint32_t streamID_list[] = { 0U, 1U }; + + uint64_t data[] = { + ULL(0xBAADFEEDCEEBDAAF), + ULL(0x0123456776543210) + }; + + /* Write pre-determined content to source pages */ + for (i = 0U; i < (cpy_range / 8U); i++) { + mmio_write64_offset(source_addr, i * 8, data[i%2]); + } + + /* Clean the data caches */ + clean_dcache_range(source_addr, cpy_range); + + /* + * Make sure above load, store and cache maintenance instructions + * complete before we start writing to TestEngine frame configuration + * fields + */ + dsbsy(); + + for (f = 0U; f < FRAME_COUNT; f++) { + attempts = 0U; + begin_addr = source_addr + (TRANSFER_SIZE * f); + end_addr = begin_addr + TRANSFER_SIZE - 1U; + dest_addr = target_addr + (TRANSFER_SIZE * f); + + /* Initiate DMA sequence */ + mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), PCTRL_OFF, 0); + mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), DOWNSTREAM_PORT_OFF, 0); + mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), STREAM_ID_OFF, streamID_list[f%2]); + mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), SUBSTREAM_ID_OFF, NO_SUBSTREAMID); + + mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), UCTRL_OFF, 0); + mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), SEED_OFF, 0); + mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), BEGIN_OFF, begin_addr); + mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), END_CTRL_OFF, end_addr); + + /* Legal values for stride: 1 and any multiples of 8 */ + mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), STRIDE_OFF, 1); + mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), UDATA_OFF, dest_addr); + + mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF, ENGINE_MEMCPY); + VERBOSE("SMMUv3TestEngine: Waiting for MEMCPY completion for frame: %u\n", f); + + /* + * It is guaranteed that a read of "cmd" fields after writing to it will + * immediately return ENGINE_FRAME_MISCONFIGURED if the command was + * invalid. + */ + if (mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF) == ENGINE_MIS_CFG) { + ERROR("SMMUv3TestEngine: Misconfigured for frame: %u\n", f); + return false; + } + + /* Wait for mem copy to be complete */ + while (attempts++ < LOOP_COUNT) { + status = mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF); + if (status == ENGINE_HALTED) { + break; + } else if (status == ENGINE_ERROR) { + ERROR("SMMUv3: Test failed\n"); + return false; + } + + /* + * TODO: Introduce a small delay here to make sure the + * CPU memory accesses do not starve the interconnect + * due to continuous polling. + */ + } + + if (attempts == LOOP_COUNT) { + ERROR("SMMUv3: Test failed\n"); + return false; + } + + dsbsy(); + } + + /* + * Invalidate cached entries to force the CPU to fetch the data from + * Main memory + */ + inv_dcache_range(source_addr, cpy_range); + inv_dcache_range(target_addr, cpy_range); + + /* Compare source and destination memory locations for data */ + for (i = 0U; i < (cpy_range / 8U); i++) { + if (mmio_read_64(source_addr + 8 * i) != mmio_read_64(target_addr + 8 * i)) { + ERROR("SMMUv3: Mem copy failed: %llx\n", target_addr + 8 * i); + return false; + } + } + + return true; +} + +CACTUS_CMD_HANDLER(smmuv3_cmd, CACTUS_DMA_SMMUv3_CMD) +{ + smc_ret_values ffa_ret; + ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args); + ffa_vm_id_t source = ffa_dir_msg_source(*args); + + VERBOSE("Received request through direct message for DMA service\n"); + + /* + * At present, the test cannot be run concurrently on multiple SPs as + * there is only one SMMUv3TestEngine IP in the FVP model. Hence, run + * the test only on the first SP. + */ + if (vm_id != SPM_VM_ID_FIRST) { + return cactus_error_resp(vm_id, source, 0); + } + + if (run_smmuv3_test()) { + ffa_ret = cactus_success_resp(vm_id, source, 0); + } else { + ffa_ret = cactus_error_resp(vm_id, source, 0); + } + + return ffa_ret; +} diff --git a/spm/cactus/cactus_tests/smmuv3_test_engine.h b/spm/cactus/cactus_tests/smmuv3_test_engine.h new file mode 100644 index 000000000..32d86ac9c --- /dev/null +++ b/spm/cactus/cactus_tests/smmuv3_test_engine.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* The test engine supports numerous frames but we only use a few */ +#define FRAME_COUNT (2U) +#define FRAME_SIZE (0x80U) /* 128 bytes */ +#define F_IDX(n) (n * FRAME_SIZE) + +/* Commands supported by SMMUv3TestEngine built into the AEM */ +#define ENGINE_NO_FRAME (0U) +#define ENGINE_HALTED (1U) + +/* + * ENGINE_MEMCPY: Read and Write transactions + * ENGINE_RAND48: Only Write transactions: Source address not required + * ENGINE_SUM64: Only read transactions: Target address not required + */ +#define ENGINE_MEMCPY (2U) +#define ENGINE_RAND48 (3U) +#define ENGINE_SUM64 (4U) +#define ENGINE_ERROR (0xFFFFFFFFU) +#define ENGINE_MIS_CFG (ENGINE_ERROR - 1) + +/* + * Refer to: + * https://developer.arm.com/documentation/100964/1111-00/Trace-components/SMMUv3TestEngine---trace + */ + +/* Offset of various control fields belonging to User Frame */ +#define CMD_OFF (0x0U) +#define UCTRL_OFF (0x4U) +#define SEED_OFF (0x24U) +#define BEGIN_OFF (0x28U) +#define END_CTRL_OFF (0x30U) +#define STRIDE_OFF (0x38U) +#define UDATA_OFF (0x40U) + +/* Offset of various control fields belonging to PRIV Frame */ +#define PCTRL_OFF (0x0U) +#define DOWNSTREAM_PORT_OFF (0x4U) +#define STREAM_ID_OFF (0x8U) +#define SUBSTREAM_ID_OFF (0xCU) diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts index eb569f7a1..1c28fde49 100644 --- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts +++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts @@ -62,6 +62,24 @@ pages-count = <4>; attributes = <0x7>; /* read-write-execute */ }; + + /* + * Scratch memory used for the purpose of testing SMMUv3 driver + * through Cactus SP + */ + smmuv3-memcpy-src { + description = "smmuv3-memcpy-source"; + pages-count = <4>; + base-address = <0x00000000 0x7400000>; + attributes = <0x3>; /* read-write */ + }; + + smmuv3-memcpy-dst { + description = "smmuv3-memcpy-destination"; + pages-count = <4>; + base-address = <0x00000000 0x7404000>; + attributes = <0x3>; /* read-write */ + }; }; device-regions { @@ -73,6 +91,20 @@ attributes = <0x3>; /* read-write */ }; + smmuv3-testengine { + /* + * SMMUv3TestEngine is a DMA IP modeled in the + * Base-RevC FVP Model. + * User Frame: 0x2bfe0000 + * Privileged Frame: 0x2bff0000 + */ + base-address = <0x00000000 0x2bfe0000>; + pages-count = <32>; /* Two 64KB pages */ + attributes = <0x3>; /* read-write */ + smmu-id = <0>; + stream-ids = <0x0 0x1>; + }; + test-reg { /* Dummy Values */ base-address = <0x00000000 0x22000000>; diff --git a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h index b4c57efed..8940c83f5 100644 --- a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h +++ b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,8 +18,16 @@ #define PLAT_CACTUS_RX_BASE ULL(0x7300000) #define PLAT_CACTUS_CORE_COUNT (8U) +/* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */ +#define PLAT_CACTUS_MEMCPY_BASE ULL(0x7400000) +#define PLAT_CACTUS_MEMCPY_RANGE ULL(0x8000) + #define CACTUS_PRIMARY_EC_COUNT (8U) #define CACTUS_SECONDARY_EC_COUNT (8U) #define CACTUS_TERTIARY_EC_COUNT (1U) +/* Base address of user and PRIV frames in SMMUv3TestEngine */ +#define USR_BASE_FRAME ULL(0x2BFE0000) +#define PRIV_BASE_FRAME ULL(0x2BFF0000) + #endif /* CACTUS_PLATFORM_DEF_H */ diff --git a/tftf/tests/runtime_services/secure_service/test_spm_smmu.c b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c new file mode 100644 index 000000000..b041a976c --- /dev/null +++ b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <cactus_test_cmds.h> +#include <debug.h> +#include <ffa_endpoints.h> +#include <smccc.h> +#include <test_helpers.h> + +static const struct ffa_uuid expected_sp_uuids[] = { {PRIMARY_UUID} }; + +/************************************************************************** + * Send a command to SP1 initiate DMA service with the help of a peripheral + * device upstream of an SMMUv3 IP + **************************************************************************/ +test_result_t test_smmu_spm(void) +{ + smc_ret_values ret; + + /********************************************************************** + * Check SPMC has ffa_version and expected FFA endpoints are deployed. + **********************************************************************/ + CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids); + + VERBOSE("Sending command to SP %x for initiating DMA transfer\n", + SP_ID(1)); + ret = cactus_send_dma_cmd(HYP_ID, SP_ID(1)); + + if (cactus_get_response(ret) != CACTUS_SUCCESS) { + return TEST_RESULT_FAIL; + } + + return TEST_RESULT_SUCCESS; +} + diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk index 9364052b6..e62e03d94 100644 --- a/tftf/tests/tests-spm.mk +++ b/tftf/tests/tests-spm.mk @@ -15,4 +15,5 @@ TESTS_SOURCES += \ test_ffa_rxtx_map.c \ test_ffa_version.c \ test_spm_cpu_features.c \ + test_spm_smmu.c \ ) diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml index 01ebceab2..32efc161b 100644 --- a/tftf/tests/tests-spm.xml +++ b/tftf/tests/tests-spm.xml @@ -84,4 +84,9 @@ function="test_ffa_ns_interrupt" /> </testsuite> + <testsuite name="SMMUv3 tests" + description="Initiate stage2 translation for streams from upstream peripherals" > + <testcase name="Check DMA command by SMMUv3TestEngine completes" + function="test_smmu_spm" /> + </testsuite> </testsuites> |