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