1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022-2023, MediaTek Inc. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #if MTK_SIP_KERNEL_BOOT_ENABLE 10*91f16700Schasinglulu #include <cold_boot.h> 11*91f16700Schasinglulu #endif 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <common/runtime_svc.h> 14*91f16700Schasinglulu #include <lib/mtk_init/mtk_init.h> 15*91f16700Schasinglulu #include <mtk_sip_svc.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__) 18*91f16700Schasinglulu #define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n" 19*91f16700Schasinglulu #define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n" 20*91f16700Schasinglulu #define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n" 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* 23*91f16700Schasinglulu * These macros below are used to identify SIP calls from Kernel, 24*91f16700Schasinglulu * Hypervisor, or 2ndBootloader 25*91f16700Schasinglulu */ 26*91f16700Schasinglulu #define SIP_FID_ORI_MASK (0xc000) 27*91f16700Schasinglulu #define SIP_FID_ORI_SHIFT (14) 28*91f16700Schasinglulu #define SIP_FID_KERNEL (0x0) 29*91f16700Schasinglulu #define SIP_FID_KERNEL_VIA_GZ (0x1) 30*91f16700Schasinglulu #define SIP_FID_GZ (0x2) 31*91f16700Schasinglulu 32*91f16700Schasinglulu #define GET_SMC_ORI(_fid) (((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT) 33*91f16700Schasinglulu #define GET_SMC_ORI_NUM(_fid) ((_fid) & ~(SIP_FID_ORI_MASK)) 34*91f16700Schasinglulu 35*91f16700Schasinglulu #define is_from_nsel2(_ori) (_ori == SIP_FID_GZ) 36*91f16700Schasinglulu #define is_from_bl33(_ori) \ 37*91f16700Schasinglulu ((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1)) 38*91f16700Schasinglulu #define is_from_nsel1(_ori) \ 39*91f16700Schasinglulu (((_ori == SIP_FID_KERNEL) || \ 40*91f16700Schasinglulu (_ori == SIP_FID_KERNEL_VIA_GZ)) && \ 41*91f16700Schasinglulu (is_el1_2nd_bootloader() == 0)) 42*91f16700Schasinglulu 43*91f16700Schasinglulu #define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ) 44*91f16700Schasinglulu 45*91f16700Schasinglulu #define MASK_32_BIT (0xffffffffU) 46*91f16700Schasinglulu #define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \ 47*91f16700Schasinglulu case _smc_id##_AARCH32: \ 48*91f16700Schasinglulu { \ 49*91f16700Schasinglulu x1 = x1 & MASK_32_BIT; \ 50*91f16700Schasinglulu x2 = x2 & MASK_32_BIT; \ 51*91f16700Schasinglulu x3 = x3 & MASK_32_BIT; \ 52*91f16700Schasinglulu x4 = x4 & MASK_32_BIT; \ 53*91f16700Schasinglulu } \ 54*91f16700Schasinglulu /* fallthrough */ \ 55*91f16700Schasinglulu case _smc_id##_AARCH64: \ 56*91f16700Schasinglulu { \ 57*91f16700Schasinglulu if (_smc_id##_descriptor_index < 0) { \ 58*91f16700Schasinglulu SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \ 59*91f16700Schasinglulu break; \ 60*91f16700Schasinglulu } \ 61*91f16700Schasinglulu if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \ 62*91f16700Schasinglulu SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \ 63*91f16700Schasinglulu _smc_id##_descriptor_index, smc_id_descriptor_max); \ 64*91f16700Schasinglulu break; \ 65*91f16700Schasinglulu } \ 66*91f16700Schasinglulu SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \ 67*91f16700Schasinglulu _smc_id##_descriptor_index); \ 68*91f16700Schasinglulu ret = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\ 69*91f16700Schasinglulu x2, x3, x4, handle, &smc_ret); \ 70*91f16700Schasinglulu SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \ 71*91f16700Schasinglulu break; \ 72*91f16700Schasinglulu } 73*91f16700Schasinglulu 74*91f16700Schasinglulu #define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \ 75*91f16700Schasinglulu short _smc_id##_descriptor_index __section(".mtk_plat_ro") = -1; 76*91f16700Schasinglulu 77*91f16700Schasinglulu MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX); 78*91f16700Schasinglulu MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX); 79*91f16700Schasinglulu MTK_SIP_SMC_FROM_S_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX); 80*91f16700Schasinglulu 81*91f16700Schasinglulu IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START); 82*91f16700Schasinglulu IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED); 83*91f16700Schasinglulu 84*91f16700Schasinglulu static const struct smc_descriptor *smc_handler_pool; 85*91f16700Schasinglulu static short smc_id_descriptor_max; 86*91f16700Schasinglulu 87*91f16700Schasinglulu #if !MTK_SIP_KERNEL_BOOT_ENABLE 88*91f16700Schasinglulu /* 89*91f16700Schasinglulu * If there is no SMC request needs to be served in 2nd bootloader, 90*91f16700Schasinglulu * disable the service path inherently. 91*91f16700Schasinglulu */ 92*91f16700Schasinglulu bool is_el1_2nd_bootloader(void) 93*91f16700Schasinglulu { 94*91f16700Schasinglulu return false; 95*91f16700Schasinglulu } 96*91f16700Schasinglulu #endif 97*91f16700Schasinglulu 98*91f16700Schasinglulu static void print_smc_descriptor(const struct smc_descriptor pool[]) 99*91f16700Schasinglulu { 100*91f16700Schasinglulu const struct smc_descriptor *p_smc_desc; 101*91f16700Schasinglulu 102*91f16700Schasinglulu INFO("print smc descriptor pool\n"); 103*91f16700Schasinglulu for (p_smc_desc = &pool[0]; 104*91f16700Schasinglulu (char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED; 105*91f16700Schasinglulu p_smc_desc++) { 106*91f16700Schasinglulu INFO("descriptor name:%s\n", p_smc_desc->smc_name); 107*91f16700Schasinglulu INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index); 108*91f16700Schasinglulu INFO("smc id 32:0x%x, smc id 64:0x%x\n", 109*91f16700Schasinglulu p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64); 110*91f16700Schasinglulu } 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu static int mtk_smc_handler_init(void) 114*91f16700Schasinglulu { 115*91f16700Schasinglulu const struct smc_descriptor *iter; 116*91f16700Schasinglulu short index_cnt; 117*91f16700Schasinglulu int ret = 0; 118*91f16700Schasinglulu 119*91f16700Schasinglulu smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START; 120*91f16700Schasinglulu /* Designate descriptor index point to smc_handler_pool */ 121*91f16700Schasinglulu for (index_cnt = 0, iter = &smc_handler_pool[0]; 122*91f16700Schasinglulu (char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED; 123*91f16700Schasinglulu iter++, index_cnt++) { 124*91f16700Schasinglulu if (index_cnt < 0) { 125*91f16700Schasinglulu SMC_HANDLER_DEBUG("smc handler pool index overflow!\n"); 126*91f16700Schasinglulu ret = -EPERM; 127*91f16700Schasinglulu assert(0); 128*91f16700Schasinglulu break; 129*91f16700Schasinglulu } 130*91f16700Schasinglulu *(iter->smc_descriptor_index) = index_cnt; 131*91f16700Schasinglulu } 132*91f16700Schasinglulu smc_id_descriptor_max = index_cnt; 133*91f16700Schasinglulu print_smc_descriptor(smc_handler_pool); 134*91f16700Schasinglulu return ret; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu MTK_EARLY_PLAT_INIT(mtk_smc_handler_init); 137*91f16700Schasinglulu 138*91f16700Schasinglulu /* This function handles Mediatek defined SiP Calls from Secure world */ 139*91f16700Schasinglulu static u_register_t mtk_smc_handler_sel1(uint32_t smc_id, 140*91f16700Schasinglulu u_register_t x1, 141*91f16700Schasinglulu u_register_t x2, 142*91f16700Schasinglulu u_register_t x3, 143*91f16700Schasinglulu u_register_t x4, 144*91f16700Schasinglulu void *cookie, 145*91f16700Schasinglulu void *handle, 146*91f16700Schasinglulu u_register_t flags) 147*91f16700Schasinglulu { 148*91f16700Schasinglulu u_register_t ret = MTK_SIP_E_SUCCESS; 149*91f16700Schasinglulu struct smccc_res smc_ret = {0}; 150*91f16700Schasinglulu 151*91f16700Schasinglulu switch (smc_id) { 152*91f16700Schasinglulu MTK_SIP_SMC_FROM_S_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION); 153*91f16700Schasinglulu default: 154*91f16700Schasinglulu INFO("SEL1 SMC ID:0x%x not support\n", smc_id); 155*91f16700Schasinglulu ret = SMC_UNK; 156*91f16700Schasinglulu } 157*91f16700Schasinglulu SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3); 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu /* This function handles Mediatek defined SiP Calls from Bootloader */ 161*91f16700Schasinglulu static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id, 162*91f16700Schasinglulu u_register_t x1, 163*91f16700Schasinglulu u_register_t x2, 164*91f16700Schasinglulu u_register_t x3, 165*91f16700Schasinglulu u_register_t x4, 166*91f16700Schasinglulu void *cookie, 167*91f16700Schasinglulu void *handle, 168*91f16700Schasinglulu u_register_t flags) 169*91f16700Schasinglulu { 170*91f16700Schasinglulu uintptr_t ret = MTK_SIP_E_SUCCESS; 171*91f16700Schasinglulu struct smccc_res smc_ret = {0}; 172*91f16700Schasinglulu 173*91f16700Schasinglulu switch (smc_id) { 174*91f16700Schasinglulu MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION); 175*91f16700Schasinglulu default: 176*91f16700Schasinglulu INFO("BL33 SMC ID:0x%x not supported\n", smc_id); 177*91f16700Schasinglulu ret = SMC_UNK; 178*91f16700Schasinglulu break; 179*91f16700Schasinglulu } 180*91f16700Schasinglulu SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3); 181*91f16700Schasinglulu } 182*91f16700Schasinglulu 183*91f16700Schasinglulu /* This function handles Mediatek defined SiP Calls from Kernel */ 184*91f16700Schasinglulu static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id, 185*91f16700Schasinglulu u_register_t x1, 186*91f16700Schasinglulu u_register_t x2, 187*91f16700Schasinglulu u_register_t x3, 188*91f16700Schasinglulu u_register_t x4, 189*91f16700Schasinglulu void *cookie, 190*91f16700Schasinglulu void *handle, 191*91f16700Schasinglulu u_register_t flags) 192*91f16700Schasinglulu { 193*91f16700Schasinglulu uintptr_t ret = MTK_SIP_E_SUCCESS; 194*91f16700Schasinglulu struct smccc_res smc_ret = {0}; 195*91f16700Schasinglulu 196*91f16700Schasinglulu switch (smc_id) { 197*91f16700Schasinglulu MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION); 198*91f16700Schasinglulu default: 199*91f16700Schasinglulu INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id); 200*91f16700Schasinglulu ret = SMC_UNK; 201*91f16700Schasinglulu break; 202*91f16700Schasinglulu } 203*91f16700Schasinglulu SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3); 204*91f16700Schasinglulu } 205*91f16700Schasinglulu 206*91f16700Schasinglulu static uintptr_t mtk_smc_handler(uint32_t smc_id, 207*91f16700Schasinglulu u_register_t x1, 208*91f16700Schasinglulu u_register_t x2, 209*91f16700Schasinglulu u_register_t x3, 210*91f16700Schasinglulu u_register_t x4, 211*91f16700Schasinglulu void *cookie, 212*91f16700Schasinglulu void *handle, 213*91f16700Schasinglulu u_register_t flags) 214*91f16700Schasinglulu { 215*91f16700Schasinglulu uintptr_t ret = SMC_UNK; 216*91f16700Schasinglulu uint32_t ns; 217*91f16700Schasinglulu uint32_t smc_ori; 218*91f16700Schasinglulu uint32_t smc_num; 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* Get SMC Originator bit 14.15 */ 221*91f16700Schasinglulu smc_ori = GET_SMC_ORI(smc_id); 222*91f16700Schasinglulu /* Get SMC Number. Clean bit 14.15 */ 223*91f16700Schasinglulu smc_num = GET_SMC_ORI_NUM(smc_id); 224*91f16700Schasinglulu 225*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 226*91f16700Schasinglulu ns = is_caller_non_secure(flags); 227*91f16700Schasinglulu 228*91f16700Schasinglulu if (ns && is_smc_forbidden(smc_ori)) { 229*91f16700Schasinglulu ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id); 230*91f16700Schasinglulu SMC_RET1(handle, ret); 231*91f16700Schasinglulu } 232*91f16700Schasinglulu 233*91f16700Schasinglulu if (!ns) { 234*91f16700Schasinglulu /* SiP SMC service secure world's call */ 235*91f16700Schasinglulu return mtk_smc_handler_sel1(smc_num, x1, x2, x3, x4, 236*91f16700Schasinglulu cookie, handle, flags); 237*91f16700Schasinglulu } 238*91f16700Schasinglulu if (is_from_bl33(smc_ori)) { 239*91f16700Schasinglulu /* SiP SMC service secure bootloader's call */ 240*91f16700Schasinglulu return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4, 241*91f16700Schasinglulu cookie, handle, flags); 242*91f16700Schasinglulu } else if (is_from_nsel1(smc_ori)) { 243*91f16700Schasinglulu /* SiP SMC service kernel's call */ 244*91f16700Schasinglulu return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4, 245*91f16700Schasinglulu cookie, handle, flags); 246*91f16700Schasinglulu } 247*91f16700Schasinglulu INFO("SMC ID:0x%x not supported\n", smc_id); 248*91f16700Schasinglulu SMC_RET1(handle, ret); 249*91f16700Schasinglulu } 250*91f16700Schasinglulu 251*91f16700Schasinglulu /* Define a runtime service descriptor for fast SMC calls */ 252*91f16700Schasinglulu DECLARE_RT_SVC( 253*91f16700Schasinglulu mtk_smc_handler, 254*91f16700Schasinglulu OEN_SIP_START, 255*91f16700Schasinglulu OEN_SIP_END, 256*91f16700Schasinglulu SMC_TYPE_FAST, 257*91f16700Schasinglulu NULL, 258*91f16700Schasinglulu mtk_smc_handler 259*91f16700Schasinglulu ); 260