xref: /rk3399_ARM-atf/services/std_svc/sdei/sdei_private.h (revision 084b886495ee167a3601e43ea9a25ace8e4c74d5)
1b7cb133eSJeenu Viswambharan /*
2b142ede7SIgor Podgainõi  * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
3b7cb133eSJeenu Viswambharan  *
4b7cb133eSJeenu Viswambharan  * SPDX-License-Identifier: BSD-3-Clause
5b7cb133eSJeenu Viswambharan  */
6b7cb133eSJeenu Viswambharan 
7ba6e5ca6SJeenu Viswambharan #ifndef SDEI_PRIVATE_H
8ba6e5ca6SJeenu Viswambharan #define SDEI_PRIVATE_H
9b7cb133eSJeenu Viswambharan 
10b7cb133eSJeenu Viswambharan #include <errno.h>
11b7cb133eSJeenu Viswambharan #include <stdbool.h>
1293c78ed2SAntonio Nino Diaz #include <stdint.h>
1309d40e0eSAntonio Nino Diaz 
1409d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1509d40e0eSAntonio Nino Diaz #include <bl31/interrupt_mgmt.h>
1609d40e0eSAntonio Nino Diaz #include <common/debug.h>
1709d40e0eSAntonio Nino Diaz #include <context.h>
1809d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/context_mgmt.h>
1909d40e0eSAntonio Nino Diaz #include <lib/spinlock.h>
2009d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
2109d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
2209d40e0eSAntonio Nino Diaz #include <services/sdei.h>
2309d40e0eSAntonio Nino Diaz #include <setjmp.h>
24b7cb133eSJeenu Viswambharan 
25402b3cf8SJulius Werner #ifndef __aarch64__
26b7cb133eSJeenu Viswambharan # error SDEI is implemented only for AArch64 systems
27b7cb133eSJeenu Viswambharan #endif
28b7cb133eSJeenu Viswambharan 
29b7cb133eSJeenu Viswambharan #ifndef PLAT_SDEI_CRITICAL_PRI
30b7cb133eSJeenu Viswambharan # error Platform must define SDEI critical priority value
31b7cb133eSJeenu Viswambharan #endif
32b7cb133eSJeenu Viswambharan 
33b7cb133eSJeenu Viswambharan #ifndef PLAT_SDEI_NORMAL_PRI
34b7cb133eSJeenu Viswambharan # error Platform must define SDEI normal priority value
35b7cb133eSJeenu Viswambharan #endif
36b7cb133eSJeenu Viswambharan 
37b7cb133eSJeenu Viswambharan /* Output SDEI logs as verbose */
38b7cb133eSJeenu Viswambharan #define SDEI_LOG(...)	VERBOSE("SDEI: " __VA_ARGS__)
39b7cb133eSJeenu Viswambharan 
40b7cb133eSJeenu Viswambharan /* SDEI handler unregistered state. This is the default state. */
41ba6e5ca6SJeenu Viswambharan #define SDEI_STATE_UNREGISTERED		0U
42b7cb133eSJeenu Viswambharan 
43b7cb133eSJeenu Viswambharan /* SDE event status values in bit position */
44ba6e5ca6SJeenu Viswambharan #define SDEI_STATF_REGISTERED		0U
45ba6e5ca6SJeenu Viswambharan #define SDEI_STATF_ENABLED		1U
46ba6e5ca6SJeenu Viswambharan #define SDEI_STATF_RUNNING		2U
47b7cb133eSJeenu Viswambharan 
48b7cb133eSJeenu Viswambharan /* SDEI SMC error codes */
49b7cb133eSJeenu Viswambharan #define	SDEI_EINVAL	(-2)
50b7cb133eSJeenu Viswambharan #define	SDEI_EDENY	(-3)
51b7cb133eSJeenu Viswambharan #define	SDEI_EPEND	(-5)
52b7cb133eSJeenu Viswambharan #define	SDEI_ENOMEM	(-10)
53b7cb133eSJeenu Viswambharan 
54b7cb133eSJeenu Viswambharan /*
55b7cb133eSJeenu Viswambharan  * 'info' parameter to SDEI_EVENT_GET_INFO SMC.
56b7cb133eSJeenu Viswambharan  *
578aabea33SPaul Beesley  * Note that the SDEI v1.0 specification mistakenly enumerates the
58b7cb133eSJeenu Viswambharan  * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a
59b7cb133eSJeenu Viswambharan  * future version.
60b7cb133eSJeenu Viswambharan  */
61b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_TYPE		0
62b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_NOT_SIGNALED	1
63b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_PRIORITY		2
64b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_ROUTING_MODE	3
65b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_ROUTING_AFF	4
66b7cb133eSJeenu Viswambharan 
67ba6e5ca6SJeenu Viswambharan #define SDEI_PRIVATE_MAPPING()	(&sdei_global_mappings[SDEI_MAP_IDX_PRIV_])
68ba6e5ca6SJeenu Viswambharan #define SDEI_SHARED_MAPPING()	(&sdei_global_mappings[SDEI_MAP_IDX_SHRD_])
69b7cb133eSJeenu Viswambharan 
70b7cb133eSJeenu Viswambharan #define for_each_mapping_type(_i, _mapping) \
71ba6e5ca6SJeenu Viswambharan 	for ((_i) = 0, (_mapping) = &sdei_global_mappings[(_i)]; \
72ba6e5ca6SJeenu Viswambharan 			(_i) < SDEI_MAP_IDX_MAX_; \
73ba6e5ca6SJeenu Viswambharan 			(_i)++, (_mapping) = &sdei_global_mappings[(_i)])
74b7cb133eSJeenu Viswambharan 
75b7cb133eSJeenu Viswambharan #define iterate_mapping(_mapping, _i, _map) \
76ba6e5ca6SJeenu Viswambharan 	for ((_map) = (_mapping)->map, (_i) = 0; \
77ba6e5ca6SJeenu Viswambharan 			(_i) < (_mapping)->num_maps; \
78ba6e5ca6SJeenu Viswambharan 			(_i)++, (_map)++)
79b7cb133eSJeenu Viswambharan 
80b7cb133eSJeenu Viswambharan #define for_each_private_map(_i, _map) \
81b7cb133eSJeenu Viswambharan 	iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map)
82b7cb133eSJeenu Viswambharan 
83b7cb133eSJeenu Viswambharan #define for_each_shared_map(_i, _map) \
84b7cb133eSJeenu Viswambharan 	iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map)
85b7cb133eSJeenu Viswambharan 
86b7cb133eSJeenu Viswambharan /* SDEI_FEATURES */
87ba6e5ca6SJeenu Viswambharan #define SDEI_FEATURE_BIND_SLOTS		0U
88ba6e5ca6SJeenu Viswambharan #define BIND_SLOTS_MASK			0xffffU
89ba6e5ca6SJeenu Viswambharan #define FEATURES_SHARED_SLOTS_SHIFT	16U
90ba6e5ca6SJeenu Viswambharan #define FEATURES_PRIVATE_SLOTS_SHIFT	0U
91b7cb133eSJeenu Viswambharan #define FEATURE_BIND_SLOTS(_priv, _shrd) \
92ba6e5ca6SJeenu Viswambharan 	(((((uint64_t) (_priv)) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \
93ba6e5ca6SJeenu Viswambharan 	 ((((uint64_t) (_shrd)) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT))
94b7cb133eSJeenu Viswambharan 
95b7cb133eSJeenu Viswambharan #define GET_EV_STATE(_e, _s)	get_ev_state_bit(_e, SDEI_STATF_##_s)
96b7cb133eSJeenu Viswambharan #define SET_EV_STATE(_e, _s)	clr_ev_state_bit(_e->state, SDEI_STATF_##_s)
97b7cb133eSJeenu Viswambharan 
is_event_private(sdei_ev_map_t * map)98ba6e5ca6SJeenu Viswambharan static inline bool is_event_private(sdei_ev_map_t *map)
99b7cb133eSJeenu Viswambharan {
100ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U);
101b7cb133eSJeenu Viswambharan }
102b7cb133eSJeenu Viswambharan 
is_event_shared(sdei_ev_map_t * map)103ba6e5ca6SJeenu Viswambharan static inline bool is_event_shared(sdei_ev_map_t *map)
104b7cb133eSJeenu Viswambharan {
105b7cb133eSJeenu Viswambharan 	return !is_event_private(map);
106b7cb133eSJeenu Viswambharan }
107b7cb133eSJeenu Viswambharan 
is_event_critical(sdei_ev_map_t * map)108ba6e5ca6SJeenu Viswambharan static inline bool is_event_critical(sdei_ev_map_t *map)
109b7cb133eSJeenu Viswambharan {
110ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_CRITICAL_SHIFT_)) != 0U);
111b7cb133eSJeenu Viswambharan }
112b7cb133eSJeenu Viswambharan 
is_event_normal(sdei_ev_map_t * map)113ba6e5ca6SJeenu Viswambharan static inline bool is_event_normal(sdei_ev_map_t *map)
114b7cb133eSJeenu Viswambharan {
115b7cb133eSJeenu Viswambharan 	return !is_event_critical(map);
116b7cb133eSJeenu Viswambharan }
117b7cb133eSJeenu Viswambharan 
is_event_signalable(sdei_ev_map_t * map)118ba6e5ca6SJeenu Viswambharan static inline bool is_event_signalable(sdei_ev_map_t *map)
119b7cb133eSJeenu Viswambharan {
120ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_SIGNALABLE_SHIFT_)) != 0U);
121b7cb133eSJeenu Viswambharan }
122b7cb133eSJeenu Viswambharan 
is_map_dynamic(sdei_ev_map_t * map)123ba6e5ca6SJeenu Viswambharan static inline bool is_map_dynamic(sdei_ev_map_t *map)
124b7cb133eSJeenu Viswambharan {
125ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_DYNAMIC_SHIFT_)) != 0U);
126b7cb133eSJeenu Viswambharan }
127b7cb133eSJeenu Viswambharan 
128b7cb133eSJeenu Viswambharan /*
129b7cb133eSJeenu Viswambharan  * Checks whether an event is associated with an interrupt. Static events always
130b7cb133eSJeenu Viswambharan  * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been
131b7cb133eSJeenu Viswambharan  * called on them. This can be used on both static or dynamic events to check
132b7cb133eSJeenu Viswambharan  * for an associated interrupt.
133b7cb133eSJeenu Viswambharan  */
is_map_bound(sdei_ev_map_t * map)134ba6e5ca6SJeenu Viswambharan static inline bool is_map_bound(sdei_ev_map_t *map)
135b7cb133eSJeenu Viswambharan {
136ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_BOUND_SHIFT_)) != 0U);
137b7cb133eSJeenu Viswambharan }
138b7cb133eSJeenu Viswambharan 
set_map_bound(sdei_ev_map_t * map)139b7cb133eSJeenu Viswambharan static inline void set_map_bound(sdei_ev_map_t *map)
140b7cb133eSJeenu Viswambharan {
141ba6e5ca6SJeenu Viswambharan 	map->map_flags |= BIT_32(SDEI_MAPF_BOUND_SHIFT_);
142b7cb133eSJeenu Viswambharan }
143b7cb133eSJeenu Viswambharan 
is_map_explicit(sdei_ev_map_t * map)144ba6e5ca6SJeenu Viswambharan static inline bool is_map_explicit(sdei_ev_map_t *map)
145af2c9ecdSJeenu Viswambharan {
146ba6e5ca6SJeenu Viswambharan 	return ((map->map_flags & BIT_32(SDEI_MAPF_EXPLICIT_SHIFT_)) != 0U);
147af2c9ecdSJeenu Viswambharan }
148af2c9ecdSJeenu Viswambharan 
clr_map_bound(sdei_ev_map_t * map)149b7cb133eSJeenu Viswambharan static inline void clr_map_bound(sdei_ev_map_t *map)
150b7cb133eSJeenu Viswambharan {
151ba6e5ca6SJeenu Viswambharan 	map->map_flags &= ~BIT_32(SDEI_MAPF_BOUND_SHIFT_);
152b7cb133eSJeenu Viswambharan }
153b7cb133eSJeenu Viswambharan 
is_secure_sgi(unsigned int intr)154ba6e5ca6SJeenu Viswambharan static inline bool is_secure_sgi(unsigned int intr)
155b7cb133eSJeenu Viswambharan {
156ba6e5ca6SJeenu Viswambharan 	return ((plat_ic_is_sgi(intr) != 0) &&
157b7cb133eSJeenu Viswambharan 			(plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3));
158b7cb133eSJeenu Viswambharan }
159b7cb133eSJeenu Viswambharan 
160b7cb133eSJeenu Viswambharan /*
161b7cb133eSJeenu Viswambharan  * Determine EL of the client. If EL2 is implemented (hence the enabled HCE
162b7cb133eSJeenu Viswambharan  * bit), deem EL2; otherwise, deem EL1.
163b7cb133eSJeenu Viswambharan  */
sdei_client_el(void)164b7cb133eSJeenu Viswambharan static inline unsigned int sdei_client_el(void)
165b7cb133eSJeenu Viswambharan {
1662ccfcb2eSJeenu Viswambharan 	cpu_context_t *ns_ctx = cm_get_context(NON_SECURE);
1672ccfcb2eSJeenu Viswambharan 	el3_state_t *el3_ctx = get_el3state_ctx(ns_ctx);
1682ccfcb2eSJeenu Viswambharan 
169ba6e5ca6SJeenu Viswambharan 	return ((read_ctx_reg(el3_ctx, CTX_SCR_EL3) & SCR_HCE_BIT) != 0U) ?
170ba6e5ca6SJeenu Viswambharan 		MODE_EL2 : MODE_EL1;
171b7cb133eSJeenu Viswambharan }
172b7cb133eSJeenu Viswambharan 
sdei_event_priority(sdei_ev_map_t * map)173b7cb133eSJeenu Viswambharan static inline unsigned int sdei_event_priority(sdei_ev_map_t *map)
174b7cb133eSJeenu Viswambharan {
175ba6e5ca6SJeenu Viswambharan 	return (unsigned int) (is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI :
176ba6e5ca6SJeenu Viswambharan 			PLAT_SDEI_NORMAL_PRI);
177b7cb133eSJeenu Viswambharan }
178b7cb133eSJeenu Viswambharan 
get_ev_state_bit(sdei_entry_t * se,unsigned int bit_no)179ba6e5ca6SJeenu Viswambharan static inline bool get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
180b7cb133eSJeenu Viswambharan {
181ba6e5ca6SJeenu Viswambharan 	return ((se->state & BIT_32(bit_no)) != 0U);
182b7cb133eSJeenu Viswambharan }
183b7cb133eSJeenu Viswambharan 
clr_ev_state_bit(sdei_entry_t * se,unsigned int bit_no)184b7cb133eSJeenu Viswambharan static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
185b7cb133eSJeenu Viswambharan {
186ba6e5ca6SJeenu Viswambharan 	se->state &= ~BIT_32(bit_no);
187b7cb133eSJeenu Viswambharan }
188b7cb133eSJeenu Viswambharan 
189b7cb133eSJeenu Viswambharan /* SDEI actions for state transition */
190b7cb133eSJeenu Viswambharan typedef enum {
191b7cb133eSJeenu Viswambharan 	/*
192b7cb133eSJeenu Viswambharan 	 * Actions resulting from client requests. These directly map to SMC
193b7cb133eSJeenu Viswambharan 	 * calls. Note that the state table columns are listed in this order
194b7cb133eSJeenu Viswambharan 	 * too.
195b7cb133eSJeenu Viswambharan 	 */
196b7cb133eSJeenu Viswambharan 	DO_REGISTER = 0,
197b7cb133eSJeenu Viswambharan 	DO_RELEASE = 1,
198b7cb133eSJeenu Viswambharan 	DO_ENABLE = 2,
199b7cb133eSJeenu Viswambharan 	DO_DISABLE = 3,
200b7cb133eSJeenu Viswambharan 	DO_UNREGISTER = 4,
201b7cb133eSJeenu Viswambharan 	DO_ROUTING = 5,
202b7cb133eSJeenu Viswambharan 	DO_CONTEXT = 6,
203b7cb133eSJeenu Viswambharan 	DO_COMPLETE = 7,
204b7cb133eSJeenu Viswambharan 	DO_COMPLETE_RESUME = 8,
205b7cb133eSJeenu Viswambharan 
206b7cb133eSJeenu Viswambharan 	/* Action for event dispatch */
207b7cb133eSJeenu Viswambharan 	DO_DISPATCH = 9,
208b7cb133eSJeenu Viswambharan 
209b7cb133eSJeenu Viswambharan 	DO_MAX,
210b7cb133eSJeenu Viswambharan } sdei_action_t;
211b7cb133eSJeenu Viswambharan 
212b7cb133eSJeenu Viswambharan typedef enum {
213b7cb133eSJeenu Viswambharan 	SDEI_NORMAL,
214b7cb133eSJeenu Viswambharan 	SDEI_CRITICAL
215b7cb133eSJeenu Viswambharan } sdei_class_t;
216b7cb133eSJeenu Viswambharan 
sdei_map_lock(sdei_ev_map_t * map)217b7cb133eSJeenu Viswambharan static inline void sdei_map_lock(sdei_ev_map_t *map)
218b7cb133eSJeenu Viswambharan {
219b7cb133eSJeenu Viswambharan 	spin_lock(&map->lock);
220b7cb133eSJeenu Viswambharan }
221b7cb133eSJeenu Viswambharan 
sdei_map_unlock(sdei_ev_map_t * map)222b7cb133eSJeenu Viswambharan static inline void sdei_map_unlock(sdei_ev_map_t *map)
223b7cb133eSJeenu Viswambharan {
224b7cb133eSJeenu Viswambharan 	spin_unlock(&map->lock);
225b7cb133eSJeenu Viswambharan }
226b7cb133eSJeenu Viswambharan 
227b7cb133eSJeenu Viswambharan extern const sdei_mapping_t sdei_global_mappings[];
228b7cb133eSJeenu Viswambharan extern sdei_entry_t sdei_private_event_table[];
229b7cb133eSJeenu Viswambharan extern sdei_entry_t sdei_shared_event_table[];
230b7cb133eSJeenu Viswambharan 
231b7cb133eSJeenu Viswambharan void init_sdei_state(void);
232b7cb133eSJeenu Viswambharan 
233ba6e5ca6SJeenu Viswambharan sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared);
234b7cb133eSJeenu Viswambharan sdei_ev_map_t *find_event_map(int ev_num);
235b142ede7SIgor Podgainõi sdei_entry_t *get_event_entry(const sdei_ev_map_t *map);
236*6d113285SGovindraj Raja sdei_entry_t *get_event_entry_target_pe(long int mapsub, size_t nm, uint64_t target_pe);
237b7cb133eSJeenu Viswambharan 
238ba6e5ca6SJeenu Viswambharan int64_t sdei_event_context(void *handle, unsigned int param);
239ba6e5ca6SJeenu Viswambharan int sdei_event_complete(bool resume, uint64_t pc);
240b7cb133eSJeenu Viswambharan 
241b142ede7SIgor Podgainõi bool sdei_is_target_pe_masked(uint64_t target_pe);
242ba6e5ca6SJeenu Viswambharan int64_t sdei_pe_mask(void);
243b142ede7SIgor Podgainõi void sdei_pe_unmask(void);
244b7cb133eSJeenu Viswambharan 
245ba6e5ca6SJeenu Viswambharan int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle,
246b7cb133eSJeenu Viswambharan 		void *cookie);
247b7cb133eSJeenu Viswambharan bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act);
248e0566305SAntonio Nino Diaz void begin_sdei_synchronous_dispatch(jmp_buf *buffer);
249b7cb133eSJeenu Viswambharan 
250ba6e5ca6SJeenu Viswambharan #endif /* SDEI_PRIVATE_H */
251