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, unsigned int nm, 65 uint64_t target_pe) 66 { 67 sdei_entry_t *cpu_priv_base; 68 unsigned int base_idx = 0U; 69 long int idx; 70 int target_pos; 71 72 /* 73 * For a private map, find the index of the mapping in the 74 * array. 75 */ 76 idx = mapsub; 77 78 /* Base of private mappings for this CPU */ 79 target_pos = plat_core_pos_by_mpidr(target_pe); 80 81 if ((target_pos < 0) || ((unsigned int)target_pos >= PLATFORM_CORE_COUNT)) { 82 return NULL; 83 } 84 85 base_idx = (unsigned int) target_pos; 86 base_idx *= nm; 87 88 cpu_priv_base = &sdei_private_event_table[base_idx]; 89 90 /* 91 * Return the address of the entry at the same index in the 92 * per-CPU event entry. 93 */ 94 return &cpu_priv_base[idx]; 95 } 96 97 /* 98 * Find event mapping for a given interrupt number: On success, returns pointer 99 * to the event mapping. On error, returns NULL. 100 */ 101 sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared) 102 { 103 const sdei_mapping_t *mapping; 104 sdei_ev_map_t *map; 105 unsigned int i; 106 107 /* 108 * Look for a match in private and shared mappings, as requested. This 109 * is a linear search. However, if the mappings are required to be 110 * sorted, for large maps, we could consider binary search. 111 */ 112 mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING(); 113 iterate_mapping(mapping, i, map) { 114 if (map->intr == intr_num) 115 return map; 116 } 117 118 return NULL; 119 } 120 121 /* 122 * Find event mapping for a given event number: On success returns pointer to 123 * the event mapping. On error, returns NULL. 124 */ 125 sdei_ev_map_t *find_event_map(int ev_num) 126 { 127 const sdei_mapping_t *mapping; 128 sdei_ev_map_t *map; 129 unsigned int i, j; 130 131 /* 132 * Iterate through mappings to find a match. This is a linear search. 133 * However, if the mappings are required to be sorted, for large maps, 134 * we could consider binary search. 135 */ 136 for_each_mapping_type(i, mapping) { 137 iterate_mapping(mapping, j, map) { 138 if (map->ev_num == ev_num) 139 return map; 140 } 141 } 142 143 return NULL; 144 } 145 146 /* 147 * Return the total number of currently registered SDEI events. 148 */ 149 int sdei_get_registered_event_count(void) 150 { 151 const sdei_mapping_t *mapping; 152 sdei_ev_map_t *map; 153 unsigned int i; 154 unsigned int j; 155 int count = 0; 156 157 /* Add up reg counts for each mapping. */ 158 for_each_mapping_type(i, mapping) { 159 iterate_mapping(mapping, j, map) { 160 count += map->reg_count; 161 } 162 } 163 164 return count; 165 } 166