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