aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMadhukar Pappireddy <madhukar.pappireddy@arm.com>2020-12-31 19:25:33 -0600
committerMadhukar Pappireddy <madhukar.pappireddy@arm.com>2021-04-30 09:31:53 -0500
commit172523b9ceadd0af9f6e8e4fb899cc7f354ff002 (patch)
treeef3d02c2953b208aa5e1c84a23bc58a117f27e9a
parentc5b60fce76bd56739c909fa0d5ac53d482171c88 (diff)
downloadtf-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.h19
-rw-r--r--include/runtime_services/cactus_test_cmds.h13
-rw-r--r--plat/arm/fvp/include/platform_def.h6
-rw-r--r--spm/cactus/cactus.mk1
-rw-r--r--spm/cactus/cactus_main.c3
-rw-r--r--spm/cactus/cactus_tests/cactus_tests_smmuv3.c175
-rw-r--r--spm/cactus/cactus_tests/smmuv3_test_engine.h45
-rw-r--r--spm/cactus/plat/arm/fvp/fdts/cactus.dts32
-rw-r--r--spm/cactus/plat/arm/fvp/include/cactus_platform_def.h10
-rw-r--r--tftf/tests/runtime_services/secure_service/test_spm_smmu.c38
-rw-r--r--tftf/tests/tests-spm.mk1
-rw-r--r--tftf/tests/tests-spm.xml5
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>