diff options
author | Dimitris Papastamos <dimitris.papastamos@arm.com> | 2018-03-16 10:51:43 +0000 |
---|---|---|
committer | Dimitris Papastamos <dimitris.papastamos@arm.com> | 2018-03-19 14:05:44 +0000 |
commit | a0d9ef5c54fb8ed43967b5a871346c635c6e6886 (patch) | |
tree | 257a4f8d4d8f4112b8bab2f2ed67a655f18e44c8 | |
parent | 90d54fce5f4c2ed0ab4de290e2c47f9093d998b2 (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.h | 4 | ||||
-rw-r--r-- | tests/runtime_services/arm_arch_svc/arm_arch_svc.c | 172 | ||||
-rw-r--r-- | tests/tests-cpu-extensions.xml | 4 | ||||
-rw-r--r-- | tests/tests.mk | 1 |
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 \ |