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