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