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 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 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 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 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