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