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