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