1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016-2020, Linaro Limited 4 * Copyright (c) 2014, STMicroelectronics International N.V. 5 */ 6 #include <arm.h> 7 #include <compiler.h> 8 #include <config.h> 9 #include <drivers/wdt.h> 10 #include <kernel/misc.h> 11 #include <kernel/thread.h> 12 #include <platform_config.h> 13 #include <sm/optee_smc.h> 14 #include <sm/sm.h> 15 #include <sm/std_smc.h> 16 #include <string.h> 17 #include "sm_private.h" 18 sm_platform_handler(struct sm_ctx * ctx __unused)19enum sm_handler_ret __weak sm_platform_handler(struct sm_ctx *ctx __unused) 20 { 21 return SM_HANDLER_PENDING_SMC; 22 } 23 smc_arch_handler(struct thread_smc_args * args)24static void smc_arch_handler(struct thread_smc_args *args) 25 { 26 uint32_t smc_fid = args->a0; 27 uint32_t feature_fid = args->a1; 28 29 switch (smc_fid) { 30 case ARM_SMCCC_VERSION: 31 args->a0 = SMCCC_V_1_1; 32 break; 33 case ARM_SMCCC_ARCH_FEATURES: 34 switch (feature_fid) { 35 case ARM_SMCCC_VERSION: 36 case ARM_SMCCC_ARCH_SOC_ID: 37 args->a0 = ARM_SMCCC_RET_SUCCESS; 38 break; 39 default: 40 args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; 41 break; 42 } 43 break; 44 case ARM_SMCCC_ARCH_SOC_ID: 45 args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; 46 break; 47 case ARM_SMCCC_ARCH_WORKAROUND_1: 48 case ARM_SMCCC_ARCH_WORKAROUND_2: 49 args->a0 = ARM_SMCCC_RET_NOT_REQUIRED; 50 break; 51 default: 52 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; 53 break; 54 } 55 } 56 sm_from_nsec(struct sm_ctx * ctx)57uint32_t sm_from_nsec(struct sm_ctx *ctx) 58 { 59 uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); 60 struct thread_smc_args *args = (struct thread_smc_args *)nsec_r0; 61 62 /* 63 * Check that struct sm_ctx has the different parts properly 64 * aligned since the stack pointer will be updated to point at 65 * different parts of this struct. 66 */ 67 COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, sec.r0) % 8)); 68 COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, nsec.r0) % 8)); 69 COMPILE_TIME_ASSERT(!(sizeof(struct sm_ctx) % 8)); 70 71 if (wdt_sm_handler(args) == SM_HANDLER_SMC_HANDLED) 72 return SM_EXIT_TO_NON_SECURE; 73 74 if (IS_ENABLED(CFG_SM_PLATFORM_HANDLER) && 75 sm_platform_handler(ctx) == SM_HANDLER_SMC_HANDLED) 76 return SM_EXIT_TO_NON_SECURE; 77 78 switch (OPTEE_SMC_OWNER_NUM(args->a0)) { 79 case OPTEE_SMC_OWNER_STANDARD: 80 if (IS_ENABLED(CFG_PSCI_ARM32)) { 81 smc_std_handler(args, &ctx->nsec); 82 return SM_EXIT_TO_NON_SECURE; 83 } 84 break; 85 case OPTEE_SMC_OWNER_ARCH: 86 smc_arch_handler(args); 87 return SM_EXIT_TO_NON_SECURE; 88 default: 89 break; 90 } 91 92 sm_save_unbanked_regs(&ctx->nsec.ub_regs); 93 sm_restore_unbanked_regs(&ctx->sec.ub_regs); 94 95 memcpy(&ctx->sec.r0, args, sizeof(*args)); 96 97 if (IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) { 98 /* Make sure FIQ is masked when jumping to SMC entry. */ 99 ctx->sec.mon_spsr |= CPSR_F; 100 } 101 102 if (OPTEE_SMC_IS_FAST_CALL(ctx->sec.r0)) 103 ctx->sec.mon_lr = (uint32_t)vector_fast_smc_entry; 104 else 105 ctx->sec.mon_lr = (uint32_t)vector_std_smc_entry; 106 107 return SM_EXIT_TO_SECURE; 108 } 109