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