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 <types.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