xref: /rk3399_ARM-atf/common/runtime_svc.c (revision 14320bce3a5e8c213dd65c0c9c43dc8026e3bbbe)
1 /*
2  * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <arch.h>
12 #include <arch_helpers.h>
13 #include <arch_features.h>
14 #include <bl31/interrupt_mgmt.h>
15 #include <bl31/sync_handle.h>
16 #include <bl31/ea_handle.h>
17 #include <common/debug.h>
18 #include <common/runtime_svc.h>
19 #include <context.h>
20 #include <lib/cpus/cpu_ops.h>
21 #include <plat/common/platform.h>
22 
23 /*******************************************************************************
24  * The 'rt_svc_descs' array holds the runtime service descriptors exported by
25  * services by placing them in the 'rt_svc_descs' linker section.
26  * The 'rt_svc_descs_indices' array holds the index of a descriptor in the
27  * 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call
28  * type[31] bit in the function id are combined to get an index into the
29  * 'rt_svc_descs_indices' array. This gives the index of the descriptor in the
30  * 'rt_svc_descs' array which contains the SMC handler.
31  ******************************************************************************/
32 uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
33 
34 void __dead2 report_unhandled_exception(void);
35 
36 #define RT_SVC_DECS_NUM		((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\
37 					/ sizeof(rt_svc_desc_t))
38 
39 static bool get_handler_for_smc_fid(uint32_t smc_fid, rt_svc_handle_t *handler)
40 {
41 	unsigned int index;
42 	unsigned int idx;
43 	const rt_svc_desc_t *rt_svc_descs;
44 
45 	idx = get_unique_oen_from_smc_fid(smc_fid);
46 	assert(idx < MAX_RT_SVCS);
47 	index = rt_svc_descs_indices[idx];
48 
49 	if (index >= RT_SVC_DECS_NUM)
50 		return false;
51 
52 	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
53 	assert(handler != NULL);
54 	*handler = rt_svc_descs[index].handle;
55 	assert(*handler != NULL);
56 
57 	return true;
58 }
59 
60 #if __aarch64__
61 #include <lib/extensions/ras_arch.h>
62 
63 #if FFH_SUPPORT
64 static void ea_proceed(uint32_t ea_reason, u_register_t esr_el3, cpu_context_t *ctx)
65 {
66 	/*
67 	 * If it is a double fault invoke platform handler.  Double fault
68 	 * scenario would arise when platform is handling a fault in lower EL
69 	 * using plat_ea_handler() and another fault happens which would trap
70 	 * into EL3 as FFH_SUPPORT is enabled for the platform.
71 	 */
72 	el3_state_t *state = get_el3state_ctx(ctx);
73 	if (read_ctx_reg(state, CTX_DOUBLE_FAULT_ESR) != 0) {
74 		return plat_handle_double_fault(ea_reason, esr_el3);
75 	}
76 
77 	/*
78 	 * Save CTX_DOUBLE_FAULT_ESR, so that if another fault happens in lower
79 	 * EL, we catch it as DoubleFault in next invocation of ea_proceed()
80 	 * along with preserving original ESR_EL3.
81 	 */
82 	write_ctx_reg(state, CTX_DOUBLE_FAULT_ESR, esr_el3);
83 
84 	/* Call platform External Abort handler. */
85 	plat_ea_handler(ea_reason, esr_el3, NULL, ctx, read_scr_el3() & SCR_NS_BIT);
86 
87 	/* Clear Double Fault storage */
88 	write_ctx_reg(state, CTX_DOUBLE_FAULT_ESR, 0);
89 }
90 
91 /*
92  * This function handles SErrors from lower ELs.
93  *
94  * It delegates the handling of the EA to platform handler, and upon
95  * successfully handling the EA, exits EL3
96  */
97 void handler_lower_el_async_ea(cpu_context_t *ctx)
98 {
99 	u_register_t esr_el3 = read_esr_el3();
100 
101 #if ENABLE_FEAT_RAS
102 	/*  should only be invoked for SError */
103 	assert(EXTRACT(ESR_EC, esr_el3) == EC_SERROR);
104 
105 	/*
106 	 * Check for Implementation Defined Syndrome. If so, skip checking
107 	 * Uncontainable error type from the syndrome as the format is unknown.
108 	 */
109 	if ((esr_el3 & SERROR_IDS_BIT) != 0) {
110 		/* AET only valid when DFSC is 0x11. Route to platform fatal
111 		 * error handler if it is an uncontainable error type */
112 		if (EXTRACT(EABORT_DFSC, esr_el3) == DFSC_SERROR &&
113 		    EXTRACT(EABORT_AET, esr_el3) == ERROR_STATUS_UET_UC) {
114 			return plat_handle_uncontainable_ea();
115 		}
116 	}
117 #endif
118 	return ea_proceed(ERROR_EA_ASYNC, esr_el3, ctx);
119 }
120 
121 #endif /* FFH_SUPPORT */
122 
123 /*
124  * This function handles FIQ or IRQ interrupts i.e. EL3, S-EL1 and NS
125  * interrupts.
126  */
127 void handler_interrupt_exception(cpu_context_t *ctx)
128 {
129 	/*
130 	 * Find out whether this is a valid interrupt type.
131 	 * If the interrupt controller reports a spurious interrupt then return
132 	 * to where we came from.
133 	 */
134 	uint32_t type = plat_ic_get_pending_interrupt_type();
135 	if (type == INTR_TYPE_INVAL) {
136 		return;
137 	}
138 
139 	/*
140 	 * Get the registered handler for this interrupt type.
141 	 * A NULL return value could be 'cause of the following conditions:
142 	 *
143 	 * a. An interrupt of a type was routed correctly but a handler for its
144 	 *    type was not registered.
145 	 *
146 	 * b. An interrupt of a type was not routed correctly so a handler for
147 	 *    its type was not registered.
148 	 *
149 	 * c. An interrupt of a type was routed correctly to EL3, but was
150 	 *    deasserted before its pending state could be read. Another
151 	 *    interrupt of a different type pended at the same time and its
152 	 *    type was reported as pending instead. However, a handler for this
153 	 *    type was not registered.
154 	 *
155 	 * a. and b. can only happen due to a programming error. The
156 	 * occurrence of c. could be beyond the control of Trusted Firmware.
157 	 * It makes sense to return from this exception instead of reporting an
158 	 * error.
159 	 */
160 	interrupt_type_handler_t handler = get_interrupt_type_handler(type);
161 	if (handler == NULL) {
162 		return;
163 	}
164 
165 	handler(INTR_ID_UNAVAILABLE, read_scr_el3() & SCR_NS_BIT, ctx, NULL);
166 }
167 
168 static void smc_unknown(cpu_context_t *ctx)
169 {
170 	/*
171 	 * Unknown SMC call. Populate return value with SMC_UNK and call
172 	 * el3_exit() which will restore the remaining architectural state
173 	 * i.e., SYS, GP and PAuth registers(if any) prior to issuing the ERET
174 	 * to the desired lower EL.
175 	 */
176 	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, SMC_UNK);
177 }
178 
179 static u_register_t get_flags(uint32_t smc_fid, u_register_t scr_el3)
180 {
181 	u_register_t flags = 0;
182 
183 	/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
184 	flags |= scr_el3 & SCR_NS_BIT;
185 #if ENABLE_RME
186 	/* Copy SCR_EL3.NSE bit to the flag to indicate caller's security Shift
187 	 * copied SCR_EL3.NSE bit by 5 to create space for SCR_EL3.NS bit. Bit 5
188 	 * of the flag corresponds to the SCR_EL3.NSE bit.
189 	 */
190 	flags |= ((scr_el3 & SCR_NSE_BIT) >> SCR_NSE_SHIFT) << 5;
191 #endif /* ENABLE_RME */
192 
193 	/*
194 	 * Per SMCCCv1.3 a caller can set the SVE hint bit in the SMC FID passed
195 	 * through x0. Copy the SVE hint bit to flags and mask the bit in
196 	 * smc_fid passed to the standard service dispatcher.  A
197 	 * service/dispatcher can retrieve the SVE hint bit state from flags
198 	 * using the appropriate helper.
199 	 */
200 	flags |= smc_fid & MASK(FUNCID_SVE_HINT);
201 
202 	return flags;
203 }
204 
205 static void sync_handler(cpu_context_t *ctx, uint32_t smc_fid)
206 {
207 	u_register_t scr_el3 = read_scr_el3();
208 	rt_svc_handle_t handler;
209 
210 	/*
211 	 * Per SMCCC documentation, bits [23:17] must be zero for Fast SMCs.
212 	 * Other values are reserved for future use. Ensure that these bits are
213 	 * zeroes, if not report as unknown SMC.
214 	 */
215 	if (EXTRACT(FUNCID_TYPE, smc_fid) == SMC_TYPE_FAST &&
216 	    EXTRACT(FUNCID_FC_RESERVED, smc_fid) != 0) {
217 		return smc_unknown(ctx);
218 	}
219 
220 	smc_fid &= ~MASK(FUNCID_SVE_HINT);
221 
222 	/* Get the descriptor using the index */
223 	if (!get_handler_for_smc_fid(smc_fid, &handler)) {
224 		return smc_unknown(ctx);
225 	}
226 
227 	u_register_t x1, x2, x3, x4;
228 	get_smc_params_from_ctx(ctx, x1, x2, x3, x4);
229 	handler(smc_fid, x1, x2, x3, x4, NULL, ctx, get_flags(smc_fid, scr_el3));
230 }
231 
232 void handler_sync_exception(cpu_context_t *ctx)
233 {
234 	uint32_t smc_fid = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0);
235 	u_register_t esr_el3 = read_esr_el3();
236 	u_register_t exc_class = EXTRACT(ESR_EC, esr_el3);
237 	el3_state_t *state = get_el3state_ctx(ctx);
238 
239 	if (exc_class == EC_AARCH32_SMC || exc_class == EC_AARCH64_SMC) {
240 		if (exc_class == EC_AARCH32_SMC && EXTRACT(FUNCID_CC, smc_fid) != 0) {
241 			return smc_unknown(ctx);
242 		}
243 		return sync_handler(ctx, smc_fid);
244 	} else if (exc_class == EC_AARCH64_SYS) {
245 		int ret = handle_sysreg_trap(esr_el3, ctx, get_flags(smc_fid, read_scr_el3()));
246 
247 		/* unhandled trap, UNDEF injection into lower. The support is
248 		 * only provided for lower EL in AArch64 mode. */
249 		if (ret == TRAP_RET_UNHANDLED) {
250 			if (read_spsr_el3() & MASK(SPSR_M)) {
251 				lower_el_panic();
252 			}
253 			inject_undef64(ctx);
254 		} else if (ret == TRAP_RET_CONTINUE) {
255 			/* advance the PC to continue after the instruction */
256 			write_ctx_reg(state, CTX_ELR_EL3, read_ctx_reg(state, CTX_ELR_EL3) + 4);
257 		} /* otherwise return to the trapping instruction (repeating it) */
258 		return;
259 	/* If FFH Support then try to handle lower EL EA exceptions. */
260 	} else if ((exc_class == EC_IABORT_LOWER_EL || exc_class == EC_DABORT_LOWER_EL)
261 		    && (read_ctx_reg(state, CTX_SCR_EL3) | SCR_EA_BIT)) {
262 #if FFH_SUPPORT
263 		/*
264 		 * Check for Uncontainable error type. If so, route to the
265 		 * platform fatal error handler rather than the generic EA one.
266 		 */
267 		if (is_feat_ras_supported() &&
268 		    (EXTRACT(EABORT_SET, esr_el3) == ERROR_STATUS_SET_UC ||
269 		     EXTRACT(EABORT_DFSC, esr_el3) == SYNC_EA_FSC)) {
270 			return plat_handle_uncontainable_ea();
271 		}
272 		/* Setup exception class and syndrome arguments for platform handler */
273 		return ea_proceed(ERROR_EA_SYNC, esr_el3, ctx);
274 #endif /* FFH_SUPPORT */
275 	}
276 
277 	/* Synchronous exceptions other than the above are unhandled */
278 	report_unhandled_exception();
279 }
280 #endif /* __aarch64__ */
281 
282 /*******************************************************************************
283  * Function to invoke the registered `handle` corresponding to the smc_fid in
284  * AArch32 mode.
285  ******************************************************************************/
286 uintptr_t handle_runtime_svc(uint32_t smc_fid,
287 			     void *cookie,
288 			     void *handle,
289 			     unsigned int flags)
290 {
291 	u_register_t x1, x2, x3, x4;
292 	rt_svc_handle_t handler;
293 
294 	assert(handle != NULL);
295 
296 	if (!get_handler_for_smc_fid(smc_fid, &handler)) {
297 		SMC_RET1(handle, SMC_UNK);
298 	}
299 
300 	get_smc_params_from_ctx(handle, x1, x2, x3, x4);
301 
302 	return handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
303 }
304 
305 /*******************************************************************************
306  * Simple routine to sanity check a runtime service descriptor before using it
307  ******************************************************************************/
308 static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc)
309 {
310 	if (desc == NULL) {
311 		return -EINVAL;
312 	}
313 	if (desc->start_oen > desc->end_oen) {
314 		return -EINVAL;
315 	}
316 	if (desc->end_oen >= OEN_LIMIT) {
317 		return -EINVAL;
318 	}
319 	if ((desc->call_type != SMC_TYPE_FAST) &&
320 	    (desc->call_type != SMC_TYPE_YIELD)) {
321 		return -EINVAL;
322 	}
323 	/* A runtime service having no init or handle function doesn't make sense */
324 	if ((desc->init == NULL) && (desc->handle == NULL)) {
325 		return -EINVAL;
326 	}
327 	return 0;
328 }
329 
330 /*******************************************************************************
331  * This function calls the initialisation routine in the descriptor exported by
332  * a runtime service. Once a descriptor has been validated, its start & end
333  * owning entity numbers and the call type are combined to form a unique oen.
334  * The unique oen is used as an index into the 'rt_svc_descs_indices' array.
335  * The index of the runtime service descriptor is stored at this index.
336  ******************************************************************************/
337 void __init runtime_svc_init(void)
338 {
339 	int rc = 0;
340 	uint8_t index, start_idx, end_idx;
341 	rt_svc_desc_t *rt_svc_descs;
342 
343 	/* Assert the number of descriptors detected are less than maximum indices */
344 	assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&
345 			(RT_SVC_DECS_NUM < MAX_RT_SVCS));
346 
347 	/* If no runtime services are implemented then simply bail out */
348 	if (RT_SVC_DECS_NUM == 0U) {
349 		return;
350 	}
351 	/* Initialise internal variables to invalid state */
352 	(void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));
353 
354 	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
355 	for (index = 0U; index < RT_SVC_DECS_NUM; index++) {
356 		rt_svc_desc_t *service = &rt_svc_descs[index];
357 
358 		/*
359 		 * An invalid descriptor is an error condition since it is
360 		 * difficult to predict the system behaviour in the absence
361 		 * of this service.
362 		 */
363 		rc = validate_rt_svc_desc(service);
364 		if (rc != 0) {
365 			ERROR("Invalid runtime service descriptor %p\n",
366 				(void *) service);
367 			panic();
368 		}
369 
370 		/*
371 		 * The runtime service may have separate rt_svc_desc_t
372 		 * for its fast smc and yielding smc. Since the service itself
373 		 * need to be initialized only once, only one of them will have
374 		 * an initialisation routine defined. Call the initialisation
375 		 * routine for this runtime service, if it is defined.
376 		 */
377 		if (service->init != NULL) {
378 			rc = service->init();
379 			if (rc != 0) {
380 				ERROR("Error initializing runtime service %s\n",
381 						service->name);
382 				continue;
383 			}
384 		}
385 
386 		/*
387 		 * Fill the indices corresponding to the start and end
388 		 * owning entity numbers with the index of the
389 		 * descriptor which will handle the SMCs for this owning
390 		 * entity range.
391 		 */
392 		start_idx = (uint8_t)get_unique_oen(service->start_oen,
393 						    service->call_type);
394 		end_idx = (uint8_t)get_unique_oen(service->end_oen,
395 						  service->call_type);
396 		assert(start_idx <= end_idx);
397 		assert(end_idx < MAX_RT_SVCS);
398 		for (; start_idx <= end_idx; start_idx++) {
399 			rt_svc_descs_indices[start_idx] = index;
400 		}
401 	}
402 }
403