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