summaryrefslogtreecommitdiff
path: root/services/std_svc/sdei/sdei_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'services/std_svc/sdei/sdei_private.h')
-rw-r--r--services/std_svc/sdei/sdei_private.h234
1 files changed, 234 insertions, 0 deletions
diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h
new file mode 100644
index 00000000..44db4193
--- /dev/null
+++ b/services/std_svc/sdei/sdei_private.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SDEI_PRIVATE_H__
+#define __SDEI_PRIVATE_H__
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <errno.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
+#include <sdei.h>
+#include <spinlock.h>
+#include <stdbool.h>
+#include <types.h>
+#include <utils_def.h>
+
+#ifdef AARCH32
+# error SDEI is implemented only for AArch64 systems
+#endif
+
+#ifndef PLAT_SDEI_CRITICAL_PRI
+# error Platform must define SDEI critical priority value
+#endif
+
+#ifndef PLAT_SDEI_NORMAL_PRI
+# error Platform must define SDEI normal priority value
+#endif
+
+/* Output SDEI logs as verbose */
+#define SDEI_LOG(...) VERBOSE("SDEI: " __VA_ARGS__)
+
+/* SDEI handler unregistered state. This is the default state. */
+#define SDEI_STATE_UNREGISTERED 0
+
+/* SDE event status values in bit position */
+#define SDEI_STATF_REGISTERED 0
+#define SDEI_STATF_ENABLED 1
+#define SDEI_STATF_RUNNING 2
+
+/* SDEI SMC error codes */
+#define SDEI_EINVAL (-2)
+#define SDEI_EDENY (-3)
+#define SDEI_EPEND (-5)
+#define SDEI_ENOMEM (-10)
+
+/*
+ * 'info' parameter to SDEI_EVENT_GET_INFO SMC.
+ *
+ * Note that the SDEI v1.0 speification mistakenly enumerates the
+ * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a
+ * future version.
+ */
+#define SDEI_INFO_EV_TYPE 0
+#define SDEI_INFO_EV_NOT_SIGNALED 1
+#define SDEI_INFO_EV_PRIORITY 2
+#define SDEI_INFO_EV_ROUTING_MODE 3
+#define SDEI_INFO_EV_ROUTING_AFF 4
+
+#define SDEI_PRIVATE_MAPPING() (&sdei_global_mappings[_SDEI_MAP_IDX_PRIV])
+#define SDEI_SHARED_MAPPING() (&sdei_global_mappings[_SDEI_MAP_IDX_SHRD])
+
+#define for_each_mapping_type(_i, _mapping) \
+ for (_i = 0, _mapping = &sdei_global_mappings[i]; \
+ _i < _SDEI_MAP_IDX_MAX; \
+ _i++, _mapping = &sdei_global_mappings[i])
+
+#define iterate_mapping(_mapping, _i, _map) \
+ for (_map = (_mapping)->map, _i = 0; \
+ _i < (_mapping)->num_maps; \
+ _i++, _map++)
+
+#define for_each_private_map(_i, _map) \
+ iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map)
+
+#define for_each_shared_map(_i, _map) \
+ iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map)
+
+/* SDEI_FEATURES */
+#define SDEI_FEATURE_BIND_SLOTS 0
+#define BIND_SLOTS_MASK 0xffff
+#define FEATURES_SHARED_SLOTS_SHIFT 16
+#define FEATURES_PRIVATE_SLOTS_SHIFT 0
+#define FEATURE_BIND_SLOTS(_priv, _shrd) \
+ ((((_priv) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \
+ (((_shrd) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT))
+
+#define GET_EV_STATE(_e, _s) get_ev_state_bit(_e, SDEI_STATF_##_s)
+#define SET_EV_STATE(_e, _s) clr_ev_state_bit(_e->state, SDEI_STATF_##_s)
+
+static inline int is_event_private(sdei_ev_map_t *map)
+{
+ return ((map->map_flags & BIT(_SDEI_MAPF_PRIVATE_SHIFT)) != 0);
+}
+
+static inline int is_event_shared(sdei_ev_map_t *map)
+{
+ return !is_event_private(map);
+}
+
+static inline int is_event_critical(sdei_ev_map_t *map)
+{
+ return ((map->map_flags & BIT(_SDEI_MAPF_CRITICAL_SHIFT)) != 0);
+}
+
+static inline int is_event_normal(sdei_ev_map_t *map)
+{
+ return !is_event_critical(map);
+}
+
+static inline int is_event_signalable(sdei_ev_map_t *map)
+{
+ return ((map->map_flags & BIT(_SDEI_MAPF_SIGNALABLE_SHIFT)) != 0);
+}
+
+static inline int is_map_dynamic(sdei_ev_map_t *map)
+{
+ return ((map->map_flags & BIT(_SDEI_MAPF_DYNAMIC_SHIFT)) != 0);
+}
+
+/*
+ * Checks whether an event is associated with an interrupt. Static events always
+ * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been
+ * called on them. This can be used on both static or dynamic events to check
+ * for an associated interrupt.
+ */
+static inline int is_map_bound(sdei_ev_map_t *map)
+{
+ return ((map->map_flags & BIT(_SDEI_MAPF_BOUND_SHIFT)) != 0);
+}
+
+static inline void set_map_bound(sdei_ev_map_t *map)
+{
+ map->map_flags |= BIT(_SDEI_MAPF_BOUND_SHIFT);
+}
+
+static inline void clr_map_bound(sdei_ev_map_t *map)
+{
+ map->map_flags &= ~(BIT(_SDEI_MAPF_BOUND_SHIFT));
+}
+
+static inline int is_secure_sgi(unsigned int intr)
+{
+ return (plat_ic_is_sgi(intr) &&
+ (plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3));
+}
+
+/*
+ * Determine EL of the client. If EL2 is implemented (hence the enabled HCE
+ * bit), deem EL2; otherwise, deem EL1.
+ */
+static inline unsigned int sdei_client_el(void)
+{
+ return read_scr_el3() & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
+}
+
+static inline unsigned int sdei_event_priority(sdei_ev_map_t *map)
+{
+ return is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI :
+ PLAT_SDEI_NORMAL_PRI;
+}
+
+static inline int get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
+{
+ return ((se->state & BIT(bit_no)) != 0);
+}
+
+static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
+{
+ se->state &= ~BIT(bit_no);
+}
+
+/* SDEI actions for state transition */
+typedef enum {
+ /*
+ * Actions resulting from client requests. These directly map to SMC
+ * calls. Note that the state table columns are listed in this order
+ * too.
+ */
+ DO_REGISTER = 0,
+ DO_RELEASE = 1,
+ DO_ENABLE = 2,
+ DO_DISABLE = 3,
+ DO_UNREGISTER = 4,
+ DO_ROUTING = 5,
+ DO_CONTEXT = 6,
+ DO_COMPLETE = 7,
+ DO_COMPLETE_RESUME = 8,
+
+ /* Action for event dispatch */
+ DO_DISPATCH = 9,
+
+ DO_MAX,
+} sdei_action_t;
+
+typedef enum {
+ SDEI_NORMAL,
+ SDEI_CRITICAL
+} sdei_class_t;
+
+static inline void sdei_map_lock(sdei_ev_map_t *map)
+{
+ spin_lock(&map->lock);
+}
+
+static inline void sdei_map_unlock(sdei_ev_map_t *map)
+{
+ spin_unlock(&map->lock);
+}
+
+extern const sdei_mapping_t sdei_global_mappings[];
+extern sdei_entry_t sdei_private_event_table[];
+extern sdei_entry_t sdei_shared_event_table[];
+
+void init_sdei_state(void);
+
+sdei_ev_map_t *find_event_map_by_intr(int intr_num, int shared);
+sdei_ev_map_t *find_event_map(int ev_num);
+sdei_entry_t *get_event_entry(sdei_ev_map_t *map);
+
+int sdei_event_context(void *handle, unsigned int param);
+int sdei_event_complete(int resume, uint64_t arg);
+
+void sdei_pe_unmask(void);
+unsigned int sdei_pe_mask(void);
+
+int sdei_intr_handler(uint32_t intr, uint32_t flags, void *handle,
+ void *cookie);
+bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act);
+
+#endif /* __SDEI_PRIVATE_H__ */