xref: /arm-trusted-firmware/plat/mediatek/common/mtk_smc_handlers.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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