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