1 /*
2 * Copyright (c) 2025-2026, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <arch.h>
8 #include <arch_features.h>
9 #include <arch_helpers.h>
10 #include <context.h>
11 #include <lib/el3_runtime/context_mgmt.h>
12 #include <lib/el3_runtime/cpu_data.h>
13 #include <lib/extensions/idte3.h>
14
idte3_init_percpu_once_regs(size_t security_state)15 void idte3_init_percpu_once_regs(size_t security_state)
16 {
17 assert(security_state < CPU_CONTEXT_NUM);
18
19 percpu_idregs_t * const reg =
20 &get_cpu_data(idregs[security_state]);
21
22 reg->id_aa64dfr0_el1 = read_id_aa64dfr0_el1();
23 reg->id_aa64dfr1_el1 = read_id_aa64dfr1_el1();
24
25 update_feat_spe_idreg_field(security_state);
26 update_feat_brbe_idreg_field(security_state);
27 update_feat_trbe_idreg_field(security_state);
28 update_feat_trf_idreg_field(security_state);
29 update_feat_mtpmu_idreg_field(security_state);
30 update_feat_sebep_idreg_field(security_state);
31 update_feat_sys_reg_trace_idreg_field(security_state);
32 update_feat_debugv8p9_idreg_field(security_state);
33 update_feat_ebep_idreg_field(security_state);
34 }
35
idte3_init_cached_idregs_per_world(size_t security_state)36 void idte3_init_cached_idregs_per_world(size_t security_state)
37 {
38
39 assert(security_state < CPU_CONTEXT_NUM);
40
41 per_world_context_t *per_world_ctx = &per_world_context[security_state];
42 perworld_idregs_t *reg = &(per_world_ctx->idregs);
43
44 reg->id_aa64pfr0_el1 = read_id_aa64pfr0_el1();
45 reg->id_aa64pfr1_el1 = read_id_aa64pfr1_el1();
46 reg->id_aa64pfr2_el1 = read_id_aa64pfr2_el1();
47 reg->id_aa64smfr0_el1 = read_id_aa64smfr0_el1();
48 reg->id_aa64isar0_el1 = read_id_aa64isar0_el1();
49 reg->id_aa64isar1_el1 = read_id_aa64isar1_el1();
50 reg->id_aa64isar2_el1 = read_id_aa64isar2_el1();
51 reg->id_aa64isar3_el1 = read_id_aa64isar3_el1();
52 reg->id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
53 reg->id_aa64mmfr1_el1 = read_id_aa64mmfr1_el1();
54 reg->id_aa64mmfr2_el1 = read_id_aa64mmfr2_el1();
55 reg->id_aa64mmfr3_el1 = read_id_aa64mmfr3_el1();
56 reg->id_aa64mmfr4_el1 = read_id_aa64mmfr4_el1();
57 reg->id_aa64dfr2_el1 = read_id_aa64dfr2_el1();
58
59 update_feat_pan_idreg_field(security_state);
60 update_feat_vhe_idreg_field(security_state);
61 update_feat_ttcnp_idreg_field(security_state);
62 update_feat_uao_idreg_field(security_state);
63 update_feat_pacqarma3_idreg_field(security_state);
64 update_feat_pauth_idreg_field(security_state);
65 update_feat_ttst_idreg_field(security_state);
66 update_feat_bti_idreg_field(security_state);
67 update_feat_mte2_idreg_field(security_state);
68 update_feat_ssbs_idreg_field(security_state);
69 update_feat_nmi_idreg_field(security_state);
70 update_feat_gcs_idreg_field(security_state);
71 update_feat_ebep_idreg_field(security_state);
72 update_feat_sel2_idreg_field(security_state);
73 update_feat_twed_idreg_field(security_state);
74 update_feat_fgt_idreg_field(security_state);
75 update_feat_ecv_idreg_field(security_state);
76 update_feat_rng_idreg_field(security_state);
77 update_feat_tcr2_idreg_field(security_state);
78 update_feat_s2poe_idreg_field(security_state);
79 update_feat_s1poe_idreg_field(security_state);
80 update_feat_s2pie_idreg_field(security_state);
81 update_feat_s1pie_idreg_field(security_state);
82 update_feat_amu_idreg_field(security_state);
83 update_feat_mpam_idreg_field(security_state);
84 update_feat_hcx_idreg_field(security_state);
85 update_feat_rng_trap_idreg_field(security_state);
86 update_feat_sb_idreg_field(security_state);
87 update_feat_csv2_2_idreg_field(security_state);
88 update_feat_sve_idreg_field(security_state);
89 update_feat_ras_idreg_field(security_state);
90 update_feat_dit_idreg_field(security_state);
91 update_feat_trbe_idreg_field(security_state);
92 update_feat_sme_idreg_field(security_state);
93 update_feat_fgt2_idreg_field(security_state);
94 update_feat_the_idreg_field(security_state);
95 update_feat_sctlr2_idreg_field(security_state);
96 update_feat_d128_idreg_field(security_state);
97 update_feat_ls64_accdata_idreg_field(security_state);
98 update_feat_fpmr_idreg_field(security_state);
99 update_feat_mops_idreg_field(security_state);
100 update_feat_fgwte3_idreg_field(security_state);
101 update_feat_cpa2_idreg_field(security_state);
102 update_feat_idte3_idreg_field(security_state);
103 update_feat_uinj_idreg_field(security_state);
104 update_feat_step2_idreg_field(security_state);
105 update_feat_hdbss_idreg_field(security_state);
106 update_feat_hacdbs_idreg_field(security_state);
107 }
108
handle_idreg_trap(uint64_t esr_el3,cpu_context_t * ctx,u_register_t flags)109 int handle_idreg_trap(uint64_t esr_el3, cpu_context_t *ctx, u_register_t flags)
110 {
111 uint32_t iss = (uint32_t) ESR_ELx_ISS(esr_el3);
112 uint8_t rt = (uint8_t) ISS_SYS64_RT(iss);
113 uint8_t op0 = (uint8_t) ISS_SYS64_OP0(iss);
114 uint8_t op1 = (uint8_t) ISS_SYS64_OP1(iss);
115 uint8_t CRn = (uint8_t) ISS_SYS64_CRN(iss);
116 uint8_t CRm = (uint8_t) ISS_SYS64_CRM(iss);
117 uint8_t op2 = (uint8_t) ISS_SYS64_OP2(iss);
118
119 u_register_t idreg = esr_el3 & ESR_EL3_SYSREG_MASK;
120
121 u_register_t value = 0ULL;
122 size_t security_state = GET_SECURITY_STATE(flags);
123 percpu_idregs_t *percpu_reg = &(get_cpu_data(idregs[security_state]));
124
125 per_world_context_t *per_world_ctx =
126 &per_world_context[get_cpu_context_index(security_state)];
127 perworld_idregs_t *perworld_reg = &(per_world_ctx->idregs);
128
129 switch (idreg) {
130 case ESR_EL3_IDREG_ID_AA64PFR0_EL1:
131 value = perworld_reg->id_aa64pfr0_el1;
132 break;
133 case ESR_EL3_IDREG_ID_AA64PFR1_EL1:
134 value = perworld_reg->id_aa64pfr1_el1;
135 break;
136 case ESR_EL3_IDREG_ID_AA64PFR2_EL1:
137 value = perworld_reg->id_aa64pfr2_el1;
138 break;
139 case ESR_EL3_IDREG_ID_AA64SMFR0_EL1:
140 value = perworld_reg->id_aa64smfr0_el1;
141 break;
142 case ESR_EL3_IDREG_ID_AA64ISAR0_EL1:
143 value = perworld_reg->id_aa64isar0_el1;
144 break;
145 case ESR_EL3_IDREG_ID_AA64ISAR1_EL1:
146 value = perworld_reg->id_aa64isar1_el1;
147 break;
148 case ESR_EL3_IDREG_ID_AA64ISAR2_EL1:
149 value = perworld_reg->id_aa64isar2_el1;
150 break;
151 case ESR_EL3_IDREG_ID_AA64ISAR3_EL1:
152 value = perworld_reg->id_aa64isar3_el1;
153 break;
154 case ESR_EL3_IDREG_ID_AA64MMFR0_EL1:
155 value = perworld_reg->id_aa64mmfr0_el1;
156 break;
157 case ESR_EL3_IDREG_ID_AA64MMFR1_EL1:
158 value = perworld_reg->id_aa64mmfr1_el1;
159 break;
160 case ESR_EL3_IDREG_ID_AA64MMFR2_EL1:
161 value = perworld_reg->id_aa64mmfr2_el1;
162 break;
163 case ESR_EL3_IDREG_ID_AA64MMFR3_EL1:
164 value = perworld_reg->id_aa64mmfr3_el1;
165 break;
166 case ESR_EL3_IDREG_ID_AA64MMFR4_EL1:
167 value = perworld_reg->id_aa64mmfr4_el1;
168 break;
169 case ESR_EL3_IDREG_ID_AA64DFR0_EL1:
170 value = percpu_reg->id_aa64dfr0_el1;
171 break;
172 case ESR_EL3_IDREG_ID_AA64DFR1_EL1:
173 value = percpu_reg->id_aa64dfr1_el1;
174 break;
175 case ESR_EL3_IDREG_ID_AA64ZFR0_EL1:
176 value = read_id_aa64zfr0_el1();
177 break;
178 case ESR_EL3_IDREG_ID_AA64FPFR0_EL1:
179 value = read_id_aa64fpfr0_el1();
180 break;
181 case ESR_EL3_IDREG_ID_AA64DFR2_EL1:
182 value = perworld_reg->id_aa64dfr2_el1;
183 break;
184 case ESR_EL3_IDREG_ID_AA64AFR0_EL1:
185 value = read_id_aa64afr0_el1();
186 break;
187 case ESR_EL3_IDREG_ID_AA64AFR1_EL1:
188 value = read_id_aa64afr1_el1();
189 break;
190 case ESR_EL3_IDREG_GMID_EL1:
191 value = read_gmid_el1();
192 break;
193 case ESR_EL3_IDREG_ID_PFR0_EL1:
194 value = read_id_pfr0_el1();
195 break;
196 case ESR_EL3_IDREG_ID_PFR1_EL1:
197 value = read_id_pfr1_el1();
198 break;
199 case ESR_EL3_IDREG_ID_DFR0_EL1:
200 value = read_id_dfr0_el1();
201 break;
202 case ESR_EL3_IDREG_ID_AFR0_EL1:
203 value = read_id_afr0_el1();
204 break;
205 case ESR_EL3_IDREG_ID_PFR2_EL1:
206 value = read_id_pfr2_el1();
207 break;
208 case ESR_EL3_IDREG_ID_DFR1_EL1:
209 value = read_id_dfr1_el1();
210 break;
211 case ESR_EL3_IDREG_ID_MMFR0_EL1:
212 value = read_id_mmfr0_el1();
213 break;
214 case ESR_EL3_IDREG_ID_MMFR1_EL1:
215 value = read_id_mmfr1_el1();
216 break;
217 case ESR_EL3_IDREG_ID_MMFR2_EL1:
218 value = read_id_mmfr2_el1();
219 break;
220 case ESR_EL3_IDREG_ID_MMFR3_EL1:
221 value = read_id_mmfr3_el1();
222 break;
223 case ESR_EL3_IDREG_ID_MMFR4_EL1:
224 value = read_id_mmfr4_el1();
225 break;
226 case ESR_EL3_IDREG_ID_MMFR5_EL1:
227 value = read_id_mmfr5_el1();
228 break;
229 case ESR_EL3_IDREG_ID_ISAR0_EL1:
230 value = read_id_isar0_el1();
231 break;
232 case ESR_EL3_IDREG_ID_ISAR1_EL1:
233 value = read_id_isar1_el1();
234 break;
235 case ESR_EL3_IDREG_ID_ISAR2_EL1:
236 value = read_id_isar2_el1();
237 break;
238 case ESR_EL3_IDREG_ID_ISAR3_EL1:
239 value = read_id_isar3_el1();
240 break;
241 case ESR_EL3_IDREG_ID_ISAR4_EL1:
242 value = read_id_isar4_el1();
243 break;
244 case ESR_EL3_IDREG_ID_ISAR5_EL1:
245 value = read_id_isar5_el1();
246 break;
247 case ESR_EL3_IDREG_ID_ISAR6_EL1:
248 value = read_id_isar6_el1();
249 break;
250 case ESR_EL3_IDREG_MVFR0_EL1:
251 value = read_mvfr0_el1();
252 break;
253 case ESR_EL3_IDREG_MVFR1_EL1:
254 value = read_mvfr1_el1();
255 break;
256 case ESR_EL3_IDREG_MVFR2_EL1:
257 value = read_mvfr2_el1();
258 break;
259
260 /*
261 * Any ID register access that falls within the Group 3
262 * ID space (op0 == 3, op1 == 0, CRn == 0, CRm == {2-7}, op2 == {0-7})
263 * but is not explicitly handled here will return 0.
264 * This covers newly introduced ID registers that were previously
265 * reserved or unknown.
266 *
267 * When new ID registers are added in future revisions of
268 * the architecture, they must be explicitly handled in this
269 * switch statement to return their actual value instead of
270 * Res0.
271 */
272 default:
273 WARN("Unknown ID register: S%u_%u_C%u_C%u_%u is trapped\n",
274 op0, op1, CRn, CRm, op2);
275 value = 0UL;
276 }
277
278 ctx->gpregs_ctx.ctx_regs[rt] = value;
279 return TRAP_RET_CONTINUE;
280 }
281
idte3_enable(cpu_context_t * context)282 void idte3_enable(cpu_context_t *context)
283 {
284 u_register_t reg;
285 el3_state_t *state;
286
287 state = get_el3state_ctx(context);
288
289 /*
290 * Setting the TID3 & TID5 bits enables trapping for
291 * group 3 ID registers and group 5
292 * ID register - GMID_EL1.
293 */
294
295 reg = read_ctx_reg(state, CTX_SCR_EL3);
296 reg |= (SCR_TID3_BIT | SCR_TID5_BIT);
297 write_ctx_reg(state, CTX_SCR_EL3, reg);
298 }
299