xref: /rk3399_ARM-atf/bl32/tsp/tsp_ffa_main.c (revision 15ca1ee342a4dcd8a73a4ae158d245cd4266c832)
14a8bfdb9SAchin Gupta /*
2*15ca1ee3SMarc 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>
18*15ca1ee3SMarc Bonnici #include "ffa_helpers.h"
194a8bfdb9SAchin Gupta #include <lib/psci/psci.h>
204a8bfdb9SAchin Gupta #include <lib/spinlock.h>
21*15ca1ee3SMarc Bonnici #include <lib/xlat_tables/xlat_tables_defs.h>
22*15ca1ee3SMarc 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;
31*15ca1ee3SMarc Bonnici uint8_t mem_region_buffer[4096 * 2]  __aligned(PAGE_SIZE);
32*15ca1ee3SMarc Bonnici 
33*15ca1ee3SMarc Bonnici /* Partition Mailbox. */
34*15ca1ee3SMarc Bonnici static uint8_t send_page[PAGE_SIZE] __aligned(PAGE_SIZE);
35*15ca1ee3SMarc Bonnici static uint8_t recv_page[PAGE_SIZE] __aligned(PAGE_SIZE);
36*15ca1ee3SMarc Bonnici 
37*15ca1ee3SMarc Bonnici /*
38*15ca1ee3SMarc Bonnici  * Declare a global mailbox for use within the TSP.
39*15ca1ee3SMarc Bonnici  * This will be initialized appropriately when the buffers
40*15ca1ee3SMarc Bonnici  * are mapped with the SPMC.
41*15ca1ee3SMarc Bonnici  */
42*15ca1ee3SMarc Bonnici static struct mailbox mailbox;
43*15ca1ee3SMarc Bonnici 
44*15ca1ee3SMarc Bonnici /*******************************************************************************
45*15ca1ee3SMarc Bonnici  * This enum is used to handle test cases driven from the FF-A Test Driver.
46*15ca1ee3SMarc Bonnici  ******************************************************************************/
47*15ca1ee3SMarc Bonnici /* Keep in Sync with FF-A Test Driver. */
48*15ca1ee3SMarc Bonnici enum message_t {
49*15ca1ee3SMarc Bonnici 	/* Partition Only Messages. */
50*15ca1ee3SMarc Bonnici 	FF_A_RELAY_MESSAGE = 0,
51*15ca1ee3SMarc Bonnici 
52*15ca1ee3SMarc Bonnici 	/* Basic Functionality. */
53*15ca1ee3SMarc Bonnici 	FF_A_ECHO_MESSAGE,
54*15ca1ee3SMarc Bonnici 	FF_A_RELAY_MESSAGE_EL3,
55*15ca1ee3SMarc Bonnici 
56*15ca1ee3SMarc Bonnici 	/* Memory Sharing. */
57*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_SHARE,
58*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_SHARE_FRAGMENTED,
59*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_LEND,
60*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_LEND_FRAGMENTED,
61*15ca1ee3SMarc Bonnici 
62*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_SHARE_MULTI_ENDPOINT,
63*15ca1ee3SMarc Bonnici 	FF_A_MEMORY_LEND_MULTI_ENDPOINT,
64*15ca1ee3SMarc Bonnici 
65*15ca1ee3SMarc Bonnici 	LAST,
66*15ca1ee3SMarc Bonnici 	FF_A_RUN_ALL = 255,
67*15ca1ee3SMarc Bonnici 	FF_A_OP_MAX = 256
68*15ca1ee3SMarc Bonnici };
69*15ca1ee3SMarc Bonnici 
70*15ca1ee3SMarc Bonnici #if SPMC_AT_EL3
71*15ca1ee3SMarc Bonnici extern void tsp_cpu_on_entry(void);
72*15ca1ee3SMarc Bonnici #endif
73*15ca1ee3SMarc Bonnici 
74*15ca1ee3SMarc Bonnici /*******************************************************************************
75*15ca1ee3SMarc Bonnici  * Test Functions.
76*15ca1ee3SMarc Bonnici  ******************************************************************************/
77*15ca1ee3SMarc Bonnici 
78*15ca1ee3SMarc Bonnici /*******************************************************************************
79*15ca1ee3SMarc Bonnici  * Enable the TSP to forward the received message to another partition and ask
80*15ca1ee3SMarc Bonnici  * it to echo the value back in order to validate direct messages functionality.
81*15ca1ee3SMarc Bonnici  ******************************************************************************/
82*15ca1ee3SMarc Bonnici static int ffa_test_relay(uint64_t arg0,
83*15ca1ee3SMarc Bonnici 			  uint64_t arg1,
84*15ca1ee3SMarc Bonnici 			  uint64_t arg2,
85*15ca1ee3SMarc Bonnici 			  uint64_t arg3,
86*15ca1ee3SMarc Bonnici 			  uint64_t arg4,
87*15ca1ee3SMarc Bonnici 			  uint64_t arg5,
88*15ca1ee3SMarc Bonnici 			  uint64_t arg6,
89*15ca1ee3SMarc Bonnici 			  uint64_t arg7)
90*15ca1ee3SMarc Bonnici {
91*15ca1ee3SMarc Bonnici 	smc_args_t ffa_forward_result;
92*15ca1ee3SMarc Bonnici 	ffa_endpoint_id16_t receiver = arg5;
93*15ca1ee3SMarc Bonnici 
94*15ca1ee3SMarc Bonnici 	ffa_forward_result = ffa_msg_send_direct_req(ffa_endpoint_source(arg1),
95*15ca1ee3SMarc Bonnici 						     receiver,
96*15ca1ee3SMarc Bonnici 						     FF_A_ECHO_MESSAGE, arg4,
97*15ca1ee3SMarc Bonnici 						     0, 0, 0);
98*15ca1ee3SMarc Bonnici 	return ffa_forward_result._regs[3];
99*15ca1ee3SMarc Bonnici }
100*15ca1ee3SMarc Bonnici 
101*15ca1ee3SMarc Bonnici /*******************************************************************************
102*15ca1ee3SMarc Bonnici  * This function handles memory management tests, currently share and lend.
103*15ca1ee3SMarc Bonnici  * This test supports the use of FRAG_RX to use memory descriptors that do not
104*15ca1ee3SMarc Bonnici  * fit in a single 4KB buffer.
105*15ca1ee3SMarc Bonnici  ******************************************************************************/
106*15ca1ee3SMarc Bonnici static int test_memory_send(ffa_endpoint_id16_t sender, uint64_t handle,
107*15ca1ee3SMarc Bonnici 			    ffa_mtd_flag32_t flags, bool multi_endpoint)
108*15ca1ee3SMarc Bonnici {
109*15ca1ee3SMarc Bonnici 	struct ffa_mtd *m;
110*15ca1ee3SMarc Bonnici 	struct ffa_emad_v1_0 *receivers;
111*15ca1ee3SMarc Bonnici 	struct ffa_comp_mrd *composite;
112*15ca1ee3SMarc Bonnici 	int ret, status = 0;
113*15ca1ee3SMarc Bonnici 	unsigned int mem_attrs;
114*15ca1ee3SMarc Bonnici 	char *ptr;
115*15ca1ee3SMarc Bonnici 	ffa_endpoint_id16_t source = sender;
116*15ca1ee3SMarc Bonnici 	uint32_t total_length, recv_length = 0;
117*15ca1ee3SMarc Bonnici 
118*15ca1ee3SMarc Bonnici 	/*
119*15ca1ee3SMarc Bonnici 	 * In the case that we're testing multiple endpoints choose a partition
120*15ca1ee3SMarc Bonnici 	 * ID that resides in the normal world so the SPMC won't detect it as
121*15ca1ee3SMarc Bonnici 	 * invalid.
122*15ca1ee3SMarc Bonnici 	 * TODO: Should get endpoint receiver id and flag as input from NWd.
123*15ca1ee3SMarc Bonnici 	 */
124*15ca1ee3SMarc Bonnici 	uint32_t receiver_count = multi_endpoint ? 2 : 1;
125*15ca1ee3SMarc Bonnici 	ffa_endpoint_id16_t test_receivers[2] = { tsp_id, 0x10 };
126*15ca1ee3SMarc Bonnici 
127*15ca1ee3SMarc Bonnici 	/* Ensure that the sender ID resides in the normal world. */
128*15ca1ee3SMarc Bonnici 	if (ffa_is_secure_world_id(sender)) {
129*15ca1ee3SMarc Bonnici 		ERROR("Invalid sender ID 0x%x.\n", sender);
130*15ca1ee3SMarc Bonnici 		return FFA_ERROR_DENIED;
131*15ca1ee3SMarc Bonnici 	}
132*15ca1ee3SMarc Bonnici 
133*15ca1ee3SMarc Bonnici 	if (!memory_retrieve(&mailbox, &m, handle, source, test_receivers,
134*15ca1ee3SMarc Bonnici 			     receiver_count, flags, &recv_length,
135*15ca1ee3SMarc Bonnici 			     &total_length)) {
136*15ca1ee3SMarc Bonnici 		return FFA_ERROR_INVALID_PARAMETER;
137*15ca1ee3SMarc Bonnici 	}
138*15ca1ee3SMarc Bonnici 
139*15ca1ee3SMarc Bonnici 	receivers = (struct ffa_emad_v1_0 *)
140*15ca1ee3SMarc Bonnici 		    ((uint8_t *) m + m->emad_offset);
141*15ca1ee3SMarc Bonnici 	while (total_length != recv_length) {
142*15ca1ee3SMarc Bonnici 		smc_args_t ffa_return;
143*15ca1ee3SMarc Bonnici 		uint32_t frag_length;
144*15ca1ee3SMarc Bonnici 
145*15ca1ee3SMarc Bonnici 		ffa_return = ffa_mem_frag_rx(handle, recv_length);
146*15ca1ee3SMarc Bonnici 
147*15ca1ee3SMarc Bonnici 		if (ffa_return._regs[0] == FFA_ERROR) {
148*15ca1ee3SMarc Bonnici 			WARN("TSP: failed to resume mem with handle %lx\n",
149*15ca1ee3SMarc Bonnici 			     handle);
150*15ca1ee3SMarc Bonnici 			return ffa_return._regs[2];
151*15ca1ee3SMarc Bonnici 		}
152*15ca1ee3SMarc Bonnici 		frag_length = ffa_return._regs[3];
153*15ca1ee3SMarc Bonnici 
154*15ca1ee3SMarc Bonnici 		/* Validate frag_length is less than total_length and mailbox size. */
155*15ca1ee3SMarc Bonnici 		if (frag_length > total_length ||
156*15ca1ee3SMarc Bonnici 				frag_length > (mailbox.rxtx_page_count * PAGE_SIZE)) {
157*15ca1ee3SMarc Bonnici 			ERROR("Invalid parameters!\n");
158*15ca1ee3SMarc Bonnici 			return FFA_ERROR_INVALID_PARAMETER;
159*15ca1ee3SMarc Bonnici 		}
160*15ca1ee3SMarc Bonnici 
161*15ca1ee3SMarc Bonnici 		/* Validate frag_length is less than remaining mem_region_buffer size. */
162*15ca1ee3SMarc Bonnici 		if (frag_length + recv_length >= REGION_BUF_SIZE) {
163*15ca1ee3SMarc Bonnici 			ERROR("Out of memory!\n");
164*15ca1ee3SMarc Bonnici 			return FFA_ERROR_INVALID_PARAMETER;
165*15ca1ee3SMarc Bonnici 		}
166*15ca1ee3SMarc Bonnici 
167*15ca1ee3SMarc Bonnici 		memcpy(&mem_region_buffer[recv_length], mailbox.rx_buffer,
168*15ca1ee3SMarc Bonnici 		       frag_length);
169*15ca1ee3SMarc Bonnici 
170*15ca1ee3SMarc Bonnici 		if (ffa_rx_release()) {
171*15ca1ee3SMarc Bonnici 			ERROR("Failed to release buffer!\n");
172*15ca1ee3SMarc Bonnici 			return FFA_ERROR_DENIED;
173*15ca1ee3SMarc Bonnici 		}
174*15ca1ee3SMarc Bonnici 
175*15ca1ee3SMarc Bonnici 		recv_length += frag_length;
176*15ca1ee3SMarc Bonnici 
177*15ca1ee3SMarc Bonnici 		assert(recv_length <= total_length);
178*15ca1ee3SMarc Bonnici 	}
179*15ca1ee3SMarc Bonnici 
180*15ca1ee3SMarc Bonnici 	composite = ffa_memory_region_get_composite(m, 0);
181*15ca1ee3SMarc Bonnici 	if (composite == NULL) {
182*15ca1ee3SMarc Bonnici 		WARN("Failed to get composite descriptor!\n");
183*15ca1ee3SMarc Bonnici 		return FFA_ERROR_INVALID_PARAMETER;
184*15ca1ee3SMarc Bonnici 	}
185*15ca1ee3SMarc Bonnici 
186*15ca1ee3SMarc Bonnici 	VERBOSE("Address: %p; page_count: %x %lx\n",
187*15ca1ee3SMarc Bonnici 		(void *)composite->address_range_array[0].address,
188*15ca1ee3SMarc Bonnici 		composite->address_range_array[0].page_count, PAGE_SIZE);
189*15ca1ee3SMarc Bonnici 
190*15ca1ee3SMarc Bonnici 	/* This test is only concerned with RW permissions. */
191*15ca1ee3SMarc Bonnici 	if (ffa_get_data_access_attr(
192*15ca1ee3SMarc Bonnici 	    receivers[0].mapd.memory_access_permissions) != FFA_MEM_PERM_RW) {
193*15ca1ee3SMarc Bonnici 		ERROR("Data permission in retrieve response %x does not match share/lend %x!\n",
194*15ca1ee3SMarc Bonnici 		      ffa_get_data_access_attr(receivers[0].mapd.memory_access_permissions),
195*15ca1ee3SMarc Bonnici 		      FFA_MEM_PERM_RW);
196*15ca1ee3SMarc Bonnici 		return FFA_ERROR_INVALID_PARAMETER;
197*15ca1ee3SMarc Bonnici 	}
198*15ca1ee3SMarc Bonnici 
199*15ca1ee3SMarc Bonnici 	mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER;
200*15ca1ee3SMarc Bonnici 
201*15ca1ee3SMarc Bonnici 	/* Only expecting to be sent memory from NWd so map accordingly. */
202*15ca1ee3SMarc Bonnici 	mem_attrs |= MT_NS;
203*15ca1ee3SMarc Bonnici 
204*15ca1ee3SMarc Bonnici 	for (uint32_t i = 0U; i < composite->address_range_count; i++) {
205*15ca1ee3SMarc Bonnici 		size_t size = composite->address_range_array[i].page_count * PAGE_SIZE;
206*15ca1ee3SMarc Bonnici 
207*15ca1ee3SMarc Bonnici 		ptr = (char *) composite->address_range_array[i].address;
208*15ca1ee3SMarc Bonnici 		ret = mmap_add_dynamic_region(
209*15ca1ee3SMarc Bonnici 				(uint64_t)ptr,
210*15ca1ee3SMarc Bonnici 				(uint64_t)ptr,
211*15ca1ee3SMarc Bonnici 				size, mem_attrs);
212*15ca1ee3SMarc Bonnici 
213*15ca1ee3SMarc Bonnici 		if (ret != 0) {
214*15ca1ee3SMarc Bonnici 			ERROR("Failed [%u] mmap_add_dynamic_region %u (%lx) (%lx) (%x)!\n",
215*15ca1ee3SMarc Bonnici 				i, ret,
216*15ca1ee3SMarc Bonnici 				(uint64_t)composite->address_range_array[i].address,
217*15ca1ee3SMarc Bonnici 				size, mem_attrs);
218*15ca1ee3SMarc Bonnici 
219*15ca1ee3SMarc Bonnici 			/* Remove mappings created in this transaction. */
220*15ca1ee3SMarc Bonnici 			for (i--; i >= 0U; i--) {
221*15ca1ee3SMarc Bonnici 				ret = mmap_remove_dynamic_region(
222*15ca1ee3SMarc Bonnici 					(uint64_t)ptr,
223*15ca1ee3SMarc Bonnici 					composite->address_range_array[i].page_count * PAGE_SIZE);
224*15ca1ee3SMarc Bonnici 
225*15ca1ee3SMarc Bonnici 				if (ret != 0) {
226*15ca1ee3SMarc Bonnici 					ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i);
227*15ca1ee3SMarc Bonnici 					panic();
228*15ca1ee3SMarc Bonnici 				}
229*15ca1ee3SMarc Bonnici 			}
230*15ca1ee3SMarc Bonnici 			return FFA_ERROR_NO_MEMORY;
231*15ca1ee3SMarc Bonnici 		}
232*15ca1ee3SMarc Bonnici 
233*15ca1ee3SMarc Bonnici 		/* Increment memory region for validation purposes. */
234*15ca1ee3SMarc Bonnici 		++(*ptr);
235*15ca1ee3SMarc Bonnici 
236*15ca1ee3SMarc Bonnici 		/*
237*15ca1ee3SMarc Bonnici 		 * Read initial magic number from memory region for
238*15ca1ee3SMarc Bonnici 		 * validation purposes.
239*15ca1ee3SMarc Bonnici 		 */
240*15ca1ee3SMarc Bonnici 		if (!i) {
241*15ca1ee3SMarc Bonnici 			status = *ptr;
242*15ca1ee3SMarc Bonnici 		}
243*15ca1ee3SMarc Bonnici 	}
244*15ca1ee3SMarc Bonnici 
245*15ca1ee3SMarc Bonnici 	for (uint32_t i = 0U; i < composite->address_range_count; i++) {
246*15ca1ee3SMarc Bonnici 		ret = mmap_remove_dynamic_region(
247*15ca1ee3SMarc Bonnici 			(uint64_t)composite->address_range_array[i].address,
248*15ca1ee3SMarc Bonnici 			composite->address_range_array[i].page_count * PAGE_SIZE);
249*15ca1ee3SMarc Bonnici 
250*15ca1ee3SMarc Bonnici 		if (ret != 0) {
251*15ca1ee3SMarc Bonnici 			ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i);
252*15ca1ee3SMarc Bonnici 			return FFA_ERROR_NO_MEMORY;
253*15ca1ee3SMarc Bonnici 		}
254*15ca1ee3SMarc Bonnici 	}
255*15ca1ee3SMarc Bonnici 
256*15ca1ee3SMarc Bonnici 	if (!memory_relinquish((struct ffa_mem_relinquish_descriptor *)mailbox.tx_buffer,
257*15ca1ee3SMarc Bonnici 				m->handle, tsp_id)) {
258*15ca1ee3SMarc Bonnici 		ERROR("Failed to relinquish memory region!\n");
259*15ca1ee3SMarc Bonnici 		return FFA_ERROR_INVALID_PARAMETER;
260*15ca1ee3SMarc Bonnici 	}
261*15ca1ee3SMarc Bonnici 	return status;
262*15ca1ee3SMarc Bonnici }
2634a8bfdb9SAchin Gupta 
2644a8bfdb9SAchin Gupta static smc_args_t *send_ffa_pm_success(void)
2654a8bfdb9SAchin Gupta {
2664a8bfdb9SAchin Gupta 	return set_smc_args(FFA_MSG_SEND_DIRECT_RESP_SMC32,
267*15ca1ee3SMarc Bonnici 			    ((tsp_id & FFA_DIRECT_MSG_ENDPOINT_ID_MASK)
268*15ca1ee3SMarc Bonnici 			    << FFA_DIRECT_MSG_SOURCE_SHIFT) | spmc_id,
2694a8bfdb9SAchin Gupta 			    FFA_FWK_MSG_BIT |
2704a8bfdb9SAchin Gupta 			    (FFA_PM_MSG_PM_RESP & FFA_FWK_MSG_MASK),
2714a8bfdb9SAchin Gupta 			    0, 0, 0, 0, 0);
2724a8bfdb9SAchin Gupta }
2734a8bfdb9SAchin Gupta 
2744a8bfdb9SAchin Gupta /*******************************************************************************
2754a8bfdb9SAchin Gupta  * This function performs any remaining book keeping in the test secure payload
2764a8bfdb9SAchin Gupta  * before this cpu is turned off in response to a psci cpu_off request.
2774a8bfdb9SAchin Gupta  ******************************************************************************/
2784a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_off_main(uint64_t arg0,
2794a8bfdb9SAchin Gupta 			     uint64_t arg1,
2804a8bfdb9SAchin Gupta 			     uint64_t arg2,
2814a8bfdb9SAchin Gupta 			     uint64_t arg3,
2824a8bfdb9SAchin Gupta 			     uint64_t arg4,
2834a8bfdb9SAchin Gupta 			     uint64_t arg5,
2844a8bfdb9SAchin Gupta 			     uint64_t arg6,
2854a8bfdb9SAchin Gupta 			     uint64_t arg7)
2864a8bfdb9SAchin Gupta {
2874a8bfdb9SAchin Gupta 	uint32_t linear_id = plat_my_core_pos();
2884a8bfdb9SAchin Gupta 
2894a8bfdb9SAchin Gupta 	/*
2904a8bfdb9SAchin Gupta 	 * This cpu is being turned off, so disable the timer to prevent the
2914a8bfdb9SAchin Gupta 	 * secure timer interrupt from interfering with power down. A pending
2924a8bfdb9SAchin Gupta 	 * interrupt will be lost but we do not care as we are turning off.
2934a8bfdb9SAchin Gupta 	 */
2944a8bfdb9SAchin Gupta 	tsp_generic_timer_stop();
2954a8bfdb9SAchin Gupta 
2964a8bfdb9SAchin Gupta 	/* Update this cpu's statistics. */
2974a8bfdb9SAchin Gupta 	tsp_stats[linear_id].smc_count++;
2984a8bfdb9SAchin Gupta 	tsp_stats[linear_id].eret_count++;
2994a8bfdb9SAchin Gupta 	tsp_stats[linear_id].cpu_off_count++;
3004a8bfdb9SAchin Gupta 
3014a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
3024a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
3034a8bfdb9SAchin Gupta 		read_mpidr(),
3044a8bfdb9SAchin Gupta 		tsp_stats[linear_id].smc_count,
3054a8bfdb9SAchin Gupta 		tsp_stats[linear_id].eret_count,
3064a8bfdb9SAchin Gupta 		tsp_stats[linear_id].cpu_off_count);
3074a8bfdb9SAchin Gupta 
3084a8bfdb9SAchin Gupta 	return send_ffa_pm_success();
3094a8bfdb9SAchin Gupta }
3104a8bfdb9SAchin Gupta 
3114a8bfdb9SAchin Gupta /*******************************************************************************
3124a8bfdb9SAchin Gupta  * This function performs any book keeping in the test secure payload before
3134a8bfdb9SAchin Gupta  * this cpu's architectural state is saved in response to an earlier psci
3144a8bfdb9SAchin Gupta  * cpu_suspend request.
3154a8bfdb9SAchin Gupta  ******************************************************************************/
3164a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_suspend_main(uint64_t arg0,
3174a8bfdb9SAchin Gupta 				 uint64_t arg1,
3184a8bfdb9SAchin Gupta 				 uint64_t arg2,
3194a8bfdb9SAchin Gupta 				 uint64_t arg3,
3204a8bfdb9SAchin Gupta 				 uint64_t arg4,
3214a8bfdb9SAchin Gupta 				 uint64_t arg5,
3224a8bfdb9SAchin Gupta 				 uint64_t arg6,
3234a8bfdb9SAchin Gupta 				 uint64_t arg7)
3244a8bfdb9SAchin Gupta {
3254a8bfdb9SAchin Gupta 	uint32_t linear_id = plat_my_core_pos();
3264a8bfdb9SAchin Gupta 
3274a8bfdb9SAchin Gupta 	/*
3284a8bfdb9SAchin Gupta 	 * Save the time context and disable it to prevent the secure timer
3294a8bfdb9SAchin Gupta 	 * interrupt from interfering with wakeup from the suspend state.
3304a8bfdb9SAchin Gupta 	 */
3314a8bfdb9SAchin Gupta 	tsp_generic_timer_save();
3324a8bfdb9SAchin Gupta 	tsp_generic_timer_stop();
3334a8bfdb9SAchin Gupta 
3344a8bfdb9SAchin Gupta 	/* Update this cpu's statistics. */
3354a8bfdb9SAchin Gupta 	tsp_stats[linear_id].smc_count++;
3364a8bfdb9SAchin Gupta 	tsp_stats[linear_id].eret_count++;
3374a8bfdb9SAchin Gupta 	tsp_stats[linear_id].cpu_suspend_count++;
3384a8bfdb9SAchin Gupta 
3394a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
3404a8bfdb9SAchin Gupta 		read_mpidr(),
3414a8bfdb9SAchin Gupta 		tsp_stats[linear_id].smc_count,
3424a8bfdb9SAchin Gupta 		tsp_stats[linear_id].eret_count,
3434a8bfdb9SAchin Gupta 		tsp_stats[linear_id].cpu_suspend_count);
3444a8bfdb9SAchin Gupta 
3454a8bfdb9SAchin Gupta 	return send_ffa_pm_success();
3464a8bfdb9SAchin Gupta }
3474a8bfdb9SAchin Gupta 
3484a8bfdb9SAchin Gupta /*******************************************************************************
3494a8bfdb9SAchin Gupta  * This function performs any bookkeeping in the test secure payload after this
3504a8bfdb9SAchin Gupta  * cpu's architectural state has been restored after wakeup from an earlier psci
3514a8bfdb9SAchin Gupta  * cpu_suspend request.
3524a8bfdb9SAchin Gupta  ******************************************************************************/
3534a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
3544a8bfdb9SAchin Gupta 				uint64_t arg1,
3554a8bfdb9SAchin Gupta 				uint64_t arg2,
3564a8bfdb9SAchin Gupta 				uint64_t arg3,
3574a8bfdb9SAchin Gupta 				uint64_t arg4,
3584a8bfdb9SAchin Gupta 				uint64_t arg5,
3594a8bfdb9SAchin Gupta 				uint64_t arg6,
3604a8bfdb9SAchin Gupta 				uint64_t arg7)
3614a8bfdb9SAchin Gupta {
3624a8bfdb9SAchin Gupta 	uint32_t linear_id = plat_my_core_pos();
3634a8bfdb9SAchin Gupta 
3644a8bfdb9SAchin Gupta 	/* Restore the generic timer context. */
3654a8bfdb9SAchin Gupta 	tsp_generic_timer_restore();
3664a8bfdb9SAchin Gupta 
3674a8bfdb9SAchin Gupta 	/* Update this cpu's statistics. */
3684a8bfdb9SAchin Gupta 	tsp_stats[linear_id].smc_count++;
3694a8bfdb9SAchin Gupta 	tsp_stats[linear_id].eret_count++;
3704a8bfdb9SAchin Gupta 	tsp_stats[linear_id].cpu_resume_count++;
3714a8bfdb9SAchin Gupta 
3724a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n",
3734a8bfdb9SAchin Gupta 	     read_mpidr(), max_off_pwrlvl);
3744a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
3754a8bfdb9SAchin Gupta 		read_mpidr(),
3764a8bfdb9SAchin Gupta 		tsp_stats[linear_id].smc_count,
3774a8bfdb9SAchin Gupta 		tsp_stats[linear_id].eret_count,
3784a8bfdb9SAchin Gupta 		tsp_stats[linear_id].cpu_resume_count);
3794a8bfdb9SAchin Gupta 
3804a8bfdb9SAchin Gupta 	return send_ffa_pm_success();
3814a8bfdb9SAchin Gupta }
3824a8bfdb9SAchin Gupta 
3834a8bfdb9SAchin Gupta /*******************************************************************************
3844a8bfdb9SAchin Gupta  * This function handles framework messages. Currently only PM.
3854a8bfdb9SAchin Gupta  ******************************************************************************/
3864a8bfdb9SAchin Gupta static smc_args_t *handle_framework_message(uint64_t arg0,
3874a8bfdb9SAchin Gupta 					    uint64_t arg1,
3884a8bfdb9SAchin Gupta 					    uint64_t arg2,
3894a8bfdb9SAchin Gupta 					    uint64_t arg3,
3904a8bfdb9SAchin Gupta 					    uint64_t arg4,
3914a8bfdb9SAchin Gupta 					    uint64_t arg5,
3924a8bfdb9SAchin Gupta 					    uint64_t arg6,
3934a8bfdb9SAchin Gupta 					    uint64_t arg7)
3944a8bfdb9SAchin Gupta {
3954a8bfdb9SAchin Gupta 	/* Check if it is a power management message from the SPMC. */
3964a8bfdb9SAchin Gupta 	if (ffa_endpoint_source(arg1) != spmc_id) {
3974a8bfdb9SAchin Gupta 		goto err;
3984a8bfdb9SAchin Gupta 	}
3994a8bfdb9SAchin Gupta 
4004a8bfdb9SAchin Gupta 	/* Check if it is a PM request message. */
4014a8bfdb9SAchin Gupta 	if ((arg2 & FFA_FWK_MSG_MASK) == FFA_FWK_MSG_PSCI) {
4024a8bfdb9SAchin Gupta 		/* Check if it is a PSCI CPU_OFF request. */
4034a8bfdb9SAchin Gupta 		if (arg3 == PSCI_CPU_OFF) {
4044a8bfdb9SAchin Gupta 			return tsp_cpu_off_main(arg0, arg1, arg2, arg3,
4054a8bfdb9SAchin Gupta 						arg4, arg5, arg6, arg7);
4064a8bfdb9SAchin Gupta 		} else if (arg3 == PSCI_CPU_SUSPEND_AARCH64) {
4074a8bfdb9SAchin Gupta 			return tsp_cpu_suspend_main(arg0, arg1, arg2, arg3,
4084a8bfdb9SAchin Gupta 						arg4, arg5, arg6, arg7);
4094a8bfdb9SAchin Gupta 		}
4104a8bfdb9SAchin Gupta 	} else if ((arg2 & FFA_FWK_MSG_MASK) == FFA_PM_MSG_WB_REQ) {
4114a8bfdb9SAchin Gupta 		/* Check it is a PSCI Warm Boot request. */
4124a8bfdb9SAchin Gupta 		if (arg3 == FFA_WB_TYPE_NOTS2RAM) {
4134a8bfdb9SAchin Gupta 			return tsp_cpu_resume_main(arg0, arg1, arg2, arg3,
4144a8bfdb9SAchin Gupta 						arg4, arg5, arg6, arg7);
4154a8bfdb9SAchin Gupta 		}
4164a8bfdb9SAchin Gupta 	}
4174a8bfdb9SAchin Gupta 
4184a8bfdb9SAchin Gupta err:
4194a8bfdb9SAchin Gupta 	ERROR("%s: Unknown framework message!\n", __func__);
4204a8bfdb9SAchin Gupta 	panic();
4214a8bfdb9SAchin Gupta }
4224a8bfdb9SAchin Gupta 
4234a8bfdb9SAchin Gupta /*******************************************************************************
424*15ca1ee3SMarc Bonnici  * Handles partition messages. Exercised from the FF-A Test Driver.
425*15ca1ee3SMarc Bonnici  ******************************************************************************/
426*15ca1ee3SMarc Bonnici static smc_args_t *handle_partition_message(uint64_t arg0,
427*15ca1ee3SMarc Bonnici 					    uint64_t arg1,
428*15ca1ee3SMarc Bonnici 					    uint64_t arg2,
429*15ca1ee3SMarc Bonnici 					    uint64_t arg3,
430*15ca1ee3SMarc Bonnici 					    uint64_t arg4,
431*15ca1ee3SMarc Bonnici 					    uint64_t arg5,
432*15ca1ee3SMarc Bonnici 					    uint64_t arg6,
433*15ca1ee3SMarc Bonnici 					    uint64_t arg7)
434*15ca1ee3SMarc Bonnici {
435*15ca1ee3SMarc Bonnici 	uint16_t sender = ffa_endpoint_source(arg1);
436*15ca1ee3SMarc Bonnici 	uint16_t receiver = ffa_endpoint_destination(arg1);
437*15ca1ee3SMarc Bonnici 	int status = -1;
438*15ca1ee3SMarc Bonnici 	const bool multi_endpoint = true;
439*15ca1ee3SMarc Bonnici 
440*15ca1ee3SMarc Bonnici 	switch (arg3) {
441*15ca1ee3SMarc Bonnici 	case FF_A_MEMORY_SHARE:
442*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Memory Share Request--\n");
443*15ca1ee3SMarc Bonnici 		status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, !multi_endpoint);
444*15ca1ee3SMarc Bonnici 		break;
445*15ca1ee3SMarc Bonnici 
446*15ca1ee3SMarc Bonnici 	case FF_A_MEMORY_LEND:
447*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Memory Lend Request--\n");
448*15ca1ee3SMarc Bonnici 		status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, !multi_endpoint);
449*15ca1ee3SMarc Bonnici 		break;
450*15ca1ee3SMarc Bonnici 
451*15ca1ee3SMarc Bonnici 	case FF_A_MEMORY_SHARE_MULTI_ENDPOINT:
452*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Multi Endpoint Memory Share Request--\n");
453*15ca1ee3SMarc Bonnici 		status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, multi_endpoint);
454*15ca1ee3SMarc Bonnici 		break;
455*15ca1ee3SMarc Bonnici 
456*15ca1ee3SMarc Bonnici 	case FF_A_MEMORY_LEND_MULTI_ENDPOINT:
457*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Multi Endpoint Memory Lend Request--\n");
458*15ca1ee3SMarc Bonnici 		status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, multi_endpoint);
459*15ca1ee3SMarc Bonnici 		break;
460*15ca1ee3SMarc Bonnici 	case FF_A_RELAY_MESSAGE:
461*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Relaying message--\n");
462*15ca1ee3SMarc Bonnici 		status = ffa_test_relay(arg0, arg1, arg2, arg3, arg4,
463*15ca1ee3SMarc Bonnici 					arg5, arg6, arg7);
464*15ca1ee3SMarc Bonnici 		break;
465*15ca1ee3SMarc Bonnici 
466*15ca1ee3SMarc Bonnici 	case FF_A_ECHO_MESSAGE:
467*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: echo message--\n");
468*15ca1ee3SMarc Bonnici 		status = arg4;
469*15ca1ee3SMarc Bonnici 		break;
470*15ca1ee3SMarc Bonnici 
471*15ca1ee3SMarc Bonnici 	default:
472*15ca1ee3SMarc Bonnici 		INFO("TSP Tests: Unknown request ID %d--\n", (int) arg3);
473*15ca1ee3SMarc Bonnici 	}
474*15ca1ee3SMarc Bonnici 
475*15ca1ee3SMarc Bonnici 	/* Swap the sender and receiver in the response. */
476*15ca1ee3SMarc Bonnici 	return ffa_msg_send_direct_resp(receiver, sender, status, 0, 0, 0, 0);
477*15ca1ee3SMarc Bonnici }
478*15ca1ee3SMarc Bonnici 
479*15ca1ee3SMarc Bonnici /*******************************************************************************
4804a8bfdb9SAchin Gupta  * This function implements the event loop for handling FF-A ABI invocations.
4814a8bfdb9SAchin Gupta  ******************************************************************************/
4824a8bfdb9SAchin Gupta static smc_args_t *tsp_event_loop(uint64_t smc_fid,
4834a8bfdb9SAchin Gupta 				  uint64_t arg1,
4844a8bfdb9SAchin Gupta 				  uint64_t arg2,
4854a8bfdb9SAchin Gupta 				  uint64_t arg3,
4864a8bfdb9SAchin Gupta 				  uint64_t arg4,
4874a8bfdb9SAchin Gupta 				  uint64_t arg5,
4884a8bfdb9SAchin Gupta 				  uint64_t arg6,
4894a8bfdb9SAchin Gupta 				  uint64_t arg7)
4904a8bfdb9SAchin Gupta {
4914a8bfdb9SAchin Gupta 	/* Panic if the SPMC did not forward an FF-A call. */
4924a8bfdb9SAchin Gupta 	if (!is_ffa_fid(smc_fid)) {
4934a8bfdb9SAchin Gupta 		ERROR("%s: Unknown SMC FID (0x%lx)\n", __func__, smc_fid);
4944a8bfdb9SAchin Gupta 		panic();
4954a8bfdb9SAchin Gupta 	}
4964a8bfdb9SAchin Gupta 
4974a8bfdb9SAchin Gupta 	switch (smc_fid) {
4984a8bfdb9SAchin Gupta 	case FFA_INTERRUPT:
4994a8bfdb9SAchin Gupta 		/*
5004a8bfdb9SAchin Gupta 		 * IRQs were enabled upon re-entry into the TSP. The interrupt
5014a8bfdb9SAchin Gupta 		 * must have been handled by now. Return to the SPMC indicating
5024a8bfdb9SAchin Gupta 		 * the same.
5034a8bfdb9SAchin Gupta 		 */
5044a8bfdb9SAchin Gupta 		return set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0);
5054a8bfdb9SAchin Gupta 
506*15ca1ee3SMarc Bonnici 	case FFA_MSG_SEND_DIRECT_REQ_SMC64:
5074a8bfdb9SAchin Gupta 	case FFA_MSG_SEND_DIRECT_REQ_SMC32:
5084a8bfdb9SAchin Gupta 		/* Check if a framework message, handle accordingly. */
5094a8bfdb9SAchin Gupta 		if ((arg2 & FFA_FWK_MSG_BIT)) {
5104a8bfdb9SAchin Gupta 			return handle_framework_message(smc_fid, arg1, arg2, arg3,
5114a8bfdb9SAchin Gupta 							arg4, arg5, arg6, arg7);
5124a8bfdb9SAchin Gupta 		}
513*15ca1ee3SMarc Bonnici 		return handle_partition_message(smc_fid, arg1, arg2, arg3,
514*15ca1ee3SMarc Bonnici 							arg4, arg5, arg6, arg7);
5154a8bfdb9SAchin Gupta 	}
5164a8bfdb9SAchin Gupta 
5174a8bfdb9SAchin Gupta 	ERROR("%s: Unsupported FF-A FID (0x%lx)\n", __func__, smc_fid);
5184a8bfdb9SAchin Gupta 	panic();
5194a8bfdb9SAchin Gupta }
5204a8bfdb9SAchin Gupta 
5214a8bfdb9SAchin Gupta static smc_args_t *tsp_loop(smc_args_t *args)
5224a8bfdb9SAchin Gupta {
5234a8bfdb9SAchin Gupta 	smc_args_t ret;
5244a8bfdb9SAchin Gupta 
5254a8bfdb9SAchin Gupta 	do {
5264a8bfdb9SAchin Gupta 		/* --------------------------------------------
5274a8bfdb9SAchin Gupta 		 * Mask FIQ interrupts to avoid preemption
5284a8bfdb9SAchin Gupta 		 * in case EL3 SPMC delegates an IRQ next or a
5294a8bfdb9SAchin Gupta 		 * managed exit. Lastly, unmask IRQs so that
530*15ca1ee3SMarc Bonnici 		 * they can be handled immediately upon re-entry.
5314a8bfdb9SAchin Gupta 		 *  ---------------------------------------------
5324a8bfdb9SAchin Gupta 		 */
5334a8bfdb9SAchin Gupta 		write_daifset(DAIF_FIQ_BIT);
5344a8bfdb9SAchin Gupta 		write_daifclr(DAIF_IRQ_BIT);
5354a8bfdb9SAchin Gupta 		ret = smc_helper(args->_regs[0], args->_regs[1], args->_regs[2],
5364a8bfdb9SAchin Gupta 			       args->_regs[3], args->_regs[4], args->_regs[5],
5374a8bfdb9SAchin Gupta 			       args->_regs[6], args->_regs[7]);
5384a8bfdb9SAchin Gupta 		args = tsp_event_loop(ret._regs[0], ret._regs[1], ret._regs[2],
5394a8bfdb9SAchin Gupta 				ret._regs[3], ret._regs[4], ret._regs[5],
5404a8bfdb9SAchin Gupta 				ret._regs[6], ret._regs[7]);
5414a8bfdb9SAchin Gupta 	} while (1);
5424a8bfdb9SAchin Gupta 
5434a8bfdb9SAchin Gupta 	/* Not Reached. */
5444a8bfdb9SAchin Gupta 	return NULL;
5454a8bfdb9SAchin Gupta }
5464a8bfdb9SAchin Gupta 
5474a8bfdb9SAchin Gupta /*******************************************************************************
5484a8bfdb9SAchin Gupta  * TSP main entry point where it gets the opportunity to initialize its secure
5494a8bfdb9SAchin Gupta  * state/applications. Once the state is initialized, it must return to the
5504a8bfdb9SAchin Gupta  * SPD with a pointer to the 'tsp_vector_table' jump table.
5514a8bfdb9SAchin Gupta  ******************************************************************************/
5524a8bfdb9SAchin Gupta uint64_t tsp_main(void)
5534a8bfdb9SAchin Gupta {
5544a8bfdb9SAchin Gupta 	smc_args_t smc_args = {0};
5554a8bfdb9SAchin Gupta 
5564a8bfdb9SAchin Gupta 	NOTICE("TSP: %s\n", version_string);
5574a8bfdb9SAchin Gupta 	NOTICE("TSP: %s\n", build_message);
5584a8bfdb9SAchin Gupta 	INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
5594a8bfdb9SAchin Gupta 	INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
5604a8bfdb9SAchin Gupta 	uint32_t linear_id = plat_my_core_pos();
5614a8bfdb9SAchin Gupta 
5624a8bfdb9SAchin Gupta 	/* Initialize the platform. */
5634a8bfdb9SAchin Gupta 	tsp_platform_setup();
5644a8bfdb9SAchin Gupta 
5654a8bfdb9SAchin Gupta 	/* Initialize secure/applications state here. */
5664a8bfdb9SAchin Gupta 	tsp_generic_timer_start();
5674a8bfdb9SAchin Gupta 
5684a8bfdb9SAchin Gupta 	/* Register secondary entrypoint with the SPMC. */
5694a8bfdb9SAchin Gupta 	smc_args = smc_helper(FFA_SECONDARY_EP_REGISTER_SMC64,
5704a8bfdb9SAchin Gupta 			(uint64_t) tsp_cpu_on_entry,
5714a8bfdb9SAchin Gupta 			0, 0, 0, 0, 0, 0);
5724a8bfdb9SAchin Gupta 	if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
5734a8bfdb9SAchin Gupta 		ERROR("TSP could not register secondary ep (0x%lx)\n",
5744a8bfdb9SAchin Gupta 				smc_args._regs[2]);
5754a8bfdb9SAchin Gupta 		panic();
5764a8bfdb9SAchin Gupta 	}
577*15ca1ee3SMarc Bonnici 	/* Get TSP's endpoint id. */
5784a8bfdb9SAchin Gupta 	smc_args = smc_helper(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0);
5794a8bfdb9SAchin Gupta 	if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
5804a8bfdb9SAchin Gupta 		ERROR("TSP could not get own ID (0x%lx) on core%d\n",
5814a8bfdb9SAchin Gupta 				smc_args._regs[2], linear_id);
5824a8bfdb9SAchin Gupta 		panic();
5834a8bfdb9SAchin Gupta 	}
5844a8bfdb9SAchin Gupta 
5854a8bfdb9SAchin Gupta 	tsp_id = smc_args._regs[2];
5864a8bfdb9SAchin Gupta 	INFO("TSP FF-A endpoint id = 0x%x\n", tsp_id);
587*15ca1ee3SMarc Bonnici 
588*15ca1ee3SMarc Bonnici 	/* Get the SPMC ID. */
5894a8bfdb9SAchin Gupta 	smc_args = smc_helper(FFA_SPM_ID_GET, 0, 0, 0, 0, 0, 0, 0);
5904a8bfdb9SAchin Gupta 	if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
5914a8bfdb9SAchin Gupta 		ERROR("TSP could not get SPMC ID (0x%lx) on core%d\n",
5924a8bfdb9SAchin Gupta 				smc_args._regs[2], linear_id);
5934a8bfdb9SAchin Gupta 		panic();
5944a8bfdb9SAchin Gupta 	}
5954a8bfdb9SAchin Gupta 
5964a8bfdb9SAchin Gupta 	spmc_id = smc_args._regs[2];
5974a8bfdb9SAchin Gupta 
598*15ca1ee3SMarc Bonnici 	/* Call RXTX_MAP to map a 4k RX and TX buffer. */
599*15ca1ee3SMarc Bonnici 	if (ffa_rxtx_map((uintptr_t) send_page,
600*15ca1ee3SMarc Bonnici 			 (uintptr_t) recv_page, 1)) {
601*15ca1ee3SMarc Bonnici 		ERROR("TSP could not map it's RX/TX Buffers\n");
602*15ca1ee3SMarc Bonnici 		panic();
603*15ca1ee3SMarc Bonnici 	}
604*15ca1ee3SMarc Bonnici 
605*15ca1ee3SMarc Bonnici 	mailbox.tx_buffer = send_page;
606*15ca1ee3SMarc Bonnici 	mailbox.rx_buffer = recv_page;
607*15ca1ee3SMarc Bonnici 	mailbox.rxtx_page_count = 1;
608*15ca1ee3SMarc Bonnici 
609*15ca1ee3SMarc Bonnici 	/* Update this cpu's statistics. */
6104a8bfdb9SAchin Gupta 	tsp_stats[linear_id].smc_count++;
6114a8bfdb9SAchin Gupta 	tsp_stats[linear_id].eret_count++;
6124a8bfdb9SAchin Gupta 	tsp_stats[linear_id].cpu_on_count++;
6134a8bfdb9SAchin Gupta 
6144a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
6154a8bfdb9SAchin Gupta 			read_mpidr(),
6164a8bfdb9SAchin Gupta 			tsp_stats[linear_id].smc_count,
6174a8bfdb9SAchin Gupta 			tsp_stats[linear_id].eret_count,
6184a8bfdb9SAchin Gupta 			tsp_stats[linear_id].cpu_on_count);
6194a8bfdb9SAchin Gupta 
6204a8bfdb9SAchin Gupta 	/* Tell SPMD that we are done initialising. */
6214a8bfdb9SAchin Gupta 	tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0));
6224a8bfdb9SAchin Gupta 
6234a8bfdb9SAchin Gupta 	/* Not reached. */
6244a8bfdb9SAchin Gupta 	return 0;
6254a8bfdb9SAchin Gupta }
6264a8bfdb9SAchin Gupta 
6274a8bfdb9SAchin Gupta /*******************************************************************************
6284a8bfdb9SAchin Gupta  * This function performs any remaining book keeping in the test secure payload
6294a8bfdb9SAchin Gupta  * after this cpu's architectural state has been setup in response to an earlier
6304a8bfdb9SAchin Gupta  * psci cpu_on request.
6314a8bfdb9SAchin Gupta  ******************************************************************************/
6324a8bfdb9SAchin Gupta smc_args_t *tsp_cpu_on_main(void)
6334a8bfdb9SAchin Gupta {
6344a8bfdb9SAchin Gupta 	uint32_t linear_id = plat_my_core_pos();
6354a8bfdb9SAchin Gupta 
6364a8bfdb9SAchin Gupta 	/* Initialize secure/applications state here. */
6374a8bfdb9SAchin Gupta 	tsp_generic_timer_start();
6384a8bfdb9SAchin Gupta 
6394a8bfdb9SAchin Gupta 	/* Update this cpu's statistics. */
6404a8bfdb9SAchin Gupta 	tsp_stats[linear_id].smc_count++;
6414a8bfdb9SAchin Gupta 	tsp_stats[linear_id].eret_count++;
6424a8bfdb9SAchin Gupta 	tsp_stats[linear_id].cpu_on_count++;
6434a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
6444a8bfdb9SAchin Gupta 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
6454a8bfdb9SAchin Gupta 			read_mpidr(),
6464a8bfdb9SAchin Gupta 			tsp_stats[linear_id].smc_count,
6474a8bfdb9SAchin Gupta 			tsp_stats[linear_id].eret_count,
6484a8bfdb9SAchin Gupta 			tsp_stats[linear_id].cpu_on_count);
6494a8bfdb9SAchin Gupta 	/* ---------------------------------------------
6504a8bfdb9SAchin Gupta 	 * Jump to the main event loop to return to EL3
6514a8bfdb9SAchin Gupta 	 * and be ready for the next request on this cpu.
6524a8bfdb9SAchin Gupta 	 * ---------------------------------------------
6534a8bfdb9SAchin Gupta 	 */
6544a8bfdb9SAchin Gupta 	return tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0));
6554a8bfdb9SAchin Gupta }
656