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