aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2018-11-16 14:00:40 +0100
committerSandrine Bailleux <sandrine.bailleux@arm.com>2019-01-03 10:51:21 +0100
commit3f556ebf53fb3c25eb1e85110643a593e5fe5d26 (patch)
tree1986260a41935607f45ec86213fee4c5206ec737
parent1779506e5be07e4e136d35b75d2672680067fdb6 (diff)
downloadtf-a-tests-3f556ebf53fb3c25eb1e85110643a593e5fe5d26.tar.gz
Add some tests for all types of SMCs
Exercise all combinations of SMCs: fast or yielding, SMC32 or SMC64 calling convention, from a 32-bit caller or a 64-bit one. Change-Id: I6d23549818db7f1b3fd0cb4b46e5a592b04b5289 Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
-rw-r--r--tftf/tests/runtime_services/generic/generic_smc.c227
-rw-r--r--tftf/tests/tests-smc.mk7
-rw-r--r--tftf/tests/tests-smc.xml19
-rw-r--r--tftf/tests/tests-standard.mk1
-rw-r--r--tftf/tests/tests-standard.xml2
5 files changed, 256 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/generic/generic_smc.c b/tftf/tests/runtime_services/generic/generic_smc.c
new file mode 100644
index 00000000..901b4481
--- /dev/null
+++ b/tftf/tests/runtime_services/generic/generic_smc.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <psci.h>
+#include <smccc.h>
+#include <std_svc.h>
+#include <string.h>
+#include <tftf_lib.h>
+#include <tsp.h>
+#include <utils_def.h>
+
+/* An invalid SMC function number. */
+#define INVALID_FN 0x666
+
+/* PSCI version returned by TF-A. */
+static const uint32_t psci_version = PSCI_VERSION(PSCI_MAJOR_VER,
+ PSCI_MINOR_VER);
+
+/* UUID of the standard service in TF-A. */
+static const smc_ret_values std_svc_uuid = {
+ 0x108d905b, 0x47e8f863, 0xfbc02dae, 0xe2f64156
+};
+
+/*
+ * Build an SMC function ID given its type (fast/yielding), calling convention,
+ * owning entity number and function number.
+ */
+static inline uint32_t make_smc_fid(unsigned int type, unsigned int cc,
+ unsigned int oen, unsigned int func_num)
+{
+ return (type << FUNCID_TYPE_SHIFT) | (cc << FUNCID_CC_SHIFT)
+ | (oen << FUNCID_OEN_SHIFT) | (func_num << FUNCID_NUM_SHIFT);
+}
+
+/* Exit the test if the specified condition holds true. */
+#define FAIL_IF(_cond) \
+ do { \
+ if ((_cond)) { \
+ return TEST_RESULT_FAIL; \
+ } \
+ } while (0)
+
+/*
+ * Send an SMC with the specified arguments.
+ * Check that the values it returns match the expected ones. If not, write an
+ * error message in the test report.
+ */
+static bool smc_check_eq(const smc_args *args, const smc_ret_values *expect)
+{
+ smc_ret_values ret = tftf_smc(args);
+
+ if (memcmp(&ret, expect, sizeof(smc_ret_values)) == 0) {
+ return true;
+ } else {
+ tftf_testcase_printf(
+ "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {0x%lx,0x%lx,0x%lx,0x%lx}.\n",
+ ret.ret0, ret.ret1, ret.ret2, ret.ret3,
+ expect->ret0, expect->ret1, expect->ret2, expect->ret3);
+ return false;
+ }
+}
+
+/* Exercise SMC32 calling convention with fast SMC calls. */
+test_result_t smc32_fast(void)
+{
+ /* Valid Fast SMC32 using all 4 return values. */
+ const smc_args args1 = { .fid = SMC_STD_SVC_UID };
+ FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+
+ /* Invalid Fast SMC32. */
+ const smc_args args2 = {
+ make_smc_fid(SMC_TYPE_FAST, SMC_32, OEN_ARM_START, INVALID_FN),
+ 0x11111111, 0x22222222, 0x33333333 };
+ const smc_ret_values ret2
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ FAIL_IF(!smc_check_eq(&args2, &ret2));
+
+ /* Valid Fast SMC32 using 1 return value. */
+ const smc_args args3
+ = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666 };
+ const smc_ret_values ret3
+ = { psci_version, 0x44444444, 0x55555555, 0x66666666 };
+ FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+ return TEST_RESULT_SUCCESS;
+}
+
+/* Exercise SMC64 calling convention with yielding SMC calls. */
+test_result_t smc64_yielding(void)
+{
+ /* Valid Fast SMC32 using all 4 return values. */
+ const smc_args args1 = { .fid = SMC_STD_SVC_UID };
+ FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+
+ /* Invalid function number, SMC64 Yielding. */
+ const smc_args args2 = {
+ make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_ARM_START, INVALID_FN),
+ 0x11111111, 0x22222222, 0x33333333 };
+ const smc_ret_values ret2
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ FAIL_IF(!smc_check_eq(&args2, &ret2));
+
+ /*
+ * Valid[1] yielding SMC64 using 1 return value.
+ *
+ * [1] Valid from the point of view of the generic SMC handler if the
+ * TSPd is present. In this case, the SMC request gets passed to the
+ * TSPd handler code. The fact that it then gets rejected by the TSPd is
+ * irrelevant here, as we are not trying to test the TSPd nor the TSP.
+ *
+ * In other cases (i.e. AArch64 BL31 with no TSPd support or AArch32
+ * SP_MIN) this test should still fail in the same way, although it
+ * doesn't exercise the same code path in TF-A.
+ */
+ const smc_args args3 = {
+ make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN),
+ 0x44444444, 0x55555555, 0x66666666 };
+ const smc_ret_values ret3
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+ return TEST_RESULT_SUCCESS;
+}
+
+#ifdef AARCH32
+static test_result_t smc64_fast_caller32(void)
+{
+ /* Valid Fast SMC32 using all 4 return values. */
+ smc_args args1 = { .fid = SMC_STD_SVC_UID };
+ FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+
+ /* Invalid SMC function number, Fast SMC64. */
+ const smc_args args2 = {
+ make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
+ 0x11111111, 0x22222222, 0x33333333 };
+ const smc_ret_values ret2
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ FAIL_IF(!smc_check_eq(&args2, &ret2));
+
+ /*
+ * Valid SMC function number, Fast SMC64. However, 32-bit callers are
+ * forbidden to use the SMC64 calling convention.
+ */
+ const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
+ 0x44444444, 0x55555555, 0x66666666 };
+ const smc_ret_values ret3
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+ return TEST_RESULT_SUCCESS;
+}
+#else
+static test_result_t smc64_fast_caller64(void)
+{
+ /* Valid Fast SMC32 using all 4 return values. */
+ smc_args args1 = { .fid = SMC_STD_SVC_UID };
+ FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+
+ /* Invalid function number, Fast SMC64. */
+ const smc_args args2 = {
+ make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
+ 0x11111111, 0x22222222, 0x33333333 };
+ const smc_ret_values ret2
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ FAIL_IF(!smc_check_eq(&args2, &ret2));
+
+ /* Valid Fast SMC64 using 1 return value. */
+ const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
+ 0x44444444, 0x55555555, 0x66666666 };
+ const smc_ret_values ret3
+ = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666 };
+ FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+ return TEST_RESULT_SUCCESS;
+}
+#endif /* AARCH32 */
+
+/* Exercise SMC64 calling convention with fast SMC calls. */
+test_result_t smc64_fast(void)
+{
+#ifdef AARCH32
+ return smc64_fast_caller32();
+#else
+ return smc64_fast_caller64();
+#endif
+}
+
+/* Exercise SMC32 calling convention with yielding SMC calls. */
+test_result_t smc32_yielding(void)
+{
+ /* Valid Fast SMC32 using all 4 return values. */
+ const smc_args args1 = { .fid = SMC_STD_SVC_UID };
+ FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+
+ /* Invalid function number, SMC32 Yielding. */
+ const smc_args args2 = {
+ make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_ARM_START, INVALID_FN),
+ 0x11111111, 0x22222222, 0x33333333 };
+ const smc_ret_values ret2
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ FAIL_IF(!smc_check_eq(&args2, &ret2));
+
+ /*
+ * Valid[1] yielding SMC32 using 1 return value.
+ *
+ * [1] Valid from the point of view of the generic SMC handler if a
+ * secure payload dispatcher handling this SMC range is present. In this
+ * case, the SMC request gets passed to the dispatcher handler code. The
+ * fact that it then gets rejected by the dispatcher is irrelevant here,
+ * as we are not trying to test the dispatcher nor the secure payload.
+ *
+ * In BL31 has no SPD support, this test should still fail in the same
+ * way, although it doesn't exercise the same code path in TF-A.
+ */
+ const smc_args args3 = {
+ make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN),
+ 0x44444444, 0x55555555, 0x66666666 };
+ const smc_ret_values ret3
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+ return TEST_RESULT_SUCCESS;
+}
+
diff --git a/tftf/tests/tests-smc.mk b/tftf/tests/tests-smc.mk
new file mode 100644
index 00000000..8496cd1d
--- /dev/null
+++ b/tftf/tests/tests-smc.mk
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES += tftf/tests/runtime_services/generic/generic_smc.c
diff --git a/tftf/tests/tests-smc.xml b/tftf/tests/tests-smc.xml
new file mode 100644
index 00000000..56f987dd
--- /dev/null
+++ b/tftf/tests/tests-smc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2018, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+ <testsuite name="SMC calling convention"
+ description="Test different flavours of the SMC calling convention">
+ <testcase name="Fast SMC32" function="smc32_fast" />
+ <testcase name="Fast SMC64" function="smc64_fast" />
+ <testcase name="Yielding SMC32" function="smc32_yielding" />
+ <testcase name="Yielding SMC64" function="smc64_yielding" />
+ </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-standard.mk b/tftf/tests/tests-standard.mk
index c4d35c60..72c2ec0d 100644
--- a/tftf/tests/tests-standard.mk
+++ b/tftf/tests/tests-standard.mk
@@ -16,6 +16,7 @@ TESTS_MAKEFILE := $(addprefix tftf/tests/, \
tests-runtime-instrumentation.mk \
tests-sdei.mk \
tests-single-fault.mk \
+ tests-smc.mk \
tests-spm.mk \
tests-template.mk \
tests-tftf-validation.mk \
diff --git a/tftf/tests/tests-standard.xml b/tftf/tests/tests-standard.xml
index e2a1a2bd..a1323d55 100644
--- a/tftf/tests/tests-standard.xml
+++ b/tftf/tests/tests-standard.xml
@@ -19,6 +19,7 @@
<!ENTITY tests-state-switch SYSTEM "tests-arm-state-switch.xml">
<!ENTITY tests-cpu-extensions SYSTEM "tests-cpu-extensions.xml">
<!ENTITY tests-performance SYSTEM "tests-performance.xml">
+ <!ENTITY tests-smc SYSTEM "tests-smc.xml">
]>
<testsuites>
@@ -33,5 +34,6 @@
&tests-state-switch;
&tests-cpu-extensions;
&tests-performance;
+ &tests-smc;
</testsuites>