xref: /rk3399_ARM-atf/lib/extensions/idte/idte3.c (revision e7e231d39c68083e870cdaaa89ecc4e5045fdd64)
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(uint8_t rt,uint64_t idreg,cpu_context_t * ctx,u_register_t flags)109 int handle_idreg_trap(uint8_t rt, uint64_t idreg, cpu_context_t *ctx, u_register_t flags)
110 {
111 	u_register_t value = 0ULL;
112 	size_t security_state = GET_SECURITY_STATE(flags);
113 	percpu_idregs_t *percpu_reg = &(get_cpu_data(idregs[security_state]));
114 
115 	per_world_context_t *per_world_ctx =
116 		&per_world_context[get_cpu_context_index(security_state)];
117 	perworld_idregs_t *perworld_reg = &(per_world_ctx->idregs);
118 
119 	switch (idreg) {
120 	case ISS_SYSREG_OPCODE_ID_AA64PFR0_EL1:
121 		value = perworld_reg->id_aa64pfr0_el1;
122 		break;
123 	case ISS_SYSREG_OPCODE_ID_AA64PFR1_EL1:
124 		value = perworld_reg->id_aa64pfr1_el1;
125 		break;
126 	case ISS_SYSREG_OPCODE_ID_AA64PFR2_EL1:
127 		value = perworld_reg->id_aa64pfr2_el1;
128 		break;
129 	case ISS_SYSREG_OPCODE_ID_AA64SMFR0_EL1:
130 		value = perworld_reg->id_aa64smfr0_el1;
131 		break;
132 	case ISS_SYSREG_OPCODE_ID_AA64ISAR0_EL1:
133 		value = perworld_reg->id_aa64isar0_el1;
134 		break;
135 	case ISS_SYSREG_OPCODE_ID_AA64ISAR1_EL1:
136 		value = perworld_reg->id_aa64isar1_el1;
137 		break;
138 	case ISS_SYSREG_OPCODE_ID_AA64ISAR2_EL1:
139 		value = perworld_reg->id_aa64isar2_el1;
140 		break;
141 	case ISS_SYSREG_OPCODE_ID_AA64ISAR3_EL1:
142 		value = perworld_reg->id_aa64isar3_el1;
143 		break;
144 	case ISS_SYSREG_OPCODE_ID_AA64MMFR0_EL1:
145 		value = perworld_reg->id_aa64mmfr0_el1;
146 		break;
147 	case ISS_SYSREG_OPCODE_ID_AA64MMFR1_EL1:
148 		value = perworld_reg->id_aa64mmfr1_el1;
149 		break;
150 	case ISS_SYSREG_OPCODE_ID_AA64MMFR2_EL1:
151 		value = perworld_reg->id_aa64mmfr2_el1;
152 		break;
153 	case ISS_SYSREG_OPCODE_ID_AA64MMFR3_EL1:
154 		value = perworld_reg->id_aa64mmfr3_el1;
155 		break;
156 	case ISS_SYSREG_OPCODE_ID_AA64MMFR4_EL1:
157 		value = perworld_reg->id_aa64mmfr4_el1;
158 		break;
159 	case ISS_SYSREG_OPCODE_ID_AA64DFR0_EL1:
160 		value = percpu_reg->id_aa64dfr0_el1;
161 		break;
162 	case ISS_SYSREG_OPCODE_ID_AA64DFR1_EL1:
163 		value = percpu_reg->id_aa64dfr1_el1;
164 		break;
165 	case ISS_SYSREG_OPCODE_ID_AA64ZFR0_EL1:
166 		value = read_id_aa64zfr0_el1();
167 		break;
168 	case ISS_SYSREG_OPCODE_ID_AA64FPFR0_EL1:
169 		value = read_id_aa64fpfr0_el1();
170 		break;
171 	case ISS_SYSREG_OPCODE_ID_AA64DFR2_EL1:
172 		value = perworld_reg->id_aa64dfr2_el1;
173 		break;
174 	case ISS_SYSREG_OPCODE_ID_AA64AFR0_EL1:
175 		value = read_id_aa64afr0_el1();
176 		break;
177 	case ISS_SYSREG_OPCODE_ID_AA64AFR1_EL1:
178 		value = read_id_aa64afr1_el1();
179 		break;
180 	case ISS_SYSREG_OPCODE_GMID_EL1:
181 		value = read_gmid_el1();
182 		break;
183 	case ISS_SYSREG_OPCODE_ID_PFR0_EL1:
184 		value = read_id_pfr0_el1();
185 		break;
186 	case ISS_SYSREG_OPCODE_ID_PFR1_EL1:
187 		value = read_id_pfr1_el1();
188 		break;
189 	case ISS_SYSREG_OPCODE_ID_DFR0_EL1:
190 		value = read_id_dfr0_el1();
191 		break;
192 	case ISS_SYSREG_OPCODE_ID_AFR0_EL1:
193 		value = read_id_afr0_el1();
194 		break;
195 	case ISS_SYSREG_OPCODE_ID_PFR2_EL1:
196 		value = read_id_pfr2_el1();
197 		break;
198 	case ISS_SYSREG_OPCODE_ID_DFR1_EL1:
199 		value = read_id_dfr1_el1();
200 		break;
201 	case ISS_SYSREG_OPCODE_ID_MMFR0_EL1:
202 		value = read_id_mmfr0_el1();
203 		break;
204 	case ISS_SYSREG_OPCODE_ID_MMFR1_EL1:
205 		value = read_id_mmfr1_el1();
206 		break;
207 	case ISS_SYSREG_OPCODE_ID_MMFR2_EL1:
208 		value = read_id_mmfr2_el1();
209 		break;
210 	case ISS_SYSREG_OPCODE_ID_MMFR3_EL1:
211 		value = read_id_mmfr3_el1();
212 		break;
213 	case ISS_SYSREG_OPCODE_ID_MMFR4_EL1:
214 		value = read_id_mmfr4_el1();
215 		break;
216 	case ISS_SYSREG_OPCODE_ID_MMFR5_EL1:
217 		value = read_id_mmfr5_el1();
218 		break;
219 	case ISS_SYSREG_OPCODE_ID_ISAR0_EL1:
220 		value = read_id_isar0_el1();
221 		break;
222 	case ISS_SYSREG_OPCODE_ID_ISAR1_EL1:
223 		value = read_id_isar1_el1();
224 		break;
225 	case ISS_SYSREG_OPCODE_ID_ISAR2_EL1:
226 		value = read_id_isar2_el1();
227 		break;
228 	case ISS_SYSREG_OPCODE_ID_ISAR3_EL1:
229 		value = read_id_isar3_el1();
230 		break;
231 	case ISS_SYSREG_OPCODE_ID_ISAR4_EL1:
232 		value = read_id_isar4_el1();
233 		break;
234 	case ISS_SYSREG_OPCODE_ID_ISAR5_EL1:
235 		value = read_id_isar5_el1();
236 		break;
237 	case ISS_SYSREG_OPCODE_ID_ISAR6_EL1:
238 		value = read_id_isar6_el1();
239 		break;
240 	case ISS_SYSREG_OPCODE_MVFR0_EL1:
241 		value = read_mvfr0_el1();
242 		break;
243 	case ISS_SYSREG_OPCODE_MVFR1_EL1:
244 		value = read_mvfr1_el1();
245 		break;
246 	case ISS_SYSREG_OPCODE_MVFR2_EL1:
247 		value = read_mvfr2_el1();
248 		break;
249 
250 	/*
251 	 * Any ID register access that falls within the Group 3
252 	 * ID space (op0 == 3, op1 == 0, CRn == 0, CRm == {2-7}, op2 == {0-7})
253 	 * but is not explicitly handled here will return 0.
254 	 * This covers newly introduced ID registers that were previously
255 	 * reserved or unknown.
256 	 *
257 	 * When new ID registers are added in future revisions of
258 	 * the architecture, they must be explicitly handled in this
259 	 * switch statement to return their actual value instead of
260 	 * Res0.
261 	 */
262 	default:
263 		WARN("Unknown ID register: S%u_%u_C%u_C%u_%u is trapped\n",
264 		     (uint8_t) EXTRACT(ISS_SYS64_OP0, idreg),
265 		     (uint8_t) EXTRACT(ISS_SYS64_OP1, idreg),
266 		     (uint8_t) EXTRACT(ISS_SYS64_CRN, idreg),
267 		     (uint8_t) EXTRACT(ISS_SYS64_CRM, idreg),
268 		     (uint8_t) EXTRACT(ISS_SYS64_OP2, idreg));
269 		value = 0UL;
270 	}
271 
272 	ctx->gpregs_ctx.ctx_regs[rt] = value;
273 	return TRAP_RET_CONTINUE;
274 }
275 
idte3_enable(cpu_context_t * context)276 void idte3_enable(cpu_context_t *context)
277 {
278 	u_register_t reg;
279 	el3_state_t *state;
280 
281 	state = get_el3state_ctx(context);
282 
283 	/*
284 	 * Setting the TID3 & TID5 bits enables trapping for
285 	 * group 3 ID registers and group 5
286 	 * ID register - GMID_EL1.
287 	 */
288 
289 	reg = read_ctx_reg(state, CTX_SCR_EL3);
290 	reg |= (SCR_TID3_BIT | SCR_TID5_BIT);
291 	write_ctx_reg(state, CTX_SCR_EL3, reg);
292 }
293