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