• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include <errno.h>
14 #include <assert.h>
15 #include <arch_helpers.h>
16 #include <bl31.h>
17 #include <bl_common.h>
18 #include <context.h>
19 #include <context_mgmt.h>
20 #include <platform.h>
21 #include <runtime_svc.h>
22 #include "tee.h"
23 #include "teed_common.h"
24 #include "teed_private.h"
25 
26 /*
27  * This function is the handler registered for S-EL1 interrupts by the TEED
28  * It validates the interrupt and upon success arranges entry into the TEE
29  * at 'tee_sel1_intr_entry()' for handling the interrupt.
30  */
teed_sel1_interrupt_handler(uint32_t id,uint32_t flags,void * handle,void * cookie)31 static uint64_t teed_sel1_interrupt_handler(uint32_t id,
32                          uint32_t flags,
33                          void *handle,
34                          void *cookie)
35 {
36     uint32_t linear_id;
37     tee_context_t *tee_ctx = NULL;
38 
39     /* Check the security state when the exception was generated */
40     assert(get_interrupt_src_ss(flags) == NON_SECURE);
41 
42     /* Sanity check the pointer to this cpu's context */
43     assert(handle == cm_get_context(NON_SECURE));
44 
45     /* Save the non-secure context before entering the TEE */
46     cm_el1_sysregs_context_save(NON_SECURE);
47     fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
48 
49     /* Get a reference to this cpu's TEE context */
50     linear_id = plat_my_core_pos();
51     tee_ctx = get_teed_sp_context(linear_id);
52     assert(tee_ctx != NULL);
53     assert(&tee_ctx->cpu_context == cm_get_context(SECURE));
54 
55     /*
56      * Determine if the tee was previously preempted. Its last known
57      * context has to be preserved in this case.
58      * The tee should return control to the teeD after handling
59      * this S-EL1 interrupt. Preserve essential EL3 context to allow entry
60      * into the tee at the S-EL1 interrupt entry point using the
61      * 'cpu_context' structure. There is no need to save the secure system
62      * register context since the tee is supposed to preserve it
63      * during S-EL1 interrupt handling.
64      */
65     if (get_yield_smc_active_flag(tee_ctx->state) == SMC_ACTIVE) {
66         tee_ctx->spsr_el3 = (uint32_t)SMC_GET_EL3(&tee_ctx->cpu_context, CTX_SPSR_EL3);
67         tee_ctx->elr_el3 = SMC_GET_EL3(&tee_ctx->cpu_context, CTX_ELR_EL3);
68     }
69 
70     cm_el1_sysregs_context_restore(SECURE);
71     fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
72     tee_vectors_t* tee_vectors_tmp = get_tee_vectors_t();
73     assert(tee_vectors_tmp != NULL);
74     cm_set_elr_spsr_el3(SECURE, (uintptr_t)&tee_vectors_tmp->sel1_intr_entry,
75                 SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
76 
77     cm_set_next_eret_context(SECURE);
78     /*
79      * Tell the TEE that it has to handle a S-EL1 interrupt
80      * synchronously. It is safe to retrieve
81      * this address from ELR_EL3 as the secure context will not take effect
82      * until el3_exit().
83      */
84     SMC_RET2((uintptr_t)&tee_ctx->cpu_context,
85          TEE_HANDLE_SEL1_INTR_AND_RETURN, read_elr_el3());
86 }
87 
88 /*
89  * This function passes control to the Secure Payload image (BL32) for the first
90  * time on the primary cpu after a cold boot. It assumes that a valid secure
91  * context has already been created by teed_setup() which can be directly
92  * used. It also assumes that a valid non-secure context has been initialised by
93  * PSCI so it does not need to save and restore any non-secure state. This
94  * function performs a synchronous entry into the Secure payload. The SP passes
95  * control back to this routine through a SMC.
96  */
teed_init(void)97 static int32_t teed_init(void)
98 {
99     uint32_t linear_id = plat_my_core_pos();
100     tee_context_t *tee_ctx = get_teed_sp_context(linear_id);
101     entry_point_info_t *tee_entry_point = NULL;
102     uint64_t rc;
103     uint64_t mpidr = read_mpidr();
104     /* set the primary cpu */
105     set_primary_cpu_mpidr(mpidr);
106     /*
107      * Get information about the Secure Payload (BL32) image. Its
108      * absence is a critical failure.
109      */
110     tee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
111     cm_init_my_context(tee_entry_point);
112 
113 #ifdef BOOT_BL32_FROM_OTHER_EXCEPTION
114     /* set el3 fiq bit for tee init */
115     cpu_context_t *ctx = NULL;
116     el3_state_t *state = NULL;
117     uint32_t scr_el3;
118     ctx = cm_get_context(GET_SECURITY_STATE(tee_entry_point->h.attr));
119     state = get_el3state_ctx(ctx);
120     scr_el3 = read_ctx_reg(state, CTX_SCR_EL3);
121     scr_el3 &= ~SCR_FIQ_BIT;
122     write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
123 
124     /* save nosecure context and disable interrupt during init */
125     cm_el1_sysregs_context_save(NON_SECURE);
126     fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
127 #endif
128     /*
129      * Arrange for an entry into the test secure payload. It will be
130      * returned via TEE_ENTRY_DONE case
131      */
132     rc = teed_synchronous_sp_entry(tee_ctx);
133     assert(rc != 0);
134     return rc;
135 }
136 
137 /*
138  * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
139  * (aarch32/aarch64) if not already known and initialises the context for entry
140  * into the SP for its initialisation.
141  */
teed_setup(void)142 static int32_t teed_setup(void)
143 {
144     entry_point_info_t *image_info = NULL;
145     uint32_t linear_id;
146 
147     linear_id = plat_my_core_pos();
148     NOTICE("teed setup start!\n");
149     /*
150      * Get information about the Secure Payload (BL32) image. Its
151      * absence is a critical failure.
152      * conditionally include the SPD service
153      */
154     image_info = bl31_plat_get_next_image_ep_info(SECURE);
155     if (image_info == NULL) {
156         WARN("No TEE provided by BL2 boot loader, Booting device"
157             " without TEE initialization. SMC`s destined for TEE"
158             " will return SMC_UNK\n");
159         return TEE_SETUP_FAIL;
160     }
161     assert(image_info != NULL);
162     /*
163      * If there's no valid entry point for SP, we return a non-zero value
164      * signalling failure initializing the service. We bail out without
165      * registering any handlers
166      */
167     if (image_info->pc == INVALID_PC_ADDR)
168         return TEE_SETUP_FAIL;
169 
170     /*
171      * We could inspect the SP image and determine its execution
172      * state i.e whether AArch32 or AArch64. Assuming it's AArch64
173      * for the time being.
174      */
175     tee_context_t *tee_ctx = get_teed_sp_context(linear_id);
176     teed_init_tee_ep_state(image_info,
177                      TEE_AARCH64,
178                      image_info->pc,
179                      tee_ctx);
180 
181     /*
182      * All TEED initialization done. Now register our init function
183      * with BL31 for deferred invocation
184      */
185     bl31_register_bl32_init(&teed_init);
186     return 0;
187 }
188 
189 /*
190  * This function ID is used only by the tee to indicate that it has
191  * finished handling a S-EL1 interrupt or was preempted by a higher
192  * priority pending EL3 interrupt. Execution should resume
193  * in the normal world.
194  * TEE_HANDLED_S_EL1_INTR:
195  * TEE_HANDLED_S_EL1_FIQ_AARCH32:
196  */
smc_handle_s_el1(tee_context_t * tee_ctx,void * handle,uint32_t ns)197 static uintptr_t smc_handle_s_el1(tee_context_t *tee_ctx,
198                   void *handle, uint32_t ns)
199 {
200     if (ns != SECURE_WORLD_FLAG)
201         SMC_RET1((uintptr_t)handle, SMC_UNK);
202 
203     assert(handle == cm_get_context(SECURE));
204     assert(tee_ctx != NULL);
205     cpu_context_t *ns_cpu_context = NULL;
206     /*
207      * Restore the relevant EL3 state which saved to service
208      * this SMC.
209      */
210     if (get_yield_smc_active_flag(tee_ctx->state) != SMC_INACTIVE) {
211         SMC_SET_EL3(&tee_ctx->cpu_context,
212                 CTX_SPSR_EL3,
213                 tee_ctx->spsr_el3);
214         SMC_SET_EL3(&tee_ctx->cpu_context,
215                 CTX_ELR_EL3,
216                 tee_ctx->elr_el3);
217     }
218 
219     /* Get a reference to the non-secure context */
220     ns_cpu_context = cm_get_context(NON_SECURE);
221     assert(ns_cpu_context != NULL);
222 
223     /*
224      * Restore non-secure state. There is no need to save the
225      * secure system register context since the tee was supposed
226      * to preserve it during S-EL1 interrupt handling.
227      */
228     cm_el1_sysregs_context_restore(NON_SECURE);
229     fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
230     cm_set_next_eret_context(NON_SECURE);
231     SMC_RET0((uintptr_t)ns_cpu_context);
232 }
233 
234 /*
235  * This function ID is used only by the SP to indicate it has
236  * finished initialising itself after a cold boot
237  * TEE_ENTRY_DONE:
238  * TEE_ENTRY_DONE_AARCH32:
239  */
smc_handle_entry_done(tee_context_t * tee_ctx,u_register_t x1,u_register_t * flags)240 static void smc_handle_entry_done(tee_context_t *tee_ctx,
241                   u_register_t x1, u_register_t *flags)
242 {
243     /*
244      * Stash the SP entry points information. This is done
245      * only once on the primary cpu
246      */
247     uint64_t rc;
248     tee_vectors_t* tee_vectors_tmp = (tee_vectors_t *)(uintptr_t)x1;
249     set_tee_vectors_t(tee_vectors_tmp);
250     if (tee_vectors_tmp != NULL) {
251         set_tee_pstate(tee_ctx->state, TEE_PSTATE_ON);
252         /*
253          * tee has been successfully initialized. Register
254          * power managemnt hooks with PSCI
255          */
256         const spd_pm_ops_t *teed_pm_tmp = get_teed_pm();
257         psci_register_spd_pm_hook(teed_pm_tmp);
258 
259         /*
260          * Register an interrupt handler for S-EL1 interrupts
261          * when generated during code executing in the
262          * non-secure state.
263          */
264         *flags = 0;
265         set_interrupt_rm_flag(*flags, NON_SECURE);
266         rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
267                              teed_sel1_interrupt_handler,
268                              *flags);
269         if (rc != 0)
270             panic();
271     }
272 
273     /*
274      * SP reports completion. The SPD must have initiated
275      * the original request through a synchronous entry
276      * into the SP. Jump back to the original C runtime
277      * context.
278      */
279     teed_synchronous_sp_exit(tee_ctx, x1);
280 }
281 
282 /*
283  * This function ID is used only by the SP to indicate it has finished
284  * aborting a preempted Yielding SMC Call.
285  * case TEE_ABORT_DONE:
286  * *********
287  * These function IDs are used only by the SP to indicate it has
288  * finished:
289  * 1. turning itself on in response to an earlier psci
290  *    cpu_on request
291  * 2. resuming itself after an earlier psci cpu_suspend
292  *    request.
293  * TEE_ON_DONE:
294  * TEE_ON_DONE_AARCH32:
295  * TEE_RESUME_DONE:
296  * TEE_RESUME_DONE_AARCH32:
297  * ****
298  * These function IDs are used only by the SP to indicate it has
299  * finished:
300  * 1. suspending itself after an earlier psci cpu_suspend
301  *    request.
302  * 2. turning itself off in response to an earlier psci
303  *    cpu_off request.
304  * TEE_OFF_DONE:
305  * TEE_SUSPEND_DONE:
306  * TEE_SUSPEND_DONE_AARCH32:
307  * TEE_SYSTEM_OFF_DONE:
308  * TEE_SYSTEM_RESET_DONE:
309  */
smc_handle_abort_on_resume(const tee_context_t * tee_ctx,u_register_t x1)310 static void smc_handle_abort_on_resume(const tee_context_t *tee_ctx, u_register_t x1)
311 {
312     /*
313      * SP reports completion. The SPD must have initiated the
314      * original request through a synchronous entry into the SP.
315      * Jump back to the original C runtime context, and pass x1 as
316      * return value to the caller
317      */
318     teed_synchronous_sp_exit(tee_ctx, x1);
319 }
320 
smc_handle_std_request(tee_context_t * tee_ctx,smc_registers_t registers_t,const void * handle,uint32_t smc_fid,uint32_t ns)321 static uintptr_t smc_handle_std_request(tee_context_t *tee_ctx,
322                     smc_registers_t registers_t,
323                     const void *handle, uint32_t smc_fid,
324                     uint32_t ns)
325 {
326     if (ns == SECURE_WORLD_FLAG)
327         SMC_RET1((uintptr_t)handle, SMC_UNK);
328     assert(handle == cm_get_context(NON_SECURE));
329     cm_el1_sysregs_context_save(NON_SECURE);
330     fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
331     assert(&tee_ctx->cpu_context == cm_get_context(SECURE));
332     /*
333      * Restore the correct state considering if the
334      * OS has been active.
335      */
336     tee_vectors_t* tee_vectors_tmp = get_tee_vectors_t();
337     assert(tee_vectors_tmp != NULL);
338     if (get_yield_smc_active_flag(tee_ctx->state) != SMC_INACTIVE) {
339         cm_set_elr_spsr_el3(SECURE,
340                     (uintptr_t)&tee_vectors_tmp->irq_return_entry,
341                     SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
342     } else {
343         cm_set_elr_spsr_el3(SECURE, (uintptr_t)&tee_vectors_tmp->yield_smc_entry,
344                     SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
345     }
346 
347     cm_el1_sysregs_context_restore(SECURE);
348     fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
349     cm_set_next_eret_context(SECURE);
350 
351     if (get_yield_smc_active_flag(tee_ctx->state) != SMC_INACTIVE) {
352         SMC_RET0((uintptr_t)&tee_ctx->cpu_context);
353     } else {
354         set_yield_smc_active_flag(tee_ctx->state);
355         SMC_RET5((uintptr_t)&tee_ctx->cpu_context, smc_fid, registers_t.x1,
356              registers_t.x2, registers_t.x3, registers_t.x4);
357     }
358 }
359 
smc_handle_std_ree_siq(uint32_t smc_fid,tee_context_t * tee_ctx,u_register_t x1,void * handle,uint32_t ns)360 static uintptr_t smc_handle_std_ree_siq(uint32_t smc_fid,
361                     tee_context_t *tee_ctx,
362                     u_register_t x1, void *handle,
363                     uint32_t ns)
364 {
365     if (ns == SECURE_WORLD_FLAG)
366         SMC_RET1((uintptr_t)handle, SMC_UNK);
367 
368     assert(handle == cm_get_context(NON_SECURE));
369 
370     cm_el1_sysregs_context_save(NON_SECURE);
371     fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
372 
373     assert(&tee_ctx->cpu_context == cm_get_context(SECURE));
374 
375     tee_ctx->spsr_el3 = SMC_GET_EL3(&tee_ctx->cpu_context,
376                          CTX_SPSR_EL3);
377     tee_ctx->elr_el3 = SMC_GET_EL3(&tee_ctx->cpu_context,
378                         CTX_ELR_EL3);
379     tee_vectors_t* tee_vectors_tmp = get_tee_vectors_t();
380     assert(tee_vectors_tmp != NULL);
381     cm_set_elr_spsr_el3(SECURE,
382                 (uintptr_t)&tee_vectors_tmp->fast_smc_entry,
383                 SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
384 
385     write_ctx_reg(get_gpregs_ctx(&tee_ctx->cpu_context), CTX_GPREG_X1, x1);
386     (void)teed_synchronous_sp_entry(tee_ctx);
387     /* Restore non-secure state */
388     cm_el1_sysregs_context_restore(NON_SECURE);
389     fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
390     cm_set_next_eret_context(NON_SECURE);
391     SMC_RET1((uintptr_t)handle, smc_fid);
392 }
393 
smc_handle_std_response(uint32_t smc_fid,tee_context_t * tee_ctx,smc_registers_t registers_t,const void * handle,uint32_t ns)394 static uintptr_t smc_handle_std_response(uint32_t smc_fid,
395                      tee_context_t *tee_ctx,
396                      smc_registers_t registers_t,
397                      const void *handle, uint32_t ns)
398 {
399     if (ns != SECURE_WORLD_FLAG)
400         SMC_RET1((uintptr_t)handle, SMC_UNK);
401     /* Forward secure responses to NS */
402     cpu_context_t *ns_cpu_context = NULL;
403 
404     assert(handle == cm_get_context(SECURE));
405     cm_el1_sysregs_context_save(SECURE);
406     fpregs_context_save(get_fpregs_ctx(cm_get_context(SECURE)));
407 
408     /* Get a reference to the non-secure context */
409     ns_cpu_context = cm_get_context(NON_SECURE);
410     assert(ns_cpu_context != NULL);
411 
412     /* Restore non-secure state */
413     cm_el1_sysregs_context_restore(NON_SECURE);
414     fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
415     cm_set_next_eret_context(NON_SECURE);
416     clr_yield_smc_active_flag(tee_ctx->state);
417     SMC_RET4((uintptr_t)ns_cpu_context, smc_fid, registers_t.x1,
418          registers_t.x2, registers_t.x3);
419 }
420 
smc_handle_std_crash(tee_context_t * tee_ctx,smc_registers_t registers_t,const void * handle,uint32_t ns)421 static uintptr_t smc_handle_std_crash(tee_context_t *tee_ctx,
422                       smc_registers_t registers_t, const void *handle,
423                       uint32_t ns)
424 {
425     if (ns != SECURE_WORLD_FLAG)
426         SMC_RET1((uintptr_t)handle, SMC_UNK);
427     NOTICE("notify teeos has crashed\n");
428     /* Secure OS has crashed, set the flag and return to ns */
429     cpu_context_t *ns_cpu_context = NULL;
430     assert(handle == cm_get_context(SECURE));
431 
432     set_std_crash_flag(tee_ctx->state);
433 
434     /* Get a reference to the non-secure context */
435     ns_cpu_context = cm_get_context(NON_SECURE);
436     assert(ns_cpu_context != NULL);
437 
438     /* Restore non-secure state */
439     cm_el1_sysregs_context_restore(NON_SECURE);
440     fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
441     cm_set_next_eret_context(NON_SECURE);
442     SMC_RET4((uintptr_t)ns_cpu_context, TEE_STD_CRASH, registers_t.x1,
443          registers_t.x2, registers_t.x3);
444 }
445 
446 /*
447  * This function is responsible for handling all SMCs in the Trusted OS/App
448  * range from the non-secure state as defined in the SMC Calling Convention
449  * Document. It is also responsible for communicating with the Secure payload
450  * to delegate work and return results back to the non-secure state. Lastly it
451  * will also return any information that the secure payload needs to do the
452  * work assigned to it.
453  */
454 
teed_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)455 static uintptr_t teed_smc_handler(uint32_t smc_fid, u_register_t x1,
456                        u_register_t x2, u_register_t x3,
457                        u_register_t x4, void *cookie,
458                        void *handle, u_register_t flags)
459 {
460     uint32_t linear_id = plat_my_core_pos();
461     /* Determine which security state this SMC originated from */
462     uint32_t ns = is_caller_non_secure(flags);
463     tee_context_t *tee_ctx = get_teed_sp_context(linear_id);
464     smc_registers_t registers_t = { x1, x2, x3, x4 };
465     /*
466      * For calls comming from non-secure side after the OS signals
467      * it has crashed just return to NS side, no more forwarding
468      */
469     assert(tee_ctx != NULL);
470     if (ns != SECURE_WORLD_FLAG &&
471         get_std_crash_flag(tee_ctx->state) != STD_NO_CRASH_FLAG)
472         SMC_RET1((uintptr_t)handle, TEE_STD_CRASH);
473 
474     switch (smc_fid) {
475     /*
476      * This function ID is used only by the tee to indicate that it has
477      * finished handling a S-EL1 interrupt or was preempted by a higher
478      * priority pending EL3 interrupt. Execution should resume
479      * in the normal world.
480      */
481     case TEE_HANDLED_S_EL1_INTR:
482     case TEE_HANDLED_S_EL1_FIQ_AARCH32:
483         return smc_handle_s_el1(tee_ctx, handle, ns);
484     /*
485      * This function ID is used only by the SP to indicate it has
486      * finished initialising itself after a cold boot
487      */
488     case TEE_ENTRY_DONE:
489     case TEE_ENTRY_DONE_AARCH32:
490         if (ns == SECURE_WORLD_FLAG)
491             smc_handle_entry_done(tee_ctx, x1, &flags);
492         break;
493     /*
494      * This function ID is used only by the SP to indicate it has finished
495      * aborting a preempted Yielding SMC Call.
496      */
497     case TEE_ABORT_DONE:
498     case TEE_ON_DONE:
499     case TEE_ON_DONE_AARCH32:
500     case TEE_RESUME_DONE:
501     case TEE_RESUME_DONE_AARCH32:
502     /*
503      * These function IDs are used only by the SP to indicate it has
504      * finished:
505      * 1. suspending itself after an earlier psci cpu_suspend
506      *    request.
507      * 2. turning itself off in response to an earlier psci
508      *    cpu_off request.
509      */
510     case TEE_SUSPEND_DONE:
511     case TEE_SUSPEND_DONE_AARCH32:
512         if (ns != SECURE_WORLD_FLAG)
513             SMC_RET1((uintptr_t)handle, SMC_UNK);
514 
515         smc_handle_abort_on_resume(tee_ctx, x1);
516         break;
517     case TEE_STD_REQUEST:
518         return smc_handle_std_request(tee_ctx, registers_t, handle, smc_fid, ns);
519     case TEE_STD_REE_SIQ:
520         return smc_handle_std_ree_siq(smc_fid, tee_ctx, x1, handle, ns);
521     case TEE_STD_RESPONSE:
522         return smc_handle_std_response(smc_fid, tee_ctx, registers_t, handle, ns);
523     case TEE_STD_CRASH:
524         return smc_handle_std_crash(tee_ctx, registers_t, handle, ns);
525     default:
526         break;
527     }
528 
529     SMC_RET1((uintptr_t)handle, SMC_UNK);
530 }
531 
532 /* Define a SPD runtime service descriptor for fast SMC calls */
533 DECLARE_RT_SVC(
534     teed_fast,
535     OEN_TOS_START,
536     OEN_TOS_END,
537     SMC_TYPE_FAST,
538     teed_setup,
539     teed_smc_handler
540 );
541 
542 /* Define a SPD runtime service descriptor for Yielding SMC Calls */
543 DECLARE_RT_SVC(
544     teed_std,
545     OEN_TOS_START,
546     OEN_TOS_END,
547     SMC_TYPE_YIELD,
548     NULL,
549     teed_smc_handler
550 );
551