1b7cb133eSJeenu Viswambharan /* 2b142ede7SIgor Podgainõi * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved. 3b7cb133eSJeenu Viswambharan * 4b7cb133eSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 5b7cb133eSJeenu Viswambharan */ 6b7cb133eSJeenu Viswambharan 7b7cb133eSJeenu Viswambharan #include <assert.h> 809d40e0eSAntonio Nino Diaz 909d40e0eSAntonio Nino Diaz #include <lib/utils.h> 1009d40e0eSAntonio Nino Diaz 11b7cb133eSJeenu Viswambharan #include "sdei_private.h" 12b7cb133eSJeenu Viswambharan 13b7cb133eSJeenu Viswambharan #define MAP_OFF(_map, _mapping) ((_map) - (_mapping)->map) 14b7cb133eSJeenu Viswambharan 15b7cb133eSJeenu Viswambharan /* 16b7cb133eSJeenu Viswambharan * Get SDEI entry with the given mapping: on success, returns pointer to SDEI 17b7cb133eSJeenu Viswambharan * entry. On error, returns NULL. 18b7cb133eSJeenu Viswambharan * 19b7cb133eSJeenu Viswambharan * Both shared and private maps are stored in single-dimensional array. Private 20b7cb133eSJeenu Viswambharan * event entries are kept for each PE forming a 2D array. 21b7cb133eSJeenu Viswambharan */ 22b142ede7SIgor Podgainõi sdei_entry_t *get_event_entry(const sdei_ev_map_t *map) 23b7cb133eSJeenu Viswambharan { 24b7cb133eSJeenu Viswambharan const sdei_mapping_t *mapping; 25b7cb133eSJeenu Viswambharan sdei_entry_t *cpu_priv_base; 26ba6e5ca6SJeenu Viswambharan unsigned int base_idx; 27ba6e5ca6SJeenu Viswambharan long int idx; 28b7cb133eSJeenu Viswambharan 29b142ede7SIgor Podgainõi if ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U) { 30b7cb133eSJeenu Viswambharan /* 31b7cb133eSJeenu Viswambharan * For a private map, find the index of the mapping in the 32b7cb133eSJeenu Viswambharan * array. 33b7cb133eSJeenu Viswambharan */ 34b7cb133eSJeenu Viswambharan mapping = SDEI_PRIVATE_MAPPING(); 35b7cb133eSJeenu Viswambharan idx = MAP_OFF(map, mapping); 36b7cb133eSJeenu Viswambharan 37b7cb133eSJeenu Viswambharan /* Base of private mappings for this CPU */ 38ba6e5ca6SJeenu Viswambharan base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps); 39b7cb133eSJeenu Viswambharan cpu_priv_base = &sdei_private_event_table[base_idx]; 40b7cb133eSJeenu Viswambharan 41b7cb133eSJeenu Viswambharan /* 42b7cb133eSJeenu Viswambharan * Return the address of the entry at the same index in the 43b7cb133eSJeenu Viswambharan * per-CPU event entry. 44b7cb133eSJeenu Viswambharan */ 45b7cb133eSJeenu Viswambharan return &cpu_priv_base[idx]; 46b7cb133eSJeenu Viswambharan } else { 47b7cb133eSJeenu Viswambharan mapping = SDEI_SHARED_MAPPING(); 48b7cb133eSJeenu Viswambharan idx = MAP_OFF(map, mapping); 49b7cb133eSJeenu Viswambharan 50b7cb133eSJeenu Viswambharan return &sdei_shared_event_table[idx]; 51b7cb133eSJeenu Viswambharan } 52b7cb133eSJeenu Viswambharan } 53b7cb133eSJeenu Viswambharan 54b7cb133eSJeenu Viswambharan /* 55b142ede7SIgor Podgainõi * Retrieve the SDEI entry for the given mapping and target PE. 56b142ede7SIgor Podgainõi * 57b142ede7SIgor Podgainõi * on success : Returns a pointer to the SDEI entry 58b142ede7SIgor Podgainõi * 59b142ede7SIgor Podgainõi * On error, returns NULL 60b142ede7SIgor Podgainõi * 61b142ede7SIgor Podgainõi * Both shared and private maps are stored in single-dimensional array. Private 62b142ede7SIgor Podgainõi * event entries are kept for each PE forming a 2D array. 63b142ede7SIgor Podgainõi */ 64*9dde2cc1SMark Dykes sdei_entry_t *get_event_entry_target_pe(long int mapsub, unsigned int nm, 65*9dde2cc1SMark Dykes uint64_t target_pe) 66b142ede7SIgor Podgainõi { 67b142ede7SIgor Podgainõi sdei_entry_t *cpu_priv_base; 68*9dde2cc1SMark Dykes unsigned int base_idx = 0U; 69b142ede7SIgor Podgainõi long int idx; 70*9dde2cc1SMark Dykes int target_pos; 71b142ede7SIgor Podgainõi 72b142ede7SIgor Podgainõi /* 73b142ede7SIgor Podgainõi * For a private map, find the index of the mapping in the 74b142ede7SIgor Podgainõi * array. 75b142ede7SIgor Podgainõi */ 76b142ede7SIgor Podgainõi idx = mapsub; 77b142ede7SIgor Podgainõi 78b142ede7SIgor Podgainõi /* Base of private mappings for this CPU */ 79*9dde2cc1SMark Dykes target_pos = plat_core_pos_by_mpidr(target_pe); 80*9dde2cc1SMark Dykes 81*9dde2cc1SMark Dykes if ((target_pos < 0) || ((unsigned int)target_pos >= PLATFORM_CORE_COUNT)) { 82*9dde2cc1SMark Dykes return NULL; 83*9dde2cc1SMark Dykes } 84*9dde2cc1SMark Dykes 85*9dde2cc1SMark Dykes base_idx = (unsigned int) target_pos; 86b142ede7SIgor Podgainõi base_idx *= nm; 87*9dde2cc1SMark Dykes 88b142ede7SIgor Podgainõi cpu_priv_base = &sdei_private_event_table[base_idx]; 89*9dde2cc1SMark Dykes 90b142ede7SIgor Podgainõi /* 91b142ede7SIgor Podgainõi * Return the address of the entry at the same index in the 92b142ede7SIgor Podgainõi * per-CPU event entry. 93b142ede7SIgor Podgainõi */ 94b142ede7SIgor Podgainõi return &cpu_priv_base[idx]; 95b142ede7SIgor Podgainõi } 96b142ede7SIgor Podgainõi 97b142ede7SIgor Podgainõi /* 98b7cb133eSJeenu Viswambharan * Find event mapping for a given interrupt number: On success, returns pointer 99b7cb133eSJeenu Viswambharan * to the event mapping. On error, returns NULL. 100b7cb133eSJeenu Viswambharan */ 101ba6e5ca6SJeenu Viswambharan sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared) 102b7cb133eSJeenu Viswambharan { 103b7cb133eSJeenu Viswambharan const sdei_mapping_t *mapping; 104b7cb133eSJeenu Viswambharan sdei_ev_map_t *map; 105b7cb133eSJeenu Viswambharan unsigned int i; 106b7cb133eSJeenu Viswambharan 107b7cb133eSJeenu Viswambharan /* 108b7cb133eSJeenu Viswambharan * Look for a match in private and shared mappings, as requested. This 109b7cb133eSJeenu Viswambharan * is a linear search. However, if the mappings are required to be 110b7cb133eSJeenu Viswambharan * sorted, for large maps, we could consider binary search. 111b7cb133eSJeenu Viswambharan */ 112b7cb133eSJeenu Viswambharan mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING(); 113b7cb133eSJeenu Viswambharan iterate_mapping(mapping, i, map) { 114b7cb133eSJeenu Viswambharan if (map->intr == intr_num) 115b7cb133eSJeenu Viswambharan return map; 116b7cb133eSJeenu Viswambharan } 117b7cb133eSJeenu Viswambharan 118b7cb133eSJeenu Viswambharan return NULL; 119b7cb133eSJeenu Viswambharan } 120b7cb133eSJeenu Viswambharan 121b7cb133eSJeenu Viswambharan /* 122b7cb133eSJeenu Viswambharan * Find event mapping for a given event number: On success returns pointer to 123b7cb133eSJeenu Viswambharan * the event mapping. On error, returns NULL. 124b7cb133eSJeenu Viswambharan */ 125b7cb133eSJeenu Viswambharan sdei_ev_map_t *find_event_map(int ev_num) 126b7cb133eSJeenu Viswambharan { 127b7cb133eSJeenu Viswambharan const sdei_mapping_t *mapping; 128b7cb133eSJeenu Viswambharan sdei_ev_map_t *map; 129b7cb133eSJeenu Viswambharan unsigned int i, j; 130b7cb133eSJeenu Viswambharan 131b7cb133eSJeenu Viswambharan /* 132b7cb133eSJeenu Viswambharan * Iterate through mappings to find a match. This is a linear search. 133b7cb133eSJeenu Viswambharan * However, if the mappings are required to be sorted, for large maps, 134b7cb133eSJeenu Viswambharan * we could consider binary search. 135b7cb133eSJeenu Viswambharan */ 136b7cb133eSJeenu Viswambharan for_each_mapping_type(i, mapping) { 137b7cb133eSJeenu Viswambharan iterate_mapping(mapping, j, map) { 138b7cb133eSJeenu Viswambharan if (map->ev_num == ev_num) 139b7cb133eSJeenu Viswambharan return map; 140b7cb133eSJeenu Viswambharan } 141b7cb133eSJeenu Viswambharan } 142b7cb133eSJeenu Viswambharan 143b7cb133eSJeenu Viswambharan return NULL; 144b7cb133eSJeenu Viswambharan } 145e6381f9cSJohn Powell 146e6381f9cSJohn Powell /* 147e6381f9cSJohn Powell * Return the total number of currently registered SDEI events. 148e6381f9cSJohn Powell */ 149e6381f9cSJohn Powell int sdei_get_registered_event_count(void) 150e6381f9cSJohn Powell { 151e6381f9cSJohn Powell const sdei_mapping_t *mapping; 152e6381f9cSJohn Powell sdei_ev_map_t *map; 153e6381f9cSJohn Powell unsigned int i; 154e6381f9cSJohn Powell unsigned int j; 155e6381f9cSJohn Powell int count = 0; 156e6381f9cSJohn Powell 157e6381f9cSJohn Powell /* Add up reg counts for each mapping. */ 158e6381f9cSJohn Powell for_each_mapping_type(i, mapping) { 159e6381f9cSJohn Powell iterate_mapping(mapping, j, map) { 160e6381f9cSJohn Powell count += map->reg_count; 161e6381f9cSJohn Powell } 162e6381f9cSJohn Powell } 163e6381f9cSJohn Powell 164e6381f9cSJohn Powell return count; 165e6381f9cSJohn Powell } 166