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