14a8bfdb9SAchin Gupta /* 2*758ccb80SChris Kay * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved. 34a8bfdb9SAchin Gupta * 44a8bfdb9SAchin Gupta * SPDX-License-Identifier: BSD-3-Clause 54a8bfdb9SAchin Gupta */ 64a8bfdb9SAchin Gupta 74a8bfdb9SAchin Gupta #include <assert.h> 84a8bfdb9SAchin Gupta #include <inttypes.h> 94a8bfdb9SAchin Gupta #include <stdint.h> 104a8bfdb9SAchin Gupta 114a8bfdb9SAchin Gupta #include "../../services/std_svc/spm/el3_spmc/spmc.h" 124a8bfdb9SAchin Gupta #include "../../services/std_svc/spm/el3_spmc/spmc_shared_mem.h" 134a8bfdb9SAchin Gupta #include <arch_features.h> 144a8bfdb9SAchin Gupta #include <arch_helpers.h> 154a8bfdb9SAchin Gupta #include <bl32/tsp/tsp.h> 164a8bfdb9SAchin Gupta #include <common/bl_common.h> 17*758ccb80SChris Kay #include <common/build_message.h> 184a8bfdb9SAchin Gupta #include <common/debug.h> 1915ca1ee3SMarc Bonnici #include "ffa_helpers.h" 204a8bfdb9SAchin Gupta #include <lib/psci/psci.h> 214a8bfdb9SAchin Gupta #include <lib/spinlock.h> 2215ca1ee3SMarc Bonnici #include <lib/xlat_tables/xlat_tables_defs.h> 2315ca1ee3SMarc Bonnici #include <lib/xlat_tables/xlat_tables_v2.h> 244a8bfdb9SAchin Gupta #include <plat/common/platform.h> 254a8bfdb9SAchin Gupta #include <platform_tsp.h> 264a8bfdb9SAchin Gupta #include <services/ffa_svc.h> 274a8bfdb9SAchin Gupta #include "tsp_private.h" 284a8bfdb9SAchin Gupta 294a8bfdb9SAchin Gupta #include <platform_def.h> 304a8bfdb9SAchin Gupta 314a8bfdb9SAchin Gupta static ffa_endpoint_id16_t tsp_id, spmc_id; 3215ca1ee3SMarc Bonnici uint8_t mem_region_buffer[4096 * 2] __aligned(PAGE_SIZE); 3315ca1ee3SMarc Bonnici 3415ca1ee3SMarc Bonnici /* Partition Mailbox. */ 3515ca1ee3SMarc Bonnici static uint8_t send_page[PAGE_SIZE] __aligned(PAGE_SIZE); 3615ca1ee3SMarc Bonnici static uint8_t recv_page[PAGE_SIZE] __aligned(PAGE_SIZE); 3715ca1ee3SMarc Bonnici 3815ca1ee3SMarc Bonnici /* 3915ca1ee3SMarc Bonnici * Declare a global mailbox for use within the TSP. 4015ca1ee3SMarc Bonnici * This will be initialized appropriately when the buffers 4115ca1ee3SMarc Bonnici * are mapped with the SPMC. 4215ca1ee3SMarc Bonnici */ 4315ca1ee3SMarc Bonnici static struct mailbox mailbox; 4415ca1ee3SMarc Bonnici 4515ca1ee3SMarc Bonnici /******************************************************************************* 4615ca1ee3SMarc Bonnici * This enum is used to handle test cases driven from the FF-A Test Driver. 4715ca1ee3SMarc Bonnici ******************************************************************************/ 4815ca1ee3SMarc Bonnici /* Keep in Sync with FF-A Test Driver. */ 4915ca1ee3SMarc Bonnici enum message_t { 5015ca1ee3SMarc Bonnici /* Partition Only Messages. */ 5115ca1ee3SMarc Bonnici FF_A_RELAY_MESSAGE = 0, 5215ca1ee3SMarc Bonnici 5315ca1ee3SMarc Bonnici /* Basic Functionality. */ 5415ca1ee3SMarc Bonnici FF_A_ECHO_MESSAGE, 5515ca1ee3SMarc Bonnici FF_A_RELAY_MESSAGE_EL3, 5615ca1ee3SMarc Bonnici 5715ca1ee3SMarc Bonnici /* Memory Sharing. */ 5815ca1ee3SMarc Bonnici FF_A_MEMORY_SHARE, 5915ca1ee3SMarc Bonnici FF_A_MEMORY_SHARE_FRAGMENTED, 6015ca1ee3SMarc Bonnici FF_A_MEMORY_LEND, 6115ca1ee3SMarc Bonnici FF_A_MEMORY_LEND_FRAGMENTED, 6215ca1ee3SMarc Bonnici 6315ca1ee3SMarc Bonnici FF_A_MEMORY_SHARE_MULTI_ENDPOINT, 6415ca1ee3SMarc Bonnici FF_A_MEMORY_LEND_MULTI_ENDPOINT, 6515ca1ee3SMarc Bonnici 6615ca1ee3SMarc Bonnici LAST, 6715ca1ee3SMarc Bonnici FF_A_RUN_ALL = 255, 6815ca1ee3SMarc Bonnici FF_A_OP_MAX = 256 6915ca1ee3SMarc Bonnici }; 7015ca1ee3SMarc Bonnici 7115ca1ee3SMarc Bonnici #if SPMC_AT_EL3 7215ca1ee3SMarc Bonnici extern void tsp_cpu_on_entry(void); 7315ca1ee3SMarc Bonnici #endif 7415ca1ee3SMarc Bonnici 7515ca1ee3SMarc Bonnici /******************************************************************************* 7615ca1ee3SMarc Bonnici * Test Functions. 7715ca1ee3SMarc Bonnici ******************************************************************************/ 7815ca1ee3SMarc Bonnici 7915ca1ee3SMarc Bonnici /******************************************************************************* 8015ca1ee3SMarc Bonnici * Enable the TSP to forward the received message to another partition and ask 8115ca1ee3SMarc Bonnici * it to echo the value back in order to validate direct messages functionality. 8215ca1ee3SMarc Bonnici ******************************************************************************/ 8315ca1ee3SMarc Bonnici static int ffa_test_relay(uint64_t arg0, 8415ca1ee3SMarc Bonnici uint64_t arg1, 8515ca1ee3SMarc Bonnici uint64_t arg2, 8615ca1ee3SMarc Bonnici uint64_t arg3, 8715ca1ee3SMarc Bonnici uint64_t arg4, 8815ca1ee3SMarc Bonnici uint64_t arg5, 8915ca1ee3SMarc Bonnici uint64_t arg6, 9015ca1ee3SMarc Bonnici uint64_t arg7) 9115ca1ee3SMarc Bonnici { 9215ca1ee3SMarc Bonnici smc_args_t ffa_forward_result; 9315ca1ee3SMarc Bonnici ffa_endpoint_id16_t receiver = arg5; 9415ca1ee3SMarc Bonnici 95ed23d274SMarc Bonnici ffa_forward_result = ffa_msg_send_direct_req(tsp_id, 9615ca1ee3SMarc Bonnici receiver, 9715ca1ee3SMarc Bonnici FF_A_ECHO_MESSAGE, arg4, 9815ca1ee3SMarc Bonnici 0, 0, 0); 9915ca1ee3SMarc Bonnici return ffa_forward_result._regs[3]; 10015ca1ee3SMarc Bonnici } 10115ca1ee3SMarc Bonnici 10215ca1ee3SMarc Bonnici /******************************************************************************* 10315ca1ee3SMarc Bonnici * This function handles memory management tests, currently share and lend. 10415ca1ee3SMarc Bonnici * This test supports the use of FRAG_RX to use memory descriptors that do not 10515ca1ee3SMarc Bonnici * fit in a single 4KB buffer. 10615ca1ee3SMarc Bonnici ******************************************************************************/ 10715ca1ee3SMarc Bonnici static int test_memory_send(ffa_endpoint_id16_t sender, uint64_t handle, 10815ca1ee3SMarc Bonnici ffa_mtd_flag32_t flags, bool multi_endpoint) 10915ca1ee3SMarc Bonnici { 11015ca1ee3SMarc Bonnici struct ffa_mtd *m; 11115ca1ee3SMarc Bonnici struct ffa_emad_v1_0 *receivers; 11215ca1ee3SMarc Bonnici struct ffa_comp_mrd *composite; 11315ca1ee3SMarc Bonnici int ret, status = 0; 11415ca1ee3SMarc Bonnici unsigned int mem_attrs; 11515ca1ee3SMarc Bonnici char *ptr; 11615ca1ee3SMarc Bonnici ffa_endpoint_id16_t source = sender; 11715ca1ee3SMarc Bonnici uint32_t total_length, recv_length = 0; 11815ca1ee3SMarc Bonnici 11915ca1ee3SMarc Bonnici /* 12015ca1ee3SMarc Bonnici * In the case that we're testing multiple endpoints choose a partition 12115ca1ee3SMarc Bonnici * ID that resides in the normal world so the SPMC won't detect it as 12215ca1ee3SMarc Bonnici * invalid. 12315ca1ee3SMarc Bonnici * TODO: Should get endpoint receiver id and flag as input from NWd. 12415ca1ee3SMarc Bonnici */ 12515ca1ee3SMarc Bonnici uint32_t receiver_count = multi_endpoint ? 2 : 1; 12615ca1ee3SMarc Bonnici ffa_endpoint_id16_t test_receivers[2] = { tsp_id, 0x10 }; 12715ca1ee3SMarc Bonnici 12815ca1ee3SMarc Bonnici /* Ensure that the sender ID resides in the normal world. */ 12915ca1ee3SMarc Bonnici if (ffa_is_secure_world_id(sender)) { 13015ca1ee3SMarc Bonnici ERROR("Invalid sender ID 0x%x.\n", sender); 13115ca1ee3SMarc Bonnici return FFA_ERROR_DENIED; 13215ca1ee3SMarc Bonnici } 13315ca1ee3SMarc Bonnici 13415ca1ee3SMarc Bonnici if (!memory_retrieve(&mailbox, &m, handle, source, test_receivers, 13515ca1ee3SMarc Bonnici receiver_count, flags, &recv_length, 13615ca1ee3SMarc Bonnici &total_length)) { 13715ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 13815ca1ee3SMarc Bonnici } 13915ca1ee3SMarc Bonnici 14015ca1ee3SMarc Bonnici receivers = (struct ffa_emad_v1_0 *) 14115ca1ee3SMarc Bonnici ((uint8_t *) m + m->emad_offset); 14215ca1ee3SMarc Bonnici while (total_length != recv_length) { 14315ca1ee3SMarc Bonnici smc_args_t ffa_return; 14415ca1ee3SMarc Bonnici uint32_t frag_length; 14515ca1ee3SMarc Bonnici 14615ca1ee3SMarc Bonnici ffa_return = ffa_mem_frag_rx(handle, recv_length); 14715ca1ee3SMarc Bonnici 14815ca1ee3SMarc Bonnici if (ffa_return._regs[0] == FFA_ERROR) { 14915ca1ee3SMarc Bonnici WARN("TSP: failed to resume mem with handle %lx\n", 15015ca1ee3SMarc Bonnici handle); 15115ca1ee3SMarc Bonnici return ffa_return._regs[2]; 15215ca1ee3SMarc Bonnici } 15315ca1ee3SMarc Bonnici frag_length = ffa_return._regs[3]; 15415ca1ee3SMarc Bonnici 15515ca1ee3SMarc Bonnici /* Validate frag_length is less than total_length and mailbox size. */ 15615ca1ee3SMarc Bonnici if (frag_length > total_length || 15715ca1ee3SMarc Bonnici frag_length > (mailbox.rxtx_page_count * PAGE_SIZE)) { 15815ca1ee3SMarc Bonnici ERROR("Invalid parameters!\n"); 15915ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 16015ca1ee3SMarc Bonnici } 16115ca1ee3SMarc Bonnici 16215ca1ee3SMarc Bonnici /* Validate frag_length is less than remaining mem_region_buffer size. */ 16315ca1ee3SMarc Bonnici if (frag_length + recv_length >= REGION_BUF_SIZE) { 16415ca1ee3SMarc Bonnici ERROR("Out of memory!\n"); 16515ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 16615ca1ee3SMarc Bonnici } 16715ca1ee3SMarc Bonnici 16815ca1ee3SMarc Bonnici memcpy(&mem_region_buffer[recv_length], mailbox.rx_buffer, 16915ca1ee3SMarc Bonnici frag_length); 17015ca1ee3SMarc Bonnici 17115ca1ee3SMarc Bonnici if (ffa_rx_release()) { 17215ca1ee3SMarc Bonnici ERROR("Failed to release buffer!\n"); 17315ca1ee3SMarc Bonnici return FFA_ERROR_DENIED; 17415ca1ee3SMarc Bonnici } 17515ca1ee3SMarc Bonnici 17615ca1ee3SMarc Bonnici recv_length += frag_length; 17715ca1ee3SMarc Bonnici 17815ca1ee3SMarc Bonnici assert(recv_length <= total_length); 17915ca1ee3SMarc Bonnici } 18015ca1ee3SMarc Bonnici 18115ca1ee3SMarc Bonnici composite = ffa_memory_region_get_composite(m, 0); 18215ca1ee3SMarc Bonnici if (composite == NULL) { 18315ca1ee3SMarc Bonnici WARN("Failed to get composite descriptor!\n"); 18415ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 18515ca1ee3SMarc Bonnici } 18615ca1ee3SMarc Bonnici 18715ca1ee3SMarc Bonnici VERBOSE("Address: %p; page_count: %x %lx\n", 18815ca1ee3SMarc Bonnici (void *)composite->address_range_array[0].address, 18915ca1ee3SMarc Bonnici composite->address_range_array[0].page_count, PAGE_SIZE); 19015ca1ee3SMarc Bonnici 19115ca1ee3SMarc Bonnici /* This test is only concerned with RW permissions. */ 19215ca1ee3SMarc Bonnici if (ffa_get_data_access_attr( 19315ca1ee3SMarc Bonnici receivers[0].mapd.memory_access_permissions) != FFA_MEM_PERM_RW) { 19415ca1ee3SMarc Bonnici ERROR("Data permission in retrieve response %x does not match share/lend %x!\n", 19515ca1ee3SMarc Bonnici ffa_get_data_access_attr(receivers[0].mapd.memory_access_permissions), 19615ca1ee3SMarc Bonnici FFA_MEM_PERM_RW); 19715ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 19815ca1ee3SMarc Bonnici } 19915ca1ee3SMarc Bonnici 20015ca1ee3SMarc Bonnici mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER; 20115ca1ee3SMarc Bonnici 20215ca1ee3SMarc Bonnici /* Only expecting to be sent memory from NWd so map accordingly. */ 20315ca1ee3SMarc Bonnici mem_attrs |= MT_NS; 20415ca1ee3SMarc Bonnici 2058c353e00SThomas Viehweger for (int32_t i = 0; i < (int32_t)composite->address_range_count; i++) { 20615ca1ee3SMarc Bonnici size_t size = composite->address_range_array[i].page_count * PAGE_SIZE; 20715ca1ee3SMarc Bonnici 20815ca1ee3SMarc Bonnici ptr = (char *) composite->address_range_array[i].address; 20915ca1ee3SMarc Bonnici ret = mmap_add_dynamic_region( 21015ca1ee3SMarc Bonnici (uint64_t)ptr, 21115ca1ee3SMarc Bonnici (uint64_t)ptr, 21215ca1ee3SMarc Bonnici size, mem_attrs); 21315ca1ee3SMarc Bonnici 21415ca1ee3SMarc Bonnici if (ret != 0) { 2158c353e00SThomas Viehweger ERROR("Failed [%d] mmap_add_dynamic_region %u (%lx) (%lx) (%x)!\n", 21615ca1ee3SMarc Bonnici i, ret, 21715ca1ee3SMarc Bonnici (uint64_t)composite->address_range_array[i].address, 21815ca1ee3SMarc Bonnici size, mem_attrs); 21915ca1ee3SMarc Bonnici 2201543d17bSShruti Gupta /* Remove mappings previously created in this transaction. */ 2211543d17bSShruti Gupta for (i--; i >= 0; i--) { 22215ca1ee3SMarc Bonnici ret = mmap_remove_dynamic_region( 2231543d17bSShruti Gupta (uint64_t)composite->address_range_array[i].address, 22415ca1ee3SMarc Bonnici composite->address_range_array[i].page_count * PAGE_SIZE); 22515ca1ee3SMarc Bonnici 22615ca1ee3SMarc Bonnici if (ret != 0) { 22715ca1ee3SMarc Bonnici ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i); 22815ca1ee3SMarc Bonnici panic(); 22915ca1ee3SMarc Bonnici } 23015ca1ee3SMarc Bonnici } 2311543d17bSShruti Gupta 23215ca1ee3SMarc Bonnici return FFA_ERROR_NO_MEMORY; 23315ca1ee3SMarc Bonnici } 23415ca1ee3SMarc Bonnici 23515ca1ee3SMarc Bonnici /* Increment memory region for validation purposes. */ 23615ca1ee3SMarc Bonnici ++(*ptr); 23715ca1ee3SMarc Bonnici 23815ca1ee3SMarc Bonnici /* 23915ca1ee3SMarc Bonnici * Read initial magic number from memory region for 24015ca1ee3SMarc Bonnici * validation purposes. 24115ca1ee3SMarc Bonnici */ 24215ca1ee3SMarc Bonnici if (!i) { 24315ca1ee3SMarc Bonnici status = *ptr; 24415ca1ee3SMarc Bonnici } 24515ca1ee3SMarc Bonnici } 24615ca1ee3SMarc Bonnici 24715ca1ee3SMarc Bonnici for (uint32_t i = 0U; i < composite->address_range_count; i++) { 24815ca1ee3SMarc Bonnici ret = mmap_remove_dynamic_region( 24915ca1ee3SMarc Bonnici (uint64_t)composite->address_range_array[i].address, 25015ca1ee3SMarc Bonnici composite->address_range_array[i].page_count * PAGE_SIZE); 25115ca1ee3SMarc Bonnici 25215ca1ee3SMarc Bonnici if (ret != 0) { 25315ca1ee3SMarc Bonnici ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i); 25415ca1ee3SMarc Bonnici return FFA_ERROR_NO_MEMORY; 25515ca1ee3SMarc Bonnici } 25615ca1ee3SMarc Bonnici } 25715ca1ee3SMarc Bonnici 25815ca1ee3SMarc Bonnici if (!memory_relinquish((struct ffa_mem_relinquish_descriptor *)mailbox.tx_buffer, 25915ca1ee3SMarc Bonnici m->handle, tsp_id)) { 26015ca1ee3SMarc Bonnici ERROR("Failed to relinquish memory region!\n"); 26115ca1ee3SMarc Bonnici return FFA_ERROR_INVALID_PARAMETER; 26215ca1ee3SMarc Bonnici } 26315ca1ee3SMarc Bonnici return status; 26415ca1ee3SMarc Bonnici } 2654a8bfdb9SAchin Gupta 2664a8bfdb9SAchin Gupta static smc_args_t *send_ffa_pm_success(void) 2674a8bfdb9SAchin Gupta { 2684a8bfdb9SAchin Gupta return set_smc_args(FFA_MSG_SEND_DIRECT_RESP_SMC32, 26915ca1ee3SMarc Bonnici ((tsp_id & FFA_DIRECT_MSG_ENDPOINT_ID_MASK) 27015ca1ee3SMarc Bonnici << FFA_DIRECT_MSG_SOURCE_SHIFT) | spmc_id, 2714a8bfdb9SAchin Gupta FFA_FWK_MSG_BIT | 2724a8bfdb9SAchin Gupta (FFA_PM_MSG_PM_RESP & FFA_FWK_MSG_MASK), 2734a8bfdb9SAchin Gupta 0, 0, 0, 0, 0); 2744a8bfdb9SAchin Gupta } 2754a8bfdb9SAchin Gupta 2764a8bfdb9SAchin Gupta /******************************************************************************* 2774a8bfdb9SAchin Gupta * This function performs any remaining book keeping in the test secure payload 2784a8bfdb9SAchin Gupta * before this cpu is turned off in response to a psci cpu_off request. 2794a8bfdb9SAchin Gupta ******************************************************************************/ 2804a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_off_main(uint64_t arg0, 2814a8bfdb9SAchin Gupta uint64_t arg1, 2824a8bfdb9SAchin Gupta uint64_t arg2, 2834a8bfdb9SAchin Gupta uint64_t arg3, 2844a8bfdb9SAchin Gupta uint64_t arg4, 2854a8bfdb9SAchin Gupta uint64_t arg5, 2864a8bfdb9SAchin Gupta uint64_t arg6, 2874a8bfdb9SAchin Gupta uint64_t arg7) 2884a8bfdb9SAchin Gupta { 2894a8bfdb9SAchin Gupta uint32_t linear_id = plat_my_core_pos(); 2904a8bfdb9SAchin Gupta 2914a8bfdb9SAchin Gupta /* 2924a8bfdb9SAchin Gupta * This cpu is being turned off, so disable the timer to prevent the 2934a8bfdb9SAchin Gupta * secure timer interrupt from interfering with power down. A pending 2944a8bfdb9SAchin Gupta * interrupt will be lost but we do not care as we are turning off. 2954a8bfdb9SAchin Gupta */ 2964a8bfdb9SAchin Gupta tsp_generic_timer_stop(); 2974a8bfdb9SAchin Gupta 2984a8bfdb9SAchin Gupta /* Update this cpu's statistics. */ 2994a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count++; 3004a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count++; 3014a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_off_count++; 3024a8bfdb9SAchin Gupta 3033354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx off request\n", read_mpidr()); 3043354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", 3054a8bfdb9SAchin Gupta read_mpidr(), 3064a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count, 3074a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count, 3084a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_off_count); 3094a8bfdb9SAchin Gupta 3104a8bfdb9SAchin Gupta return send_ffa_pm_success(); 3114a8bfdb9SAchin Gupta } 3124a8bfdb9SAchin Gupta 3134a8bfdb9SAchin Gupta /******************************************************************************* 3144a8bfdb9SAchin Gupta * This function performs any book keeping in the test secure payload before 3154a8bfdb9SAchin Gupta * this cpu's architectural state is saved in response to an earlier psci 3164a8bfdb9SAchin Gupta * cpu_suspend request. 3174a8bfdb9SAchin Gupta ******************************************************************************/ 3184a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_suspend_main(uint64_t arg0, 3194a8bfdb9SAchin Gupta uint64_t arg1, 3204a8bfdb9SAchin Gupta uint64_t arg2, 3214a8bfdb9SAchin Gupta uint64_t arg3, 3224a8bfdb9SAchin Gupta uint64_t arg4, 3234a8bfdb9SAchin Gupta uint64_t arg5, 3244a8bfdb9SAchin Gupta uint64_t arg6, 3254a8bfdb9SAchin Gupta uint64_t arg7) 3264a8bfdb9SAchin Gupta { 3274a8bfdb9SAchin Gupta uint32_t linear_id = plat_my_core_pos(); 3284a8bfdb9SAchin Gupta 3294a8bfdb9SAchin Gupta /* 3304a8bfdb9SAchin Gupta * Save the time context and disable it to prevent the secure timer 3314a8bfdb9SAchin Gupta * interrupt from interfering with wakeup from the suspend state. 3324a8bfdb9SAchin Gupta */ 3334a8bfdb9SAchin Gupta tsp_generic_timer_save(); 3344a8bfdb9SAchin Gupta tsp_generic_timer_stop(); 3354a8bfdb9SAchin Gupta 3364a8bfdb9SAchin Gupta /* Update this cpu's statistics. */ 3374a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count++; 3384a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count++; 3394a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_suspend_count++; 3404a8bfdb9SAchin Gupta 3413354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 3424a8bfdb9SAchin Gupta read_mpidr(), 3434a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count, 3444a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count, 3454a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_suspend_count); 3464a8bfdb9SAchin Gupta 3474a8bfdb9SAchin Gupta return send_ffa_pm_success(); 3484a8bfdb9SAchin Gupta } 3494a8bfdb9SAchin Gupta 3504a8bfdb9SAchin Gupta /******************************************************************************* 3514a8bfdb9SAchin Gupta * This function performs any bookkeeping in the test secure payload after this 3524a8bfdb9SAchin Gupta * cpu's architectural state has been restored after wakeup from an earlier psci 3534a8bfdb9SAchin Gupta * cpu_suspend request. 3544a8bfdb9SAchin Gupta ******************************************************************************/ 3554a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, 3564a8bfdb9SAchin Gupta uint64_t arg1, 3574a8bfdb9SAchin Gupta uint64_t arg2, 3584a8bfdb9SAchin Gupta uint64_t arg3, 3594a8bfdb9SAchin Gupta uint64_t arg4, 3604a8bfdb9SAchin Gupta uint64_t arg5, 3614a8bfdb9SAchin Gupta uint64_t arg6, 3624a8bfdb9SAchin Gupta uint64_t arg7) 3634a8bfdb9SAchin Gupta { 3644a8bfdb9SAchin Gupta uint32_t linear_id = plat_my_core_pos(); 3654a8bfdb9SAchin Gupta 3664a8bfdb9SAchin Gupta /* Restore the generic timer context. */ 3674a8bfdb9SAchin Gupta tsp_generic_timer_restore(); 3684a8bfdb9SAchin Gupta 3694a8bfdb9SAchin Gupta /* Update this cpu's statistics. */ 3704a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count++; 3714a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count++; 3724a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_resume_count++; 3734a8bfdb9SAchin Gupta 3743354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n", 3754a8bfdb9SAchin Gupta read_mpidr(), max_off_pwrlvl); 3763354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n", 3774a8bfdb9SAchin Gupta read_mpidr(), 3784a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count, 3794a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count, 3804a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_resume_count); 3814a8bfdb9SAchin Gupta 3824a8bfdb9SAchin Gupta return send_ffa_pm_success(); 3834a8bfdb9SAchin Gupta } 3844a8bfdb9SAchin Gupta 3854a8bfdb9SAchin Gupta /******************************************************************************* 3864a8bfdb9SAchin Gupta * This function handles framework messages. Currently only PM. 3874a8bfdb9SAchin Gupta ******************************************************************************/ 3884a8bfdb9SAchin Gupta static smc_args_t *handle_framework_message(uint64_t arg0, 3894a8bfdb9SAchin Gupta uint64_t arg1, 3904a8bfdb9SAchin Gupta uint64_t arg2, 3914a8bfdb9SAchin Gupta uint64_t arg3, 3924a8bfdb9SAchin Gupta uint64_t arg4, 3934a8bfdb9SAchin Gupta uint64_t arg5, 3944a8bfdb9SAchin Gupta uint64_t arg6, 3954a8bfdb9SAchin Gupta uint64_t arg7) 3964a8bfdb9SAchin Gupta { 3974a8bfdb9SAchin Gupta /* Check if it is a power management message from the SPMC. */ 3984a8bfdb9SAchin Gupta if (ffa_endpoint_source(arg1) != spmc_id) { 3994a8bfdb9SAchin Gupta goto err; 4004a8bfdb9SAchin Gupta } 4014a8bfdb9SAchin Gupta 4024a8bfdb9SAchin Gupta /* Check if it is a PM request message. */ 4034a8bfdb9SAchin Gupta if ((arg2 & FFA_FWK_MSG_MASK) == FFA_FWK_MSG_PSCI) { 4044a8bfdb9SAchin Gupta /* Check if it is a PSCI CPU_OFF request. */ 4054a8bfdb9SAchin Gupta if (arg3 == PSCI_CPU_OFF) { 4064a8bfdb9SAchin Gupta return tsp_cpu_off_main(arg0, arg1, arg2, arg3, 4074a8bfdb9SAchin Gupta arg4, arg5, arg6, arg7); 4084a8bfdb9SAchin Gupta } else if (arg3 == PSCI_CPU_SUSPEND_AARCH64) { 4094a8bfdb9SAchin Gupta return tsp_cpu_suspend_main(arg0, arg1, arg2, arg3, 4104a8bfdb9SAchin Gupta arg4, arg5, arg6, arg7); 4114a8bfdb9SAchin Gupta } 4124a8bfdb9SAchin Gupta } else if ((arg2 & FFA_FWK_MSG_MASK) == FFA_PM_MSG_WB_REQ) { 4134a8bfdb9SAchin Gupta /* Check it is a PSCI Warm Boot request. */ 4144a8bfdb9SAchin Gupta if (arg3 == FFA_WB_TYPE_NOTS2RAM) { 4154a8bfdb9SAchin Gupta return tsp_cpu_resume_main(arg0, arg1, arg2, arg3, 4164a8bfdb9SAchin Gupta arg4, arg5, arg6, arg7); 4174a8bfdb9SAchin Gupta } 4184a8bfdb9SAchin Gupta } 4194a8bfdb9SAchin Gupta 4204a8bfdb9SAchin Gupta err: 4214a8bfdb9SAchin Gupta ERROR("%s: Unknown framework message!\n", __func__); 4224a8bfdb9SAchin Gupta panic(); 4234a8bfdb9SAchin Gupta } 4244a8bfdb9SAchin Gupta 4254a8bfdb9SAchin Gupta /******************************************************************************* 42615ca1ee3SMarc Bonnici * Handles partition messages. Exercised from the FF-A Test Driver. 42715ca1ee3SMarc Bonnici ******************************************************************************/ 42815ca1ee3SMarc Bonnici static smc_args_t *handle_partition_message(uint64_t arg0, 42915ca1ee3SMarc Bonnici uint64_t arg1, 43015ca1ee3SMarc Bonnici uint64_t arg2, 43115ca1ee3SMarc Bonnici uint64_t arg3, 43215ca1ee3SMarc Bonnici uint64_t arg4, 43315ca1ee3SMarc Bonnici uint64_t arg5, 43415ca1ee3SMarc Bonnici uint64_t arg6, 43515ca1ee3SMarc Bonnici uint64_t arg7) 43615ca1ee3SMarc Bonnici { 43715ca1ee3SMarc Bonnici uint16_t sender = ffa_endpoint_source(arg1); 43815ca1ee3SMarc Bonnici uint16_t receiver = ffa_endpoint_destination(arg1); 43915ca1ee3SMarc Bonnici int status = -1; 44015ca1ee3SMarc Bonnici const bool multi_endpoint = true; 44115ca1ee3SMarc Bonnici 44215ca1ee3SMarc Bonnici switch (arg3) { 44315ca1ee3SMarc Bonnici case FF_A_MEMORY_SHARE: 44415ca1ee3SMarc Bonnici INFO("TSP Tests: Memory Share Request--\n"); 44515ca1ee3SMarc Bonnici status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, !multi_endpoint); 44615ca1ee3SMarc Bonnici break; 44715ca1ee3SMarc Bonnici 44815ca1ee3SMarc Bonnici case FF_A_MEMORY_LEND: 44915ca1ee3SMarc Bonnici INFO("TSP Tests: Memory Lend Request--\n"); 45015ca1ee3SMarc Bonnici status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, !multi_endpoint); 45115ca1ee3SMarc Bonnici break; 45215ca1ee3SMarc Bonnici 45315ca1ee3SMarc Bonnici case FF_A_MEMORY_SHARE_MULTI_ENDPOINT: 45415ca1ee3SMarc Bonnici INFO("TSP Tests: Multi Endpoint Memory Share Request--\n"); 45515ca1ee3SMarc Bonnici status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, multi_endpoint); 45615ca1ee3SMarc Bonnici break; 45715ca1ee3SMarc Bonnici 45815ca1ee3SMarc Bonnici case FF_A_MEMORY_LEND_MULTI_ENDPOINT: 45915ca1ee3SMarc Bonnici INFO("TSP Tests: Multi Endpoint Memory Lend Request--\n"); 46015ca1ee3SMarc Bonnici status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, multi_endpoint); 46115ca1ee3SMarc Bonnici break; 46215ca1ee3SMarc Bonnici case FF_A_RELAY_MESSAGE: 46315ca1ee3SMarc Bonnici INFO("TSP Tests: Relaying message--\n"); 46415ca1ee3SMarc Bonnici status = ffa_test_relay(arg0, arg1, arg2, arg3, arg4, 46515ca1ee3SMarc Bonnici arg5, arg6, arg7); 46615ca1ee3SMarc Bonnici break; 46715ca1ee3SMarc Bonnici 46815ca1ee3SMarc Bonnici case FF_A_ECHO_MESSAGE: 46915ca1ee3SMarc Bonnici INFO("TSP Tests: echo message--\n"); 47015ca1ee3SMarc Bonnici status = arg4; 47115ca1ee3SMarc Bonnici break; 47215ca1ee3SMarc Bonnici 47315ca1ee3SMarc Bonnici default: 47415ca1ee3SMarc Bonnici INFO("TSP Tests: Unknown request ID %d--\n", (int) arg3); 47515ca1ee3SMarc Bonnici } 47615ca1ee3SMarc Bonnici 47715ca1ee3SMarc Bonnici /* Swap the sender and receiver in the response. */ 47815ca1ee3SMarc Bonnici return ffa_msg_send_direct_resp(receiver, sender, status, 0, 0, 0, 0); 47915ca1ee3SMarc Bonnici } 48015ca1ee3SMarc Bonnici 48115ca1ee3SMarc Bonnici /******************************************************************************* 4824a8bfdb9SAchin Gupta * This function implements the event loop for handling FF-A ABI invocations. 4834a8bfdb9SAchin Gupta ******************************************************************************/ 4844a8bfdb9SAchin Gupta static smc_args_t *tsp_event_loop(uint64_t smc_fid, 4854a8bfdb9SAchin Gupta uint64_t arg1, 4864a8bfdb9SAchin Gupta uint64_t arg2, 4874a8bfdb9SAchin Gupta uint64_t arg3, 4884a8bfdb9SAchin Gupta uint64_t arg4, 4894a8bfdb9SAchin Gupta uint64_t arg5, 4904a8bfdb9SAchin Gupta uint64_t arg6, 4914a8bfdb9SAchin Gupta uint64_t arg7) 4924a8bfdb9SAchin Gupta { 4934a8bfdb9SAchin Gupta /* Panic if the SPMC did not forward an FF-A call. */ 4944a8bfdb9SAchin Gupta if (!is_ffa_fid(smc_fid)) { 4954a8bfdb9SAchin Gupta ERROR("%s: Unknown SMC FID (0x%lx)\n", __func__, smc_fid); 4964a8bfdb9SAchin Gupta panic(); 4974a8bfdb9SAchin Gupta } 4984a8bfdb9SAchin Gupta 4994a8bfdb9SAchin Gupta switch (smc_fid) { 5004a8bfdb9SAchin Gupta case FFA_INTERRUPT: 5014a8bfdb9SAchin Gupta /* 5024a8bfdb9SAchin Gupta * IRQs were enabled upon re-entry into the TSP. The interrupt 5034a8bfdb9SAchin Gupta * must have been handled by now. Return to the SPMC indicating 5044a8bfdb9SAchin Gupta * the same. 5054a8bfdb9SAchin Gupta */ 5064a8bfdb9SAchin Gupta return set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0); 5074a8bfdb9SAchin Gupta 50815ca1ee3SMarc Bonnici case FFA_MSG_SEND_DIRECT_REQ_SMC64: 5094a8bfdb9SAchin Gupta case FFA_MSG_SEND_DIRECT_REQ_SMC32: 5104a8bfdb9SAchin Gupta /* Check if a framework message, handle accordingly. */ 5114a8bfdb9SAchin Gupta if ((arg2 & FFA_FWK_MSG_BIT)) { 5124a8bfdb9SAchin Gupta return handle_framework_message(smc_fid, arg1, arg2, arg3, 5134a8bfdb9SAchin Gupta arg4, arg5, arg6, arg7); 5144a8bfdb9SAchin Gupta } 51515ca1ee3SMarc Bonnici return handle_partition_message(smc_fid, arg1, arg2, arg3, 51615ca1ee3SMarc Bonnici arg4, arg5, arg6, arg7); 5174a8bfdb9SAchin Gupta } 5184a8bfdb9SAchin Gupta 5194a8bfdb9SAchin Gupta ERROR("%s: Unsupported FF-A FID (0x%lx)\n", __func__, smc_fid); 5204a8bfdb9SAchin Gupta panic(); 5214a8bfdb9SAchin Gupta } 5224a8bfdb9SAchin Gupta 5234a8bfdb9SAchin Gupta static smc_args_t *tsp_loop(smc_args_t *args) 5244a8bfdb9SAchin Gupta { 5254a8bfdb9SAchin Gupta smc_args_t ret; 5264a8bfdb9SAchin Gupta 5274a8bfdb9SAchin Gupta do { 5284a8bfdb9SAchin Gupta /* -------------------------------------------- 5294a8bfdb9SAchin Gupta * Mask FIQ interrupts to avoid preemption 5304a8bfdb9SAchin Gupta * in case EL3 SPMC delegates an IRQ next or a 5314a8bfdb9SAchin Gupta * managed exit. Lastly, unmask IRQs so that 53215ca1ee3SMarc Bonnici * they can be handled immediately upon re-entry. 5334a8bfdb9SAchin Gupta * --------------------------------------------- 5344a8bfdb9SAchin Gupta */ 5354a8bfdb9SAchin Gupta write_daifset(DAIF_FIQ_BIT); 5364a8bfdb9SAchin Gupta write_daifclr(DAIF_IRQ_BIT); 5374a8bfdb9SAchin Gupta ret = smc_helper(args->_regs[0], args->_regs[1], args->_regs[2], 5384a8bfdb9SAchin Gupta args->_regs[3], args->_regs[4], args->_regs[5], 5394a8bfdb9SAchin Gupta args->_regs[6], args->_regs[7]); 5404a8bfdb9SAchin Gupta args = tsp_event_loop(ret._regs[0], ret._regs[1], ret._regs[2], 5414a8bfdb9SAchin Gupta ret._regs[3], ret._regs[4], ret._regs[5], 5424a8bfdb9SAchin Gupta ret._regs[6], ret._regs[7]); 5434a8bfdb9SAchin Gupta } while (1); 5444a8bfdb9SAchin Gupta 5454a8bfdb9SAchin Gupta /* Not Reached. */ 5464a8bfdb9SAchin Gupta return NULL; 5474a8bfdb9SAchin Gupta } 5484a8bfdb9SAchin Gupta 5494a8bfdb9SAchin Gupta /******************************************************************************* 5504a8bfdb9SAchin Gupta * TSP main entry point where it gets the opportunity to initialize its secure 5514a8bfdb9SAchin Gupta * state/applications. Once the state is initialized, it must return to the 5524a8bfdb9SAchin Gupta * SPD with a pointer to the 'tsp_vector_table' jump table. 5534a8bfdb9SAchin Gupta ******************************************************************************/ 5544a8bfdb9SAchin Gupta uint64_t tsp_main(void) 5554a8bfdb9SAchin Gupta { 5564a8bfdb9SAchin Gupta smc_args_t smc_args = {0}; 5574a8bfdb9SAchin Gupta 558*758ccb80SChris Kay NOTICE("TSP: %s\n", build_version_string); 5594a8bfdb9SAchin Gupta NOTICE("TSP: %s\n", build_message); 5604a8bfdb9SAchin Gupta INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); 5614a8bfdb9SAchin Gupta INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); 5624a8bfdb9SAchin Gupta uint32_t linear_id = plat_my_core_pos(); 5634a8bfdb9SAchin Gupta 5644a8bfdb9SAchin Gupta /* Initialize the platform. */ 5654a8bfdb9SAchin Gupta tsp_platform_setup(); 5664a8bfdb9SAchin Gupta 5674a8bfdb9SAchin Gupta /* Initialize secure/applications state here. */ 5684a8bfdb9SAchin Gupta tsp_generic_timer_start(); 5694a8bfdb9SAchin Gupta 5704a8bfdb9SAchin Gupta /* Register secondary entrypoint with the SPMC. */ 5714a8bfdb9SAchin Gupta smc_args = smc_helper(FFA_SECONDARY_EP_REGISTER_SMC64, 5724a8bfdb9SAchin Gupta (uint64_t) tsp_cpu_on_entry, 5734a8bfdb9SAchin Gupta 0, 0, 0, 0, 0, 0); 5744a8bfdb9SAchin Gupta if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) { 5754a8bfdb9SAchin Gupta ERROR("TSP could not register secondary ep (0x%lx)\n", 5764a8bfdb9SAchin Gupta smc_args._regs[2]); 5774a8bfdb9SAchin Gupta panic(); 5784a8bfdb9SAchin Gupta } 57915ca1ee3SMarc Bonnici /* Get TSP's endpoint id. */ 5804a8bfdb9SAchin Gupta smc_args = smc_helper(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0); 5814a8bfdb9SAchin Gupta if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) { 5824a8bfdb9SAchin Gupta ERROR("TSP could not get own ID (0x%lx) on core%d\n", 5834a8bfdb9SAchin Gupta smc_args._regs[2], linear_id); 5844a8bfdb9SAchin Gupta panic(); 5854a8bfdb9SAchin Gupta } 5864a8bfdb9SAchin Gupta 5874a8bfdb9SAchin Gupta tsp_id = smc_args._regs[2]; 5884a8bfdb9SAchin Gupta INFO("TSP FF-A endpoint id = 0x%x\n", tsp_id); 58915ca1ee3SMarc Bonnici 59015ca1ee3SMarc Bonnici /* Get the SPMC ID. */ 5914a8bfdb9SAchin Gupta smc_args = smc_helper(FFA_SPM_ID_GET, 0, 0, 0, 0, 0, 0, 0); 5924a8bfdb9SAchin Gupta if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) { 5934a8bfdb9SAchin Gupta ERROR("TSP could not get SPMC ID (0x%lx) on core%d\n", 5944a8bfdb9SAchin Gupta smc_args._regs[2], linear_id); 5954a8bfdb9SAchin Gupta panic(); 5964a8bfdb9SAchin Gupta } 5974a8bfdb9SAchin Gupta 5984a8bfdb9SAchin Gupta spmc_id = smc_args._regs[2]; 5994a8bfdb9SAchin Gupta 60015ca1ee3SMarc Bonnici /* Call RXTX_MAP to map a 4k RX and TX buffer. */ 60115ca1ee3SMarc Bonnici if (ffa_rxtx_map((uintptr_t) send_page, 60215ca1ee3SMarc Bonnici (uintptr_t) recv_page, 1)) { 60315ca1ee3SMarc Bonnici ERROR("TSP could not map it's RX/TX Buffers\n"); 60415ca1ee3SMarc Bonnici panic(); 60515ca1ee3SMarc Bonnici } 60615ca1ee3SMarc Bonnici 60715ca1ee3SMarc Bonnici mailbox.tx_buffer = send_page; 60815ca1ee3SMarc Bonnici mailbox.rx_buffer = recv_page; 60915ca1ee3SMarc Bonnici mailbox.rxtx_page_count = 1; 61015ca1ee3SMarc Bonnici 61115ca1ee3SMarc Bonnici /* Update this cpu's statistics. */ 6124a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count++; 6134a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count++; 6144a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_on_count++; 6154a8bfdb9SAchin Gupta 6163354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 6174a8bfdb9SAchin Gupta read_mpidr(), 6184a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count, 6194a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count, 6204a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_on_count); 6214a8bfdb9SAchin Gupta 6224a8bfdb9SAchin Gupta /* Tell SPMD that we are done initialising. */ 6234a8bfdb9SAchin Gupta tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0)); 6244a8bfdb9SAchin Gupta 6254a8bfdb9SAchin Gupta /* Not reached. */ 6264a8bfdb9SAchin Gupta return 0; 6274a8bfdb9SAchin Gupta } 6284a8bfdb9SAchin Gupta 6294a8bfdb9SAchin Gupta /******************************************************************************* 6304a8bfdb9SAchin Gupta * This function performs any remaining book keeping in the test secure payload 6314a8bfdb9SAchin Gupta * after this cpu's architectural state has been setup in response to an earlier 6324a8bfdb9SAchin Gupta * psci cpu_on request. 6334a8bfdb9SAchin Gupta ******************************************************************************/ 6344a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_on_main(void) 6354a8bfdb9SAchin Gupta { 6364a8bfdb9SAchin Gupta uint32_t linear_id = plat_my_core_pos(); 6374a8bfdb9SAchin Gupta 6384a8bfdb9SAchin Gupta /* Initialize secure/applications state here. */ 6394a8bfdb9SAchin Gupta tsp_generic_timer_start(); 6404a8bfdb9SAchin Gupta 6414a8bfdb9SAchin Gupta /* Update this cpu's statistics. */ 6424a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count++; 6434a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count++; 6444a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_on_count++; 6453354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx turned on\n", read_mpidr()); 6463354915fSShruti Gupta VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 6474a8bfdb9SAchin Gupta read_mpidr(), 6484a8bfdb9SAchin Gupta tsp_stats[linear_id].smc_count, 6494a8bfdb9SAchin Gupta tsp_stats[linear_id].eret_count, 6504a8bfdb9SAchin Gupta tsp_stats[linear_id].cpu_on_count); 6514a8bfdb9SAchin Gupta /* --------------------------------------------- 6524a8bfdb9SAchin Gupta * Jump to the main event loop to return to EL3 6534a8bfdb9SAchin Gupta * and be ready for the next request on this cpu. 6544a8bfdb9SAchin Gupta * --------------------------------------------- 6554a8bfdb9SAchin Gupta */ 6564a8bfdb9SAchin Gupta return tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0)); 6574a8bfdb9SAchin Gupta } 658