blob: 9c7f74aadee712edf6855d05658a75dd4b610c1d [file] [log] [blame]
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +01001/*
Igor Podgainõib142ede2024-10-07 15:16:29 +02002 * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +00008
9#include <lib/utils.h>
10
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010011#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 */
Igor Podgainõib142ede2024-10-07 15:16:29 +020022sdei_entry_t *get_event_entry(const sdei_ev_map_t *map)
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010023{
24 const sdei_mapping_t *mapping;
25 sdei_entry_t *cpu_priv_base;
Jeenu Viswambharanba6e5ca2018-08-02 10:14:12 +010026 unsigned int base_idx;
27 long int idx;
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010028
Igor Podgainõib142ede2024-10-07 15:16:29 +020029 if ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U) {
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010030 /*
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 */
Jeenu Viswambharanba6e5ca2018-08-02 10:14:12 +010038 base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps);
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010039 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/*
Igor Podgainõib142ede2024-10-07 15:16:29 +020055 * 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 */
Mark Dykes9dde2cc2025-04-28 16:46:47 -050064sdei_entry_t *get_event_entry_target_pe(long int mapsub, unsigned int nm,
65uint64_t target_pe)
Igor Podgainõib142ede2024-10-07 15:16:29 +020066{
67 sdei_entry_t *cpu_priv_base;
Mark Dykes9dde2cc2025-04-28 16:46:47 -050068 unsigned int base_idx = 0U;
Igor Podgainõib142ede2024-10-07 15:16:29 +020069 long int idx;
Mark Dykes9dde2cc2025-04-28 16:46:47 -050070 int target_pos;
Igor Podgainõib142ede2024-10-07 15:16:29 +020071
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 */
Mark Dykes9dde2cc2025-04-28 16:46:47 -050079 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;
Igor Podgainõib142ede2024-10-07 15:16:29 +020086 base_idx *= nm;
Mark Dykes9dde2cc2025-04-28 16:46:47 -050087
Igor Podgainõib142ede2024-10-07 15:16:29 +020088 cpu_priv_base = &sdei_private_event_table[base_idx];
Mark Dykes9dde2cc2025-04-28 16:46:47 -050089
Igor Podgainõib142ede2024-10-07 15:16:29 +020090 /*
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/*
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +010098 * Find event mapping for a given interrupt number: On success, returns pointer
99 * to the event mapping. On error, returns NULL.
100 */
Jeenu Viswambharanba6e5ca2018-08-02 10:14:12 +0100101sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared)
Jeenu Viswambharanb7cb1332017-10-16 08:43:14 +0100102{
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 */
125sdei_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}
John Powelle6381f92022-05-12 12:49:55 -0500145
146/*
147 * Return the total number of currently registered SDEI events.
148 */
149int 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}