xref: /arm-trusted-firmware/services/std_svc/sdei/sdei_event.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <lib/utils.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu #include "sdei_private.h"
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #define MAP_OFF(_map, _mapping) ((_map) - (_mapping)->map)
14*91f16700Schasinglulu 
15*91f16700Schasinglulu /*
16*91f16700Schasinglulu  * Get SDEI entry with the given mapping: on success, returns pointer to SDEI
17*91f16700Schasinglulu  * entry. On error, returns NULL.
18*91f16700Schasinglulu  *
19*91f16700Schasinglulu  * Both shared and private maps are stored in single-dimensional array. Private
20*91f16700Schasinglulu  * event entries are kept for each PE forming a 2D array.
21*91f16700Schasinglulu  */
22*91f16700Schasinglulu sdei_entry_t *get_event_entry(sdei_ev_map_t *map)
23*91f16700Schasinglulu {
24*91f16700Schasinglulu 	const sdei_mapping_t *mapping;
25*91f16700Schasinglulu 	sdei_entry_t *cpu_priv_base;
26*91f16700Schasinglulu 	unsigned int base_idx;
27*91f16700Schasinglulu 	long int idx;
28*91f16700Schasinglulu 
29*91f16700Schasinglulu 	if (is_event_private(map)) {
30*91f16700Schasinglulu 		/*
31*91f16700Schasinglulu 		 * For a private map, find the index of the mapping in the
32*91f16700Schasinglulu 		 * array.
33*91f16700Schasinglulu 		 */
34*91f16700Schasinglulu 		mapping = SDEI_PRIVATE_MAPPING();
35*91f16700Schasinglulu 		idx = MAP_OFF(map, mapping);
36*91f16700Schasinglulu 
37*91f16700Schasinglulu 		/* Base of private mappings for this CPU */
38*91f16700Schasinglulu 		base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps);
39*91f16700Schasinglulu 		cpu_priv_base = &sdei_private_event_table[base_idx];
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 		/*
42*91f16700Schasinglulu 		 * Return the address of the entry at the same index in the
43*91f16700Schasinglulu 		 * per-CPU event entry.
44*91f16700Schasinglulu 		 */
45*91f16700Schasinglulu 		return &cpu_priv_base[idx];
46*91f16700Schasinglulu 	} else {
47*91f16700Schasinglulu 		mapping = SDEI_SHARED_MAPPING();
48*91f16700Schasinglulu 		idx = MAP_OFF(map, mapping);
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 		return &sdei_shared_event_table[idx];
51*91f16700Schasinglulu 	}
52*91f16700Schasinglulu }
53*91f16700Schasinglulu 
54*91f16700Schasinglulu /*
55*91f16700Schasinglulu  * Find event mapping for a given interrupt number: On success, returns pointer
56*91f16700Schasinglulu  * to the event mapping. On error, returns NULL.
57*91f16700Schasinglulu  */
58*91f16700Schasinglulu sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared)
59*91f16700Schasinglulu {
60*91f16700Schasinglulu 	const sdei_mapping_t *mapping;
61*91f16700Schasinglulu 	sdei_ev_map_t *map;
62*91f16700Schasinglulu 	unsigned int i;
63*91f16700Schasinglulu 
64*91f16700Schasinglulu 	/*
65*91f16700Schasinglulu 	 * Look for a match in private and shared mappings, as requested. This
66*91f16700Schasinglulu 	 * is a linear search. However, if the mappings are required to be
67*91f16700Schasinglulu 	 * sorted, for large maps, we could consider binary search.
68*91f16700Schasinglulu 	 */
69*91f16700Schasinglulu 	mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING();
70*91f16700Schasinglulu 	iterate_mapping(mapping, i, map) {
71*91f16700Schasinglulu 		if (map->intr == intr_num)
72*91f16700Schasinglulu 			return map;
73*91f16700Schasinglulu 	}
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	return NULL;
76*91f16700Schasinglulu }
77*91f16700Schasinglulu 
78*91f16700Schasinglulu /*
79*91f16700Schasinglulu  * Find event mapping for a given event number: On success returns pointer to
80*91f16700Schasinglulu  * the event mapping. On error, returns NULL.
81*91f16700Schasinglulu  */
82*91f16700Schasinglulu sdei_ev_map_t *find_event_map(int ev_num)
83*91f16700Schasinglulu {
84*91f16700Schasinglulu 	const sdei_mapping_t *mapping;
85*91f16700Schasinglulu 	sdei_ev_map_t *map;
86*91f16700Schasinglulu 	unsigned int i, j;
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	/*
89*91f16700Schasinglulu 	 * Iterate through mappings to find a match. This is a linear search.
90*91f16700Schasinglulu 	 * However, if the mappings are required to be sorted, for large maps,
91*91f16700Schasinglulu 	 * we could consider binary search.
92*91f16700Schasinglulu 	 */
93*91f16700Schasinglulu 	for_each_mapping_type(i, mapping) {
94*91f16700Schasinglulu 		iterate_mapping(mapping, j, map) {
95*91f16700Schasinglulu 			if (map->ev_num == ev_num)
96*91f16700Schasinglulu 				return map;
97*91f16700Schasinglulu 		}
98*91f16700Schasinglulu 	}
99*91f16700Schasinglulu 
100*91f16700Schasinglulu 	return NULL;
101*91f16700Schasinglulu }
102*91f16700Schasinglulu 
103*91f16700Schasinglulu /*
104*91f16700Schasinglulu  * Return the total number of currently registered SDEI events.
105*91f16700Schasinglulu  */
106*91f16700Schasinglulu int sdei_get_registered_event_count(void)
107*91f16700Schasinglulu {
108*91f16700Schasinglulu 	const sdei_mapping_t *mapping;
109*91f16700Schasinglulu 	sdei_ev_map_t *map;
110*91f16700Schasinglulu 	unsigned int i;
111*91f16700Schasinglulu 	unsigned int j;
112*91f16700Schasinglulu 	int count = 0;
113*91f16700Schasinglulu 
114*91f16700Schasinglulu 	/* Add up reg counts for each mapping. */
115*91f16700Schasinglulu 	for_each_mapping_type(i, mapping) {
116*91f16700Schasinglulu 		iterate_mapping(mapping, j, map) {
117*91f16700Schasinglulu 			count += map->reg_count;
118*91f16700Schasinglulu 		}
119*91f16700Schasinglulu 	}
120*91f16700Schasinglulu 
121*91f16700Schasinglulu 	return count;
122*91f16700Schasinglulu }
123