1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4*54fd6939SJiyong Park *
5*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
6*54fd6939SJiyong Park */
7*54fd6939SJiyong Park
8*54fd6939SJiyong Park /*******************************************************************************
9*54fd6939SJiyong Park * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
10*54fd6939SJiyong Park * plug-in component to the Secure Monitor, registered as a runtime service. The
11*54fd6939SJiyong Park * SPD is expected to be a functional extension of the Secure Payload (SP) that
12*54fd6939SJiyong Park * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
13*54fd6939SJiyong Park * the Trusted OS/Applications range to the dispatcher. The SPD will either
14*54fd6939SJiyong Park * handle the request locally or delegate it to the Secure Payload. It is also
15*54fd6939SJiyong Park * responsible for initialising and maintaining communication with the SP.
16*54fd6939SJiyong Park ******************************************************************************/
17*54fd6939SJiyong Park #include <assert.h>
18*54fd6939SJiyong Park #include <bl31/interrupt_mgmt.h>
19*54fd6939SJiyong Park #include <errno.h>
20*54fd6939SJiyong Park #include <stddef.h>
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park #include <arch_helpers.h>
23*54fd6939SJiyong Park #include <bl31/bl31.h>
24*54fd6939SJiyong Park #include <bl32/payloads/tlk.h>
25*54fd6939SJiyong Park #include <common/bl_common.h>
26*54fd6939SJiyong Park #include <common/debug.h>
27*54fd6939SJiyong Park #include <common/runtime_svc.h>
28*54fd6939SJiyong Park #include <lib/el3_runtime/context_mgmt.h>
29*54fd6939SJiyong Park #include <plat/common/platform.h>
30*54fd6939SJiyong Park #include <tools_share/uuid.h>
31*54fd6939SJiyong Park
32*54fd6939SJiyong Park #include "tlkd_private.h"
33*54fd6939SJiyong Park
34*54fd6939SJiyong Park extern const spd_pm_ops_t tlkd_pm_ops;
35*54fd6939SJiyong Park
36*54fd6939SJiyong Park /*******************************************************************************
37*54fd6939SJiyong Park * Per-cpu Secure Payload state
38*54fd6939SJiyong Park ******************************************************************************/
39*54fd6939SJiyong Park tlk_context_t tlk_ctx;
40*54fd6939SJiyong Park
41*54fd6939SJiyong Park /*******************************************************************************
42*54fd6939SJiyong Park * CPU number on which TLK booted up
43*54fd6939SJiyong Park ******************************************************************************/
44*54fd6939SJiyong Park static uint32_t boot_cpu;
45*54fd6939SJiyong Park
46*54fd6939SJiyong Park /* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */
47*54fd6939SJiyong Park DEFINE_SVC_UUID2(tlk_uuid,
48*54fd6939SJiyong Park 0xc9e911bd, 0xba2b, 0xee52, 0xb1, 0x72,
49*54fd6939SJiyong Park 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63);
50*54fd6939SJiyong Park
51*54fd6939SJiyong Park static int32_t tlkd_init(void);
52*54fd6939SJiyong Park
53*54fd6939SJiyong Park /*******************************************************************************
54*54fd6939SJiyong Park * Secure Payload Dispatcher's timer interrupt handler
55*54fd6939SJiyong Park ******************************************************************************/
tlkd_interrupt_handler(uint32_t id,uint32_t flags,void * handle,void * cookie)56*54fd6939SJiyong Park static uint64_t tlkd_interrupt_handler(uint32_t id,
57*54fd6939SJiyong Park uint32_t flags,
58*54fd6939SJiyong Park void *handle,
59*54fd6939SJiyong Park void *cookie)
60*54fd6939SJiyong Park {
61*54fd6939SJiyong Park cpu_context_t *s_cpu_context;
62*54fd6939SJiyong Park int irq = plat_ic_get_pending_interrupt_id();
63*54fd6939SJiyong Park
64*54fd6939SJiyong Park /* acknowledge the interrupt and mark it complete */
65*54fd6939SJiyong Park (void)plat_ic_acknowledge_interrupt();
66*54fd6939SJiyong Park plat_ic_end_of_interrupt(irq);
67*54fd6939SJiyong Park
68*54fd6939SJiyong Park /*
69*54fd6939SJiyong Park * Disable the routing of NS interrupts from secure world to
70*54fd6939SJiyong Park * EL3 while interrupted on this core.
71*54fd6939SJiyong Park */
72*54fd6939SJiyong Park disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE);
73*54fd6939SJiyong Park
74*54fd6939SJiyong Park /* Check the security state when the exception was generated */
75*54fd6939SJiyong Park assert(get_interrupt_src_ss(flags) == NON_SECURE);
76*54fd6939SJiyong Park assert(handle == cm_get_context(NON_SECURE));
77*54fd6939SJiyong Park
78*54fd6939SJiyong Park /* Save non-secure state */
79*54fd6939SJiyong Park cm_el1_sysregs_context_save(NON_SECURE);
80*54fd6939SJiyong Park
81*54fd6939SJiyong Park /* Get a reference to the secure context */
82*54fd6939SJiyong Park s_cpu_context = cm_get_context(SECURE);
83*54fd6939SJiyong Park assert(s_cpu_context);
84*54fd6939SJiyong Park
85*54fd6939SJiyong Park /*
86*54fd6939SJiyong Park * Restore non-secure state. There is no need to save the
87*54fd6939SJiyong Park * secure system register context since the SP was supposed
88*54fd6939SJiyong Park * to preserve it during S-EL1 interrupt handling.
89*54fd6939SJiyong Park */
90*54fd6939SJiyong Park cm_el1_sysregs_context_restore(SECURE);
91*54fd6939SJiyong Park cm_set_next_eret_context(SECURE);
92*54fd6939SJiyong Park
93*54fd6939SJiyong Park /* Provide the IRQ number to the SPD */
94*54fd6939SJiyong Park SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0);
95*54fd6939SJiyong Park }
96*54fd6939SJiyong Park
97*54fd6939SJiyong Park /*******************************************************************************
98*54fd6939SJiyong Park * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
99*54fd6939SJiyong Park * (aarch32/aarch64) if not already known and initialises the context for entry
100*54fd6939SJiyong Park * into the SP for its initialisation.
101*54fd6939SJiyong Park ******************************************************************************/
tlkd_setup(void)102*54fd6939SJiyong Park static int32_t tlkd_setup(void)
103*54fd6939SJiyong Park {
104*54fd6939SJiyong Park entry_point_info_t *tlk_ep_info;
105*54fd6939SJiyong Park uint32_t flags;
106*54fd6939SJiyong Park int32_t ret;
107*54fd6939SJiyong Park
108*54fd6939SJiyong Park /*
109*54fd6939SJiyong Park * Get information about the Secure Payload (BL32) image. Its
110*54fd6939SJiyong Park * absence is a critical failure.
111*54fd6939SJiyong Park */
112*54fd6939SJiyong Park tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
113*54fd6939SJiyong Park if (!tlk_ep_info) {
114*54fd6939SJiyong Park WARN("No SP provided. Booting device without SP"
115*54fd6939SJiyong Park " initialization. SMC`s destined for SP"
116*54fd6939SJiyong Park " will return SMC_UNK\n");
117*54fd6939SJiyong Park return 1;
118*54fd6939SJiyong Park }
119*54fd6939SJiyong Park
120*54fd6939SJiyong Park /*
121*54fd6939SJiyong Park * If there's no valid entry point for SP, we return a non-zero value
122*54fd6939SJiyong Park * signalling failure initializing the service. We bail out without
123*54fd6939SJiyong Park * registering any handlers
124*54fd6939SJiyong Park */
125*54fd6939SJiyong Park if (!tlk_ep_info->pc)
126*54fd6939SJiyong Park return 1;
127*54fd6939SJiyong Park
128*54fd6939SJiyong Park /*
129*54fd6939SJiyong Park * Inspect the SP image's SPSR and determine it's execution state
130*54fd6939SJiyong Park * i.e whether AArch32 or AArch64.
131*54fd6939SJiyong Park */
132*54fd6939SJiyong Park tlkd_init_tlk_ep_state(tlk_ep_info,
133*54fd6939SJiyong Park (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK,
134*54fd6939SJiyong Park tlk_ep_info->pc,
135*54fd6939SJiyong Park &tlk_ctx);
136*54fd6939SJiyong Park
137*54fd6939SJiyong Park /* get a list of all S-EL1 IRQs from the platform */
138*54fd6939SJiyong Park
139*54fd6939SJiyong Park /* register interrupt handler */
140*54fd6939SJiyong Park flags = 0;
141*54fd6939SJiyong Park set_interrupt_rm_flag(flags, NON_SECURE);
142*54fd6939SJiyong Park ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
143*54fd6939SJiyong Park tlkd_interrupt_handler,
144*54fd6939SJiyong Park flags);
145*54fd6939SJiyong Park if (ret != 0) {
146*54fd6939SJiyong Park ERROR("failed to register tlkd interrupt handler (%d)\n", ret);
147*54fd6939SJiyong Park }
148*54fd6939SJiyong Park
149*54fd6939SJiyong Park /*
150*54fd6939SJiyong Park * All TLK SPD initialization done. Now register our init function
151*54fd6939SJiyong Park * with BL31 for deferred invocation
152*54fd6939SJiyong Park */
153*54fd6939SJiyong Park bl31_register_bl32_init(&tlkd_init);
154*54fd6939SJiyong Park
155*54fd6939SJiyong Park return 0;
156*54fd6939SJiyong Park }
157*54fd6939SJiyong Park
158*54fd6939SJiyong Park /*******************************************************************************
159*54fd6939SJiyong Park * This function passes control to the Secure Payload image (BL32) for the first
160*54fd6939SJiyong Park * time on the primary cpu after a cold boot. It assumes that a valid secure
161*54fd6939SJiyong Park * context has already been created by tlkd_setup() which can be directly
162*54fd6939SJiyong Park * used. This function performs a synchronous entry into the Secure payload.
163*54fd6939SJiyong Park * The SP passes control back to this routine through a SMC.
164*54fd6939SJiyong Park ******************************************************************************/
tlkd_init(void)165*54fd6939SJiyong Park static int32_t tlkd_init(void)
166*54fd6939SJiyong Park {
167*54fd6939SJiyong Park entry_point_info_t *tlk_entry_point;
168*54fd6939SJiyong Park
169*54fd6939SJiyong Park /*
170*54fd6939SJiyong Park * Get information about the Secure Payload (BL32) image. Its
171*54fd6939SJiyong Park * absence is a critical failure.
172*54fd6939SJiyong Park */
173*54fd6939SJiyong Park tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
174*54fd6939SJiyong Park assert(tlk_entry_point);
175*54fd6939SJiyong Park
176*54fd6939SJiyong Park cm_init_my_context(tlk_entry_point);
177*54fd6939SJiyong Park
178*54fd6939SJiyong Park /*
179*54fd6939SJiyong Park * TLK runs only on a single CPU. Store the value of the boot
180*54fd6939SJiyong Park * CPU for sanity checking later.
181*54fd6939SJiyong Park */
182*54fd6939SJiyong Park boot_cpu = plat_my_core_pos();
183*54fd6939SJiyong Park
184*54fd6939SJiyong Park /*
185*54fd6939SJiyong Park * Arrange for an entry into the test secure payload.
186*54fd6939SJiyong Park */
187*54fd6939SJiyong Park return tlkd_synchronous_sp_entry(&tlk_ctx);
188*54fd6939SJiyong Park }
189*54fd6939SJiyong Park
190*54fd6939SJiyong Park /*******************************************************************************
191*54fd6939SJiyong Park * This function is responsible for handling all SMCs in the Trusted OS/App
192*54fd6939SJiyong Park * range from the non-secure state as defined in the SMC Calling Convention
193*54fd6939SJiyong Park * Document. It is also responsible for communicating with the Secure payload
194*54fd6939SJiyong Park * to delegate work and return results back to the non-secure state. Lastly it
195*54fd6939SJiyong Park * will also return any information that the secure payload needs to do the
196*54fd6939SJiyong Park * work assigned to it.
197*54fd6939SJiyong Park ******************************************************************************/
tlkd_smc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)198*54fd6939SJiyong Park static uintptr_t tlkd_smc_handler(uint32_t smc_fid,
199*54fd6939SJiyong Park u_register_t x1,
200*54fd6939SJiyong Park u_register_t x2,
201*54fd6939SJiyong Park u_register_t x3,
202*54fd6939SJiyong Park u_register_t x4,
203*54fd6939SJiyong Park void *cookie,
204*54fd6939SJiyong Park void *handle,
205*54fd6939SJiyong Park u_register_t flags)
206*54fd6939SJiyong Park {
207*54fd6939SJiyong Park cpu_context_t *ns_cpu_context;
208*54fd6939SJiyong Park gp_regs_t *gp_regs;
209*54fd6939SJiyong Park uint32_t ns;
210*54fd6939SJiyong Park uint64_t par;
211*54fd6939SJiyong Park
212*54fd6939SJiyong Park /* Passing a NULL context is a critical programming error */
213*54fd6939SJiyong Park assert(handle);
214*54fd6939SJiyong Park
215*54fd6939SJiyong Park /* These SMCs are only supported by a single CPU */
216*54fd6939SJiyong Park if (boot_cpu != plat_my_core_pos())
217*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
218*54fd6939SJiyong Park
219*54fd6939SJiyong Park /* Determine which security state this SMC originated from */
220*54fd6939SJiyong Park ns = is_caller_non_secure(flags);
221*54fd6939SJiyong Park
222*54fd6939SJiyong Park switch (smc_fid) {
223*54fd6939SJiyong Park
224*54fd6939SJiyong Park /*
225*54fd6939SJiyong Park * This function ID is used by SP to indicate that it was
226*54fd6939SJiyong Park * preempted by a non-secure world IRQ.
227*54fd6939SJiyong Park */
228*54fd6939SJiyong Park case TLK_PREEMPTED:
229*54fd6939SJiyong Park
230*54fd6939SJiyong Park if (ns)
231*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
232*54fd6939SJiyong Park
233*54fd6939SJiyong Park assert(handle == cm_get_context(SECURE));
234*54fd6939SJiyong Park cm_el1_sysregs_context_save(SECURE);
235*54fd6939SJiyong Park
236*54fd6939SJiyong Park /* Get a reference to the non-secure context */
237*54fd6939SJiyong Park ns_cpu_context = cm_get_context(NON_SECURE);
238*54fd6939SJiyong Park assert(ns_cpu_context);
239*54fd6939SJiyong Park
240*54fd6939SJiyong Park /*
241*54fd6939SJiyong Park * Restore non-secure state. There is no need to save the
242*54fd6939SJiyong Park * secure system register context since the SP was supposed
243*54fd6939SJiyong Park * to preserve it during S-EL1 interrupt handling.
244*54fd6939SJiyong Park */
245*54fd6939SJiyong Park cm_el1_sysregs_context_restore(NON_SECURE);
246*54fd6939SJiyong Park cm_set_next_eret_context(NON_SECURE);
247*54fd6939SJiyong Park
248*54fd6939SJiyong Park SMC_RET1(ns_cpu_context, x1);
249*54fd6939SJiyong Park
250*54fd6939SJiyong Park /*
251*54fd6939SJiyong Park * This is a request from the non-secure context to:
252*54fd6939SJiyong Park *
253*54fd6939SJiyong Park * a. register shared memory with the SP for storing it's
254*54fd6939SJiyong Park * activity logs.
255*54fd6939SJiyong Park * b. register shared memory with the SP for passing args
256*54fd6939SJiyong Park * required for maintaining sessions with the Trusted
257*54fd6939SJiyong Park * Applications.
258*54fd6939SJiyong Park * c. register shared persistent buffers for secure storage
259*54fd6939SJiyong Park * d. register NS DRAM ranges passed by Cboot
260*54fd6939SJiyong Park * e. register Root of Trust parameters from Cboot for Verified Boot
261*54fd6939SJiyong Park * f. open/close sessions
262*54fd6939SJiyong Park * g. issue commands to the Trusted Apps
263*54fd6939SJiyong Park * h. resume the preempted yielding SMC call.
264*54fd6939SJiyong Park */
265*54fd6939SJiyong Park case TLK_REGISTER_LOGBUF:
266*54fd6939SJiyong Park case TLK_REGISTER_REQBUF:
267*54fd6939SJiyong Park case TLK_SS_REGISTER_HANDLER:
268*54fd6939SJiyong Park case TLK_REGISTER_NS_DRAM_RANGES:
269*54fd6939SJiyong Park case TLK_SET_ROOT_OF_TRUST:
270*54fd6939SJiyong Park case TLK_OPEN_TA_SESSION:
271*54fd6939SJiyong Park case TLK_CLOSE_TA_SESSION:
272*54fd6939SJiyong Park case TLK_TA_LAUNCH_OP:
273*54fd6939SJiyong Park case TLK_TA_SEND_EVENT:
274*54fd6939SJiyong Park case TLK_RESUME_FID:
275*54fd6939SJiyong Park case TLK_SET_BL_VERSION:
276*54fd6939SJiyong Park case TLK_LOCK_BL_INTERFACE:
277*54fd6939SJiyong Park case TLK_BL_RPMB_SERVICE:
278*54fd6939SJiyong Park
279*54fd6939SJiyong Park if (!ns)
280*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
281*54fd6939SJiyong Park
282*54fd6939SJiyong Park /*
283*54fd6939SJiyong Park * This is a fresh request from the non-secure client.
284*54fd6939SJiyong Park * The parameters are in x1 and x2. Figure out which
285*54fd6939SJiyong Park * registers need to be preserved, save the non-secure
286*54fd6939SJiyong Park * state and send the request to the secure payload.
287*54fd6939SJiyong Park */
288*54fd6939SJiyong Park assert(handle == cm_get_context(NON_SECURE));
289*54fd6939SJiyong Park
290*54fd6939SJiyong Park /*
291*54fd6939SJiyong Park * Check if we are already processing a yielding SMC
292*54fd6939SJiyong Park * call. Of all the supported fids, only the "resume"
293*54fd6939SJiyong Park * fid expects the flag to be set.
294*54fd6939SJiyong Park */
295*54fd6939SJiyong Park if (smc_fid == TLK_RESUME_FID) {
296*54fd6939SJiyong Park if (!get_yield_smc_active_flag(tlk_ctx.state))
297*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
298*54fd6939SJiyong Park } else {
299*54fd6939SJiyong Park if (get_yield_smc_active_flag(tlk_ctx.state))
300*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
301*54fd6939SJiyong Park }
302*54fd6939SJiyong Park
303*54fd6939SJiyong Park cm_el1_sysregs_context_save(NON_SECURE);
304*54fd6939SJiyong Park
305*54fd6939SJiyong Park /*
306*54fd6939SJiyong Park * Verify if there is a valid context to use.
307*54fd6939SJiyong Park */
308*54fd6939SJiyong Park assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE));
309*54fd6939SJiyong Park
310*54fd6939SJiyong Park /*
311*54fd6939SJiyong Park * Mark the SP state as active.
312*54fd6939SJiyong Park */
313*54fd6939SJiyong Park set_yield_smc_active_flag(tlk_ctx.state);
314*54fd6939SJiyong Park
315*54fd6939SJiyong Park /*
316*54fd6939SJiyong Park * We are done stashing the non-secure context. Ask the
317*54fd6939SJiyong Park * secure payload to do the work now.
318*54fd6939SJiyong Park */
319*54fd6939SJiyong Park cm_el1_sysregs_context_restore(SECURE);
320*54fd6939SJiyong Park cm_set_next_eret_context(SECURE);
321*54fd6939SJiyong Park
322*54fd6939SJiyong Park /*
323*54fd6939SJiyong Park * TLK is a 32-bit Trusted OS and so expects the SMC
324*54fd6939SJiyong Park * arguments via r0-r7. TLK expects the monitor frame
325*54fd6939SJiyong Park * registers to be 64-bits long. Hence, we pass x0 in
326*54fd6939SJiyong Park * r0-r1, x1 in r2-r3, x3 in r4-r5 and x4 in r6-r7.
327*54fd6939SJiyong Park *
328*54fd6939SJiyong Park * As smc_fid is a uint32 value, r1 contains 0.
329*54fd6939SJiyong Park */
330*54fd6939SJiyong Park gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx);
331*54fd6939SJiyong Park write_ctx_reg(gp_regs, CTX_GPREG_X4, (uint32_t)x2);
332*54fd6939SJiyong Park write_ctx_reg(gp_regs, CTX_GPREG_X5, (uint32_t)(x2 >> 32));
333*54fd6939SJiyong Park write_ctx_reg(gp_regs, CTX_GPREG_X6, (uint32_t)x3);
334*54fd6939SJiyong Park write_ctx_reg(gp_regs, CTX_GPREG_X7, (uint32_t)(x3 >> 32));
335*54fd6939SJiyong Park SMC_RET4(&tlk_ctx.cpu_ctx, smc_fid, 0, (uint32_t)x1,
336*54fd6939SJiyong Park (uint32_t)(x1 >> 32));
337*54fd6939SJiyong Park
338*54fd6939SJiyong Park /*
339*54fd6939SJiyong Park * Translate NS/EL1-S virtual addresses.
340*54fd6939SJiyong Park *
341*54fd6939SJiyong Park * x1 = virtual address
342*54fd6939SJiyong Park * x3 = type (NS/S)
343*54fd6939SJiyong Park *
344*54fd6939SJiyong Park * Returns PA:lo in r0, PA:hi in r1.
345*54fd6939SJiyong Park */
346*54fd6939SJiyong Park case TLK_VA_TRANSLATE:
347*54fd6939SJiyong Park
348*54fd6939SJiyong Park /* Should be invoked only by secure world */
349*54fd6939SJiyong Park if (ns)
350*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
351*54fd6939SJiyong Park
352*54fd6939SJiyong Park /* NS virtual addresses are 64-bit long */
353*54fd6939SJiyong Park if (x3 & TLK_TRANSLATE_NS_VADDR)
354*54fd6939SJiyong Park x1 = (uint32_t)x1 | (x2 << 32);
355*54fd6939SJiyong Park
356*54fd6939SJiyong Park if (!x1)
357*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
358*54fd6939SJiyong Park
359*54fd6939SJiyong Park /*
360*54fd6939SJiyong Park * TODO: Sanity check x1. This would require platform
361*54fd6939SJiyong Park * support.
362*54fd6939SJiyong Park */
363*54fd6939SJiyong Park
364*54fd6939SJiyong Park /* virtual address and type: ns/s */
365*54fd6939SJiyong Park par = tlkd_va_translate(x1, x3);
366*54fd6939SJiyong Park
367*54fd6939SJiyong Park /* return physical address in r0-r1 */
368*54fd6939SJiyong Park SMC_RET4(handle, (uint32_t)par, (uint32_t)(par >> 32), 0, 0);
369*54fd6939SJiyong Park
370*54fd6939SJiyong Park /*
371*54fd6939SJiyong Park * This is a request from the SP to mark completion of
372*54fd6939SJiyong Park * a yielding function ID.
373*54fd6939SJiyong Park */
374*54fd6939SJiyong Park case TLK_REQUEST_DONE:
375*54fd6939SJiyong Park if (ns)
376*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
377*54fd6939SJiyong Park
378*54fd6939SJiyong Park /*
379*54fd6939SJiyong Park * Mark the SP state as inactive.
380*54fd6939SJiyong Park */
381*54fd6939SJiyong Park clr_yield_smc_active_flag(tlk_ctx.state);
382*54fd6939SJiyong Park
383*54fd6939SJiyong Park /* Get a reference to the non-secure context */
384*54fd6939SJiyong Park ns_cpu_context = cm_get_context(NON_SECURE);
385*54fd6939SJiyong Park assert(ns_cpu_context);
386*54fd6939SJiyong Park
387*54fd6939SJiyong Park /*
388*54fd6939SJiyong Park * This is a request completion SMC and we must switch to
389*54fd6939SJiyong Park * the non-secure world to pass the result.
390*54fd6939SJiyong Park */
391*54fd6939SJiyong Park cm_el1_sysregs_context_save(SECURE);
392*54fd6939SJiyong Park
393*54fd6939SJiyong Park /*
394*54fd6939SJiyong Park * We are done stashing the secure context. Switch to the
395*54fd6939SJiyong Park * non-secure context and return the result.
396*54fd6939SJiyong Park */
397*54fd6939SJiyong Park cm_el1_sysregs_context_restore(NON_SECURE);
398*54fd6939SJiyong Park cm_set_next_eret_context(NON_SECURE);
399*54fd6939SJiyong Park SMC_RET1(ns_cpu_context, x1);
400*54fd6939SJiyong Park
401*54fd6939SJiyong Park /*
402*54fd6939SJiyong Park * This function ID is used only by the SP to indicate it has
403*54fd6939SJiyong Park * finished initialising itself after a cold boot
404*54fd6939SJiyong Park */
405*54fd6939SJiyong Park case TLK_ENTRY_DONE:
406*54fd6939SJiyong Park if (ns)
407*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
408*54fd6939SJiyong Park
409*54fd6939SJiyong Park /*
410*54fd6939SJiyong Park * SP has been successfully initialized. Register power
411*54fd6939SJiyong Park * management hooks with PSCI
412*54fd6939SJiyong Park */
413*54fd6939SJiyong Park psci_register_spd_pm_hook(&tlkd_pm_ops);
414*54fd6939SJiyong Park
415*54fd6939SJiyong Park /*
416*54fd6939SJiyong Park * TLK reports completion. The SPD must have initiated
417*54fd6939SJiyong Park * the original request through a synchronous entry
418*54fd6939SJiyong Park * into the SP. Jump back to the original C runtime
419*54fd6939SJiyong Park * context.
420*54fd6939SJiyong Park */
421*54fd6939SJiyong Park tlkd_synchronous_sp_exit(&tlk_ctx, x1);
422*54fd6939SJiyong Park break;
423*54fd6939SJiyong Park
424*54fd6939SJiyong Park /*
425*54fd6939SJiyong Park * These function IDs are used only by TLK to indicate it has
426*54fd6939SJiyong Park * finished:
427*54fd6939SJiyong Park * 1. suspending itself after an earlier psci cpu_suspend
428*54fd6939SJiyong Park * request.
429*54fd6939SJiyong Park * 2. resuming itself after an earlier psci cpu_suspend
430*54fd6939SJiyong Park * request.
431*54fd6939SJiyong Park * 3. powering down after an earlier psci system_off/system_reset
432*54fd6939SJiyong Park * request.
433*54fd6939SJiyong Park */
434*54fd6939SJiyong Park case TLK_SUSPEND_DONE:
435*54fd6939SJiyong Park case TLK_RESUME_DONE:
436*54fd6939SJiyong Park
437*54fd6939SJiyong Park if (ns)
438*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
439*54fd6939SJiyong Park
440*54fd6939SJiyong Park /*
441*54fd6939SJiyong Park * TLK reports completion. TLKD must have initiated the
442*54fd6939SJiyong Park * original request through a synchronous entry into the SP.
443*54fd6939SJiyong Park * Jump back to the original C runtime context, and pass x1 as
444*54fd6939SJiyong Park * return value to the caller
445*54fd6939SJiyong Park */
446*54fd6939SJiyong Park tlkd_synchronous_sp_exit(&tlk_ctx, x1);
447*54fd6939SJiyong Park break;
448*54fd6939SJiyong Park
449*54fd6939SJiyong Park /*
450*54fd6939SJiyong Park * This function ID is used by SP to indicate that it has completed
451*54fd6939SJiyong Park * handling the secure interrupt.
452*54fd6939SJiyong Park */
453*54fd6939SJiyong Park case TLK_IRQ_DONE:
454*54fd6939SJiyong Park
455*54fd6939SJiyong Park if (ns)
456*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
457*54fd6939SJiyong Park
458*54fd6939SJiyong Park assert(handle == cm_get_context(SECURE));
459*54fd6939SJiyong Park
460*54fd6939SJiyong Park /* save secure world context */
461*54fd6939SJiyong Park cm_el1_sysregs_context_save(SECURE);
462*54fd6939SJiyong Park
463*54fd6939SJiyong Park /* Get a reference to the non-secure context */
464*54fd6939SJiyong Park ns_cpu_context = cm_get_context(NON_SECURE);
465*54fd6939SJiyong Park assert(ns_cpu_context);
466*54fd6939SJiyong Park
467*54fd6939SJiyong Park /*
468*54fd6939SJiyong Park * Restore non-secure state. There is no need to save the
469*54fd6939SJiyong Park * secure system register context since the SP was supposed
470*54fd6939SJiyong Park * to preserve it during S-EL1 interrupt handling.
471*54fd6939SJiyong Park */
472*54fd6939SJiyong Park cm_el1_sysregs_context_restore(NON_SECURE);
473*54fd6939SJiyong Park cm_set_next_eret_context(NON_SECURE);
474*54fd6939SJiyong Park
475*54fd6939SJiyong Park SMC_RET0(ns_cpu_context);
476*54fd6939SJiyong Park
477*54fd6939SJiyong Park /*
478*54fd6939SJiyong Park * Return the number of service function IDs implemented to
479*54fd6939SJiyong Park * provide service to non-secure
480*54fd6939SJiyong Park */
481*54fd6939SJiyong Park case TOS_CALL_COUNT:
482*54fd6939SJiyong Park SMC_RET1(handle, TLK_NUM_FID);
483*54fd6939SJiyong Park
484*54fd6939SJiyong Park /*
485*54fd6939SJiyong Park * Return TLK's UID to the caller
486*54fd6939SJiyong Park */
487*54fd6939SJiyong Park case TOS_UID:
488*54fd6939SJiyong Park SMC_UUID_RET(handle, tlk_uuid);
489*54fd6939SJiyong Park
490*54fd6939SJiyong Park /*
491*54fd6939SJiyong Park * Return the version of current implementation
492*54fd6939SJiyong Park */
493*54fd6939SJiyong Park case TOS_CALL_VERSION:
494*54fd6939SJiyong Park SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR);
495*54fd6939SJiyong Park
496*54fd6939SJiyong Park default:
497*54fd6939SJiyong Park WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid);
498*54fd6939SJiyong Park break;
499*54fd6939SJiyong Park }
500*54fd6939SJiyong Park
501*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK);
502*54fd6939SJiyong Park }
503*54fd6939SJiyong Park
504*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for fast SMC calls */
505*54fd6939SJiyong Park DECLARE_RT_SVC(
506*54fd6939SJiyong Park tlkd_tos_fast,
507*54fd6939SJiyong Park
508*54fd6939SJiyong Park OEN_TOS_START,
509*54fd6939SJiyong Park OEN_TOS_END,
510*54fd6939SJiyong Park SMC_TYPE_FAST,
511*54fd6939SJiyong Park tlkd_setup,
512*54fd6939SJiyong Park tlkd_smc_handler
513*54fd6939SJiyong Park );
514*54fd6939SJiyong Park
515*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for yielding SMC calls */
516*54fd6939SJiyong Park DECLARE_RT_SVC(
517*54fd6939SJiyong Park tlkd_tos_std,
518*54fd6939SJiyong Park
519*54fd6939SJiyong Park OEN_TOS_START,
520*54fd6939SJiyong Park OEN_TOS_END,
521*54fd6939SJiyong Park SMC_TYPE_YIELD,
522*54fd6939SJiyong Park NULL,
523*54fd6939SJiyong Park tlkd_smc_handler
524*54fd6939SJiyong Park );
525*54fd6939SJiyong Park
526*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for fast SMC calls */
527*54fd6939SJiyong Park DECLARE_RT_SVC(
528*54fd6939SJiyong Park tlkd_tap_fast,
529*54fd6939SJiyong Park
530*54fd6939SJiyong Park OEN_TAP_START,
531*54fd6939SJiyong Park OEN_TAP_END,
532*54fd6939SJiyong Park SMC_TYPE_FAST,
533*54fd6939SJiyong Park NULL,
534*54fd6939SJiyong Park tlkd_smc_handler
535*54fd6939SJiyong Park );
536*54fd6939SJiyong Park
537*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for yielding SMC calls */
538*54fd6939SJiyong Park DECLARE_RT_SVC(
539*54fd6939SJiyong Park tlkd_tap_std,
540*54fd6939SJiyong Park
541*54fd6939SJiyong Park OEN_TAP_START,
542*54fd6939SJiyong Park OEN_TAP_END,
543*54fd6939SJiyong Park SMC_TYPE_YIELD,
544*54fd6939SJiyong Park NULL,
545*54fd6939SJiyong Park tlkd_smc_handler
546*54fd6939SJiyong Park );
547