summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitris Papastamos <dimitris.papastamos@arm.com>2018-03-16 10:51:43 +0000
committerDimitris Papastamos <dimitris.papastamos@arm.com>2018-03-19 14:05:44 +0000
commita0d9ef5c54fb8ed43967b5a871346c635c6e6886 (patch)
tree257a4f8d4d8f4112b8bab2f2ed67a655f18e44c8
parent90d54fce5f4c2ed0ab4de290e2c47f9093d998b2 (diff)
Add SMCCC v1.2 test case
Change-Id: I3af1aded9f42344874cd1f0bd5140db22d74ad26 Signed-off-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
-rw-r--r--include/lib/aarch64/arch.h4
-rw-r--r--tests/runtime_services/arm_arch_svc/arm_arch_svc.c172
-rw-r--r--tests/tests-cpu-extensions.xml4
-rw-r--r--tests/tests.mk1
4 files changed, 181 insertions, 0 deletions
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index a2c0fc8..560bcf5 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -132,6 +132,10 @@
#define ID_AA64PFR0_GIC_WIDTH 4
#define ID_AA64PFR0_GIC_MASK ((1 << ID_AA64PFR0_GIC_WIDTH) - 1)
+#define ID_AA64PFR0_CSV2_SHIFT 56
+#define ID_AA64PFR0_CSV2_LENGTH 4
+#define ID_AA64PFR0_CSV2_MASK 0xf
+
/* ID_PFR1_EL1 definitions */
#define ID_PFR1_VIRTEXT_SHIFT 12
#define ID_PFR1_VIRTEXT_MASK 0xf
diff --git a/tests/runtime_services/arm_arch_svc/arm_arch_svc.c b/tests/runtime_services/arm_arch_svc/arm_arch_svc.c
new file mode 100644
index 0000000..64c26c9
--- /dev/null
+++ b/tests/runtime_services/arm_arch_svc/arm_arch_svc.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_arch_svc.h>
+#include <debug.h>
+#include <plat_topology.h>
+#include <power_management.h>
+#include <psci.h>
+#include <smc.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+#ifdef AARCH64
+#define CORTEX_A57_MIDR 0x410FD070
+#define CORTEX_A72_MIDR 0x410FD080
+#define CORTEX_A73_MIDR 0x410FD090
+#define CORTEX_A75_MIDR 0x410FD0A0
+
+static int cortex_a57_test(void);
+static int csv2_test(void);
+
+static struct ent {
+ unsigned int midr;
+ int (*wa_required)(void);
+} entries[] = {
+ { .midr = CORTEX_A57_MIDR, .wa_required = cortex_a57_test },
+ { .midr = CORTEX_A72_MIDR, .wa_required = csv2_test },
+ { .midr = CORTEX_A73_MIDR, .wa_required = csv2_test },
+ { .midr = CORTEX_A75_MIDR, .wa_required = csv2_test },
+};
+
+static int cortex_a57_test(void)
+{
+ return 1;
+}
+
+static int csv2_test(void)
+{
+ uint64_t pfr0;
+
+ pfr0 = read_id_aa64pfr0_el1() >> ID_AA64PFR0_CSV2_SHIFT;
+ if ((pfr0 & ID_AA64PFR0_CSV2_MASK) == 1)
+ return 0;
+ return 1;
+}
+
+static test_result_t test_smccc_entrypoint(void)
+{
+ smc_args args;
+ smc_ret_values ret;
+ int32_t expected_ver;
+ unsigned int my_midr, midr_mask;
+ int wa_required;
+ size_t i;
+
+ /* Check if SMCCC version is at least v1.1 */
+ expected_ver = MAKE_SMCCC_VERSION(1, 1);
+ memset(&args, 0, sizeof(args));
+ args.arg0 = SMCCC_VERSION;
+ ret = tftf_smc(&args);
+ if ((int32_t)ret.ret0 < expected_ver) {
+ tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
+ (int)ret.ret0);
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* Check if SMCCC_ARCH_WORKAROUND_1 is required or not */
+ memset(&args, 0, sizeof(args));
+ args.arg0 = SMCCC_ARCH_FEATURES;
+ args.arg1 = SMCCC_ARCH_WORKAROUND_1;
+ ret = tftf_smc(&args);
+ if ((int)ret.ret0 == -1) {
+ tftf_testcase_printf("SMCCC_ARCH_WORKAROUND_1 is not implemented\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* If the call returns 0, it means the workaround is required */
+ if ((int)ret.ret0 == 0)
+ wa_required = 1;
+ else
+ wa_required = 0;
+
+ /* Check if the SMC return value matches our expectations */
+ my_midr = (unsigned int)read_midr_el1();
+ midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
+ (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ for (i = 0; i < ARRAY_SIZE(entries); i++) {
+ struct ent *entp = &entries[i];
+
+ if ((my_midr & midr_mask) == (entp->midr & midr_mask)) {
+ if (entp->wa_required() != wa_required)
+ return TEST_RESULT_FAIL;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(entries) && wa_required) {
+ tftf_testcase_printf("TFTF workaround table out of sync with TF\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Invoke the workaround to make sure nothing nasty happens */
+ memset(&args, 0, sizeof(args));
+ args.arg0 = SMCCC_ARCH_WORKAROUND_1;
+ tftf_smc(&args);
+ return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_arm_arch_svc(void)
+{
+ u_register_t lead_mpid, target_mpid;
+ int cpu_node, ret;
+
+ lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+ /* Power on all the non-lead cores. */
+ for_each_cpu(cpu_node) {
+ target_mpid = tftf_get_mpidr_from_node(cpu_node);
+ if (lead_mpid == target_mpid)
+ continue;
+ ret = tftf_cpu_on(target_mpid,
+ (uintptr_t)test_smccc_entrypoint, 0);
+ if (ret != PSCI_E_SUCCESS) {
+ ERROR("CPU ON failed for 0x%llx\n",
+ (unsigned long long)target_mpid);
+ return TEST_RESULT_FAIL;
+ }
+ /*
+ * Wait for test_smccc_entrypoint to return
+ * and the CPU to power down
+ */
+ while (tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL0) !=
+ PSCI_STATE_OFF)
+ continue;
+ }
+
+ return test_smccc_entrypoint();
+}
+#else
+test_result_t test_arm_arch_svc(void)
+{
+ INFO("%s skipped on AArch32\n", __func__);
+ return TEST_RESULT_SKIPPED;
+}
+#endif
diff --git a/tests/tests-cpu-extensions.xml b/tests/tests-cpu-extensions.xml
index e89b92d..ba76460 100644
--- a/tests/tests-cpu-extensions.xml
+++ b/tests/tests-cpu-extensions.xml
@@ -19,4 +19,8 @@
<testcase name="AMUv1 suspend/resume" function="test_amu_suspend_resume" />
</testsuite>
+ <testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">
+ <testcase name="SMCCC v1.2 test" function="test_arm_arch_svc" />
+ </testsuite>
+
</testsuites>
diff --git a/tests/tests.mk b/tests/tests.mk
index 085fcad..24f2316 100644
--- a/tests/tests.mk
+++ b/tests/tests.mk
@@ -11,6 +11,7 @@ TESTS_SOURCES := tests/extensions/amu/test_amu.c \
tests/framework_validation_tests/test_validation_nvm.c \
tests/framework_validation_tests/test_validation_sgi.c \
tests/performance_tests/smc_latencies.c \
+ tests/runtime_services/arm_arch_svc/arm_arch_svc.c \
tests/runtime_services/secure_service/legacy/test_secure_service_handle.c \
tests/runtime_services/secure_service/legacy/test_secure_service_interrupts.c \
tests/runtime_services/secure_service/secure_service_helpers.c \