diff options
Diffstat (limited to 'tftf/tests/runtime_services/mm_service/test_secure_service_handle.c')
-rw-r--r-- | tftf/tests/runtime_services/mm_service/test_secure_service_handle.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/mm_service/test_secure_service_handle.c b/tftf/tests/runtime_services/mm_service/test_secure_service_handle.c new file mode 100644 index 000000000..ce4dd5c2a --- /dev/null +++ b/tftf/tests/runtime_services/mm_service/test_secure_service_handle.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <debug.h> +#include <events.h> +#include <mm_svc.h> +#include <plat_topology.h> +#include <platform.h> +#include <power_management.h> +#include <secure_partition.h> +#include <smccc.h> +#include <spm_svc.h> +#include <test_helpers.h> +#include <tftf_lib.h> +#include <xlat_tables_v2.h> + +static event_t cpu_has_finished_test[PLATFORM_CORE_COUNT]; + +/* Test routine for test_secure_partition_secondary_cores_seq() */ +static test_result_t test_secure_partition_secondary_cores_seq_fn(void) +{ + test_result_t result = TEST_RESULT_SUCCESS; + u_register_t cpu_mpid = read_mpidr_el1() & MPID_MASK; + unsigned int core_pos = platform_get_core_pos(cpu_mpid); + + secure_partition_request_info_t *sps_request = + create_sps_request(SPS_CHECK_ALIVE, NULL, 0); + + INFO("Sending MM_COMMUNICATE_AARCH64 from CPU %u\n", + platform_get_core_pos(read_mpidr_el1() & MPID_MASK)); + + smc_args mm_communicate_smc = { + MM_COMMUNICATE_AARCH64, + 0, + (u_register_t) sps_request, + 0 + }; + + smc_ret_values smc_ret = tftf_smc(&mm_communicate_smc); + + if ((uint32_t)smc_ret.ret0 != 0) { + tftf_testcase_printf("Cactus returned: 0x%x\n", + (uint32_t)smc_ret.ret0); + + result = TEST_RESULT_FAIL; + } + + tftf_send_event(&cpu_has_finished_test[core_pos]); + + return result; +} + +/* + * @Test_Aim@ This tests that secondary CPUs can access SPM services + * sequentially. + */ +test_result_t test_secure_partition_secondary_cores_seq(void) +{ + int psci_ret; + u_register_t lead_mpid, cpu_mpid; + unsigned int cpu_node, core_pos; + test_result_t result = TEST_RESULT_SUCCESS; + + SKIP_TEST_IF_LESS_THAN_N_CPUS(2); + + SKIP_TEST_IF_MM_VERSION_LESS_THAN(1, 0); + + VERBOSE("Mapping NS<->SP shared buffer\n"); + + int rc = mmap_add_dynamic_region(ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_SIZE, + MT_MEMORY | MT_RW | MT_NS); + if (rc != 0) { + tftf_testcase_printf("%d: mmap_add_dynamic_region() = %d\n", + __LINE__, rc); + result = TEST_RESULT_FAIL; + goto exit; + } + + lead_mpid = read_mpidr_el1() & MPID_MASK; + + INFO("Lead CPU is CPU %u\n", platform_get_core_pos(lead_mpid)); + + if (test_secure_partition_secondary_cores_seq_fn() != TEST_RESULT_SUCCESS) { + result = TEST_RESULT_FAIL; + goto exit_unmap; + } + + for_each_cpu(cpu_node) { + cpu_mpid = tftf_get_mpidr_from_node(cpu_node); + /* Skip lead CPU, we have already tested it */ + if (cpu_mpid == lead_mpid) { + continue; + } + + core_pos = platform_get_core_pos(cpu_mpid); + + tftf_init_event(&cpu_has_finished_test[core_pos]); + + VERBOSE("Powering on CPU %u\n", core_pos); + + psci_ret = tftf_cpu_on(cpu_mpid, + (uintptr_t)test_secure_partition_secondary_cores_seq_fn, 0); + if (psci_ret != PSCI_E_SUCCESS) { + tftf_testcase_printf( + "Failed to power on CPU %d (rc = %d)\n", + core_pos, psci_ret); + result = TEST_RESULT_FAIL; + goto exit_unmap; + } + + tftf_wait_for_event(&cpu_has_finished_test[core_pos]); + } + +exit_unmap: + VERBOSE("Unmapping NS<->SP shared buffer\n"); + + mmap_remove_dynamic_region(ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_SIZE); + +exit: + return result; +} + +/******************************************************************************/ + +static event_t cpu_can_start_test[PLATFORM_CORE_COUNT]; + +/* Test routine for test_secure_partition_secondary_core() */ +static test_result_t test_secure_partition_secondary_cores_sim_fn(void) +{ + test_result_t result = TEST_RESULT_SUCCESS; + u_register_t cpu_mpid = read_mpidr_el1() & MPID_MASK; + unsigned int core_pos = platform_get_core_pos(cpu_mpid); + + secure_partition_request_info_t *sps_request = + create_sps_request(SPS_CHECK_ALIVE, NULL, 0); + + smc_args mm_communicate_smc = { + MM_COMMUNICATE_AARCH64, + 0, + (u_register_t) sps_request, + 0 + }; + + tftf_wait_for_event(&cpu_can_start_test[core_pos]); + + /* + * Invoke SMCs for some time to make sure that all CPUs are doing it at + * the same time during the test. + */ + for (int i = 0; i < 100; i++) { + smc_ret_values smc_ret = tftf_smc(&mm_communicate_smc); + + if ((uint32_t)smc_ret.ret0 != 0) { + tftf_testcase_printf("Cactus returned 0x%x at CPU %d\n", + (uint32_t)smc_ret.ret0, core_pos); + result = TEST_RESULT_FAIL; + break; + } + } + + tftf_send_event(&cpu_has_finished_test[core_pos]); + + return result; +} + +/* + * @Test_Aim@ This tests that secondary CPUs can access SPM services + * simultaneously. + */ +test_result_t test_secure_partition_secondary_cores_sim(void) +{ + int psci_ret; + u_register_t lead_mpid, cpu_mpid; + unsigned int cpu_node, core_pos; + test_result_t result = TEST_RESULT_SUCCESS; + + SKIP_TEST_IF_LESS_THAN_N_CPUS(2); + + SKIP_TEST_IF_MM_VERSION_LESS_THAN(1, 0); + + VERBOSE("Mapping NS<->SP shared buffer\n"); + + int rc = mmap_add_dynamic_region(ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_SIZE, + MT_MEMORY | MT_RW | MT_NS); + if (rc != 0) { + tftf_testcase_printf("%d: mmap_add_dynamic_region() = %d\n", + __LINE__, rc); + result = TEST_RESULT_FAIL; + goto exit; + } + + lead_mpid = read_mpidr_el1() & MPID_MASK; + + INFO("Lead CPU is CPU %u\n", platform_get_core_pos(lead_mpid)); + + for_each_cpu(cpu_node) { + cpu_mpid = tftf_get_mpidr_from_node(cpu_node); + core_pos = platform_get_core_pos(cpu_mpid); + tftf_init_event(&cpu_can_start_test[core_pos]); + } + + for_each_cpu(cpu_node) { + cpu_mpid = tftf_get_mpidr_from_node(cpu_node); + /* Skip lead CPU as it is already powered on */ + if (cpu_mpid == lead_mpid) { + continue; + } + + core_pos = platform_get_core_pos(cpu_mpid); + + VERBOSE("Powering on CPU %u\n", core_pos); + + psci_ret = tftf_cpu_on(cpu_mpid, + (uintptr_t)test_secure_partition_secondary_cores_sim_fn, 0); + if (psci_ret != PSCI_E_SUCCESS) { + tftf_testcase_printf( + "Failed to power on CPU %d (rc = %d)\n", + core_pos, psci_ret); + result = TEST_RESULT_FAIL; + goto exit_unmap; + } + } + + for_each_cpu(cpu_node) { + cpu_mpid = tftf_get_mpidr_from_node(cpu_node); + core_pos = platform_get_core_pos(cpu_mpid); + tftf_send_event(&cpu_can_start_test[core_pos]); + } + + result = test_secure_partition_secondary_cores_sim_fn(); + + /* Wait until all CPUs have finished to unmap the NS<->SP buffer */ + for_each_cpu(cpu_node) { + cpu_mpid = tftf_get_mpidr_from_node(cpu_node); + core_pos = platform_get_core_pos(cpu_mpid); + tftf_wait_for_event(&cpu_has_finished_test[core_pos]); + } +exit_unmap: + VERBOSE("Unmapping NS<->SP shared buffer\n"); + + mmap_remove_dynamic_region(ARM_SECURE_SERVICE_BUFFER_BASE, + ARM_SECURE_SERVICE_BUFFER_SIZE); +exit: + return result; +} |