blob: 821266740c20a40ac2f5fc300e6e482cba3e687c [file] [log] [blame]
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01001/*
Jeenu Viswambharan34392302018-01-17 12:30:11 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +01007#ifndef SDEI_PRIVATE_H
8#define SDEI_PRIVATE_H
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01009
10#include <arch_helpers.h>
Varun Wadekard8395ba2018-10-30 17:05:59 -070011#include <context.h>
Jeenu Viswambharan061e9f52018-06-21 08:47:42 +010012#include <context_mgmt.h>
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010013#include <debug.h>
14#include <errno.h>
15#include <interrupt_mgmt.h>
16#include <platform.h>
17#include <sdei.h>
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +000018#include <setjmp.h>
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010019#include <spinlock.h>
20#include <stdbool.h>
Antonio Nino Diaz4b32e622018-08-16 16:52:57 +010021#include <stdint.h>
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010022#include <utils_def.h>
23
24#ifdef AARCH32
25# error SDEI is implemented only for AArch64 systems
26#endif
27
28#ifndef PLAT_SDEI_CRITICAL_PRI
29# error Platform must define SDEI critical priority value
30#endif
31
32#ifndef PLAT_SDEI_NORMAL_PRI
33# error Platform must define SDEI normal priority value
34#endif
35
36/* Output SDEI logs as verbose */
37#define SDEI_LOG(...) VERBOSE("SDEI: " __VA_ARGS__)
38
39/* SDEI handler unregistered state. This is the default state. */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010040#define SDEI_STATE_UNREGISTERED 0U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010041
42/* SDE event status values in bit position */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010043#define SDEI_STATF_REGISTERED 0U
44#define SDEI_STATF_ENABLED 1U
45#define SDEI_STATF_RUNNING 2U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010046
47/* SDEI SMC error codes */
48#define SDEI_EINVAL (-2)
49#define SDEI_EDENY (-3)
50#define SDEI_EPEND (-5)
51#define SDEI_ENOMEM (-10)
52
53/*
54 * 'info' parameter to SDEI_EVENT_GET_INFO SMC.
55 *
56 * Note that the SDEI v1.0 speification mistakenly enumerates the
57 * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a
58 * future version.
59 */
60#define SDEI_INFO_EV_TYPE 0
61#define SDEI_INFO_EV_NOT_SIGNALED 1
62#define SDEI_INFO_EV_PRIORITY 2
63#define SDEI_INFO_EV_ROUTING_MODE 3
64#define SDEI_INFO_EV_ROUTING_AFF 4
65
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010066#define SDEI_PRIVATE_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_PRIV_])
67#define SDEI_SHARED_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_SHRD_])
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010068
69#define for_each_mapping_type(_i, _mapping) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010070 for ((_i) = 0, (_mapping) = &sdei_global_mappings[(_i)]; \
71 (_i) < SDEI_MAP_IDX_MAX_; \
72 (_i)++, (_mapping) = &sdei_global_mappings[(_i)])
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010073
74#define iterate_mapping(_mapping, _i, _map) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010075 for ((_map) = (_mapping)->map, (_i) = 0; \
76 (_i) < (_mapping)->num_maps; \
77 (_i)++, (_map)++)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010078
79#define for_each_private_map(_i, _map) \
80 iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map)
81
82#define for_each_shared_map(_i, _map) \
83 iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map)
84
85/* SDEI_FEATURES */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010086#define SDEI_FEATURE_BIND_SLOTS 0U
87#define BIND_SLOTS_MASK 0xffffU
88#define FEATURES_SHARED_SLOTS_SHIFT 16U
89#define FEATURES_PRIVATE_SLOTS_SHIFT 0U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010090#define FEATURE_BIND_SLOTS(_priv, _shrd) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010091 (((((uint64_t) (_priv)) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \
92 ((((uint64_t) (_shrd)) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT))
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010093
94#define GET_EV_STATE(_e, _s) get_ev_state_bit(_e, SDEI_STATF_##_s)
95#define SET_EV_STATE(_e, _s) clr_ev_state_bit(_e->state, SDEI_STATF_##_s)
96
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010097static inline bool is_event_private(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010098{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010099 return ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100100}
101
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100102static inline bool is_event_shared(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100103{
104 return !is_event_private(map);
105}
106
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100107static inline bool is_event_critical(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100108{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100109 return ((map->map_flags & BIT_32(SDEI_MAPF_CRITICAL_SHIFT_)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100110}
111
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100112static inline bool is_event_normal(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100113{
114 return !is_event_critical(map);
115}
116
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100117static inline bool is_event_signalable(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100118{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100119 return ((map->map_flags & BIT_32(SDEI_MAPF_SIGNALABLE_SHIFT_)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100120}
121
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100122static inline bool is_map_dynamic(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100123{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100124 return ((map->map_flags & BIT_32(SDEI_MAPF_DYNAMIC_SHIFT_)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100125}
126
127/*
128 * Checks whether an event is associated with an interrupt. Static events always
129 * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been
130 * called on them. This can be used on both static or dynamic events to check
131 * for an associated interrupt.
132 */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100133static inline bool is_map_bound(sdei_ev_map_t *map)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100134{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100135 return ((map->map_flags & BIT_32(SDEI_MAPF_BOUND_SHIFT_)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100136}
137
138static inline void set_map_bound(sdei_ev_map_t *map)
139{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100140 map->map_flags |= BIT_32(SDEI_MAPF_BOUND_SHIFT_);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100141}
142
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100143static inline bool is_map_explicit(sdei_ev_map_t *map)
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000144{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100145 return ((map->map_flags & BIT_32(SDEI_MAPF_EXPLICIT_SHIFT_)) != 0U);
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000146}
147
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100148static inline void clr_map_bound(sdei_ev_map_t *map)
149{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100150 map->map_flags &= ~BIT_32(SDEI_MAPF_BOUND_SHIFT_);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100151}
152
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100153static inline bool is_secure_sgi(unsigned int intr)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100154{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100155 return ((plat_ic_is_sgi(intr) != 0) &&
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100156 (plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3));
157}
158
159/*
160 * Determine EL of the client. If EL2 is implemented (hence the enabled HCE
161 * bit), deem EL2; otherwise, deem EL1.
162 */
163static inline unsigned int sdei_client_el(void)
164{
Jeenu Viswambharan061e9f52018-06-21 08:47:42 +0100165 cpu_context_t *ns_ctx = cm_get_context(NON_SECURE);
166 el3_state_t *el3_ctx = get_el3state_ctx(ns_ctx);
167
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100168 return ((read_ctx_reg(el3_ctx, CTX_SCR_EL3) & SCR_HCE_BIT) != 0U) ?
169 MODE_EL2 : MODE_EL1;
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100170}
171
172static inline unsigned int sdei_event_priority(sdei_ev_map_t *map)
173{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100174 return (unsigned int) (is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI :
175 PLAT_SDEI_NORMAL_PRI);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100176}
177
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100178static inline bool get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100179{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100180 return ((se->state & BIT_32(bit_no)) != 0U);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100181}
182
183static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
184{
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100185 se->state &= ~BIT_32(bit_no);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100186}
187
188/* SDEI actions for state transition */
189typedef enum {
190 /*
191 * Actions resulting from client requests. These directly map to SMC
192 * calls. Note that the state table columns are listed in this order
193 * too.
194 */
195 DO_REGISTER = 0,
196 DO_RELEASE = 1,
197 DO_ENABLE = 2,
198 DO_DISABLE = 3,
199 DO_UNREGISTER = 4,
200 DO_ROUTING = 5,
201 DO_CONTEXT = 6,
202 DO_COMPLETE = 7,
203 DO_COMPLETE_RESUME = 8,
204
205 /* Action for event dispatch */
206 DO_DISPATCH = 9,
207
208 DO_MAX,
209} sdei_action_t;
210
211typedef enum {
212 SDEI_NORMAL,
213 SDEI_CRITICAL
214} sdei_class_t;
215
216static inline void sdei_map_lock(sdei_ev_map_t *map)
217{
218 spin_lock(&map->lock);
219}
220
221static inline void sdei_map_unlock(sdei_ev_map_t *map)
222{
223 spin_unlock(&map->lock);
224}
225
226extern const sdei_mapping_t sdei_global_mappings[];
227extern sdei_entry_t sdei_private_event_table[];
228extern sdei_entry_t sdei_shared_event_table[];
229
230void init_sdei_state(void);
231
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100232sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100233sdei_ev_map_t *find_event_map(int ev_num);
234sdei_entry_t *get_event_entry(sdei_ev_map_t *map);
235
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100236int64_t sdei_event_context(void *handle, unsigned int param);
237int sdei_event_complete(bool resume, uint64_t pc);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100238
239void sdei_pe_unmask(void);
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100240int64_t sdei_pe_mask(void);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100241
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100242int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle,
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100243 void *cookie);
244bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act);
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000245void begin_sdei_synchronous_dispatch(struct jmpbuf *buffer);
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100246
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100247#endif /* SDEI_PRIVATE_H */