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