target/arm: Implement FEAT_ATS1A

Implement FEAT_ATS1A and enable for -cpu max.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20250830054128.448363-13-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson
2025-08-30 15:40:16 +10:00
committed by Peter Maydell
parent 171a302a04
commit 2b5daf79c3
5 changed files with 52 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ the following architecture extensions:
- FEAT_AFP (Alternate floating-point behavior)
- FEAT_Armv9_Crypto (Armv9 Cryptographic Extension)
- FEAT_ASID16 (16 bit ASID)
- FEAT_ATS1A (Address Translation operations that ignore stage 1 permissions)
- FEAT_BBM at level 2 (Translation table break-before-make levels)
- FEAT_BF16 (AArch64 BFloat16 instructions)
- FEAT_BTI (Branch Target Identification)

View File

@@ -854,6 +854,7 @@ typedef enum FGTBit {
DO_BIT(HFGITR, DVPRCTX),
DO_BIT(HFGITR, CPPRCTX),
DO_BIT(HFGITR, DCCVAC),
DO_BIT(HFGITR, ATS1E1A),
} FGTBit;
#undef DO_BIT

View File

@@ -619,6 +619,11 @@ static inline bool isar_feature_aa64_lut(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64ISAR2, LUT);
}
static inline bool isar_feature_aa64_ats1a(const ARMISARegisters *id)
{
return FIELD_EX64_IDREG(id, ID_AA64ISAR2, ATS1A);
}
static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically. */

View File

@@ -488,6 +488,47 @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
.writefn = ats_write },
};
static void ats_s1e1a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
ARMMMUIdx mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1;
ARMSecuritySpace ss = arm_security_space_below_el3(env);
env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
}
static void ats_s1e2a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
ARMMMUIdx mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2;
ARMSecuritySpace ss = arm_security_space_below_el3(env);
env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
}
static void ats_s1e3a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
env->cp15.par_el[1] = do_ats_write(env, value, 0, ARMMMUIdx_E3,
arm_security_space(env));
}
static const ARMCPRegInfo ats1a_reginfo[] = {
{ .name = "AT_S1E1A", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 2,
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
.fgt = FGT_ATS1E1A,
.accessfn = at_s1e01_access, .writefn = ats_s1e1a },
{ .name = "AT_S1E2A", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 9, .opc2 = 2,
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
.accessfn = at_s1e2_access, .writefn = ats_s1e2a },
{ .name = "AT_S1E3A", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 6, .crn = 7, .crm = 9, .opc2 = 2,
.access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
.writefn = ats_s1e3a },
};
void define_at_insn_regs(ARMCPU *cpu)
{
CPUARMState *env = &cpu->env;
@@ -509,4 +550,7 @@ void define_at_insn_regs(ARMCPU *cpu)
if (cpu_isar_feature(aa32_ats1e1, cpu)) {
define_arm_cp_regs(cpu, ats1cp_reginfo);
}
if (cpu_isar_feature(aa64_ats1a, cpu)) {
define_arm_cp_regs(cpu, ats1a_reginfo);
}
}

View File

@@ -1179,6 +1179,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2); /* FEAT_WFxT */
t = FIELD_DP64(t, ID_AA64ISAR2, CSSC, 1); /* FEAT_CSSC */
t = FIELD_DP64(t, ID_AA64ISAR2, ATS1A, 1); /* FEAT_ATS1A */
SET_IDREG(isar, ID_AA64ISAR2, t);
t = GET_IDREG(isar, ID_AA64PFR0);