1 /*
2 * Copyright (c) 2017-2022, 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 */
get_event_entry(sdei_ev_map_t * map)22 sdei_entry_t *get_event_entry(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 (is_event_private(map)) {
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 * Find event mapping for a given interrupt number: On success, returns pointer
56 * to the event mapping. On error, returns NULL.
57 */
find_event_map_by_intr(unsigned int intr_num,bool shared)58 sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared)
59 {
60 const sdei_mapping_t *mapping;
61 sdei_ev_map_t *map;
62 unsigned int i;
63
64 /*
65 * Look for a match in private and shared mappings, as requested. This
66 * is a linear search. However, if the mappings are required to be
67 * sorted, for large maps, we could consider binary search.
68 */
69 mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING();
70 iterate_mapping(mapping, i, map) {
71 if (map->intr == intr_num)
72 return map;
73 }
74
75 return NULL;
76 }
77
78 /*
79 * Find event mapping for a given event number: On success returns pointer to
80 * the event mapping. On error, returns NULL.
81 */
find_event_map(int ev_num)82 sdei_ev_map_t *find_event_map(int ev_num)
83 {
84 const sdei_mapping_t *mapping;
85 sdei_ev_map_t *map;
86 unsigned int i, j;
87
88 /*
89 * Iterate through mappings to find a match. This is a linear search.
90 * However, if the mappings are required to be sorted, for large maps,
91 * we could consider binary search.
92 */
93 for_each_mapping_type(i, mapping) {
94 iterate_mapping(mapping, j, map) {
95 if (map->ev_num == ev_num)
96 return map;
97 }
98 }
99
100 return NULL;
101 }
102
103 /*
104 * Return the total number of currently registered SDEI events.
105 */
sdei_get_registered_event_count(void)106 int sdei_get_registered_event_count(void)
107 {
108 const sdei_mapping_t *mapping;
109 sdei_ev_map_t *map;
110 unsigned int i;
111 unsigned int j;
112 int count = 0;
113
114 /* Add up reg counts for each mapping. */
115 for_each_mapping_type(i, mapping) {
116 iterate_mapping(mapping, j, map) {
117 count += map->reg_count;
118 }
119 }
120
121 return count;
122 }
123