diff options
Diffstat (limited to 'services/std_svc/sdei/sdei_event.c')
-rw-r--r-- | services/std_svc/sdei/sdei_event.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/services/std_svc/sdei/sdei_event.c b/services/std_svc/sdei/sdei_event.c new file mode 100644 index 0000000..e0c7971 --- /dev/null +++ b/services/std_svc/sdei/sdei_event.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <lib/utils.h> + +#include "sdei_private.h" + +#define MAP_OFF(_map, _mapping) ((_map) - (_mapping)->map) + +/* + * Get SDEI entry with the given mapping: on success, returns pointer to SDEI + * entry. On error, returns NULL. + * + * Both shared and private maps are stored in single-dimensional array. Private + * event entries are kept for each PE forming a 2D array. + */ +sdei_entry_t *get_event_entry(sdei_ev_map_t *map) +{ + const sdei_mapping_t *mapping; + sdei_entry_t *cpu_priv_base; + unsigned int base_idx; + long int idx; + + if (is_event_private(map)) { + /* + * For a private map, find the index of the mapping in the + * array. + */ + mapping = SDEI_PRIVATE_MAPPING(); + idx = MAP_OFF(map, mapping); + + /* Base of private mappings for this CPU */ + base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps); + cpu_priv_base = &sdei_private_event_table[base_idx]; + + /* + * Return the address of the entry at the same index in the + * per-CPU event entry. + */ + return &cpu_priv_base[idx]; + } else { + mapping = SDEI_SHARED_MAPPING(); + idx = MAP_OFF(map, mapping); + + return &sdei_shared_event_table[idx]; + } +} + +/* + * Find event mapping for a given interrupt number: On success, returns pointer + * to the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i; + + /* + * Look for a match in private and shared mappings, as requested. This + * is a linear search. However, if the mappings are required to be + * sorted, for large maps, we could consider binary search. + */ + mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING(); + iterate_mapping(mapping, i, map) { + if (map->intr == intr_num) + return map; + } + + return NULL; +} + +/* + * Find event mapping for a given event number: On success returns pointer to + * the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map(int ev_num) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i, j; + + /* + * Iterate through mappings to find a match. This is a linear search. + * However, if the mappings are required to be sorted, for large maps, + * we could consider binary search. + */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + if (map->ev_num == ev_num) + return map; + } + } + + return NULL; +} + +/* + * Return the total number of currently registered SDEI events. + */ +int sdei_get_registered_event_count(void) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i; + unsigned int j; + int count = 0; + + /* Add up reg counts for each mapping. */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + count += map->reg_count; + } + } + + return count; +} |