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