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 ******************************************************************************/
ffa_test_relay(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
test_memory_send(ffa_endpoint_id16_t sender,uint64_t handle,ffa_mtd_flag32_t flags,bool multi_endpoint)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
send_ffa_pm_success(void)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 ******************************************************************************/
tsp_cpu_off_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
tsp_cpu_suspend_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
tsp_cpu_resume_main(uint64_t max_off_pwrlvl,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
handle_framework_message(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
handle_partition_message(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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 ******************************************************************************/
tsp_event_loop(uint64_t smc_fid,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)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
tsp_loop(smc_args_t * args)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 ******************************************************************************/
tsp_main(void)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 ******************************************************************************/
tsp_cpu_on_main(void)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