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