This just allows read/write of three feature bits. ASID is still ignored. Any writes to TTBR0_EL0 and TTBR1_EL0, including changing the ASID, will still cause a complete flush of the TLB.
Signed-off-by: Jim MacArthur <[email protected]> --- target/arm/cpu-features.h | 7 +++++++ target/arm/helper.c | 28 ++++++++++++++++++++++------ target/arm/internals.h | 5 +++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 579fa8f8f4..d56bda9ce0 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -346,6 +346,8 @@ FIELD(ID_AA64MMFR3, SDERR, 52, 4) FIELD(ID_AA64MMFR3, ADERR, 56, 4) FIELD(ID_AA64MMFR3, SPEC_FPACC, 60, 4) +FIELD(ID_AA64MMFR4, ASID2, 8, 4) + FIELD(ID_AA64DFR0, DEBUGVER, 0, 4) FIELD(ID_AA64DFR0, TRACEVER, 4, 4) FIELD(ID_AA64DFR0, PMUVER, 8, 4) @@ -1369,6 +1371,11 @@ static inline bool isar_feature_aa64_aie(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64MMFR3, AIE) != 0; } +static inline bool isar_feature_aa64_asid2(const ARMISARegisters *id) +{ + return FIELD_EX64_IDREG(id, ID_AA64MMFR4, ASID2) != 0; +} + static inline bool isar_feature_aa64_mec(const ARMISARegisters *id) { return FIELD_EX64_IDREG(id, ID_AA64MMFR3, MEC) != 0; diff --git a/target/arm/helper.c b/target/arm/helper.c index c20334fa65..534c783be9 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -428,6 +428,15 @@ int alle1_tlbmask(CPUARMState *env) ARMMMUIdxBit_Stage2_S); } +int alle2_tlbmask(void) +{ + return (ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E20_2_GCS | + ARMMMUIdxBit_E20_0 | + ARMMMUIdxBit_E20_0_GCS); +} + static const ARMCPRegInfo cp_reginfo[] = { /* * Define the secure and non-secure FCSE identifier CP registers @@ -2802,12 +2811,7 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, */ if (extract64(raw_read(env, ri) ^ value, 48, 16) && (arm_hcr_el2_eff(env) & HCR_E2H)) { - uint16_t mask = ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E20_2_GCS | - ARMMMUIdxBit_E20_0 | - ARMMMUIdxBit_E20_0_GCS; - tlb_flush_by_mmuidx(env_cpu(env), mask); + tlb_flush_by_mmuidx(env_cpu(env), alle2_tlbmask()); } raw_write(env, ri, value); } @@ -6102,6 +6106,12 @@ static void tcr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri, if (cpu_isar_feature(aa64_aie, cpu)) { valid_mask |= TCR2_AIE; } + if (cpu_isar_feature(aa64_asid2, cpu)) { + valid_mask |= TCR2_FNG1 | TCR2_FNG0 | TCR2_A2; + if (((raw_read(env, ri) ^ value) & TCR2_A2) != 0) { + tlb_flush_by_mmuidx(CPU(cpu), alle1_tlbmask(env)); + } + } value &= valid_mask; raw_write(env, ri, value); } @@ -6121,6 +6131,12 @@ static void tcr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, if (cpu_isar_feature(aa64_mec, cpu)) { valid_mask |= TCR2_AMEC0 | TCR2_AMEC1; } + if (cpu_isar_feature(aa64_asid2, cpu)) { + valid_mask |= TCR2_FNG1 | TCR2_FNG0 | TCR2_A2; + if (((raw_read(env, ri) ^ value) & TCR2_A2) != 0) { + tlb_flush_by_mmuidx(CPU(cpu), alle2_tlbmask()); + } + } value &= valid_mask; raw_write(env, ri, value); } diff --git a/target/arm/internals.h b/target/arm/internals.h index 75677945af..db9cc1fd73 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1891,6 +1891,11 @@ uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx); * all EL1" scope; this covers stage 1 and stage 2. */ int alle1_tlbmask(CPUARMState *env); +/* + * Return mask of ARMMMUIdxBit values corresponding to an "invalidate + * all EL2&0" scope. + */ +int alle2_tlbmask(void); /* Set the float_status behaviour to match the Arm defaults */ void arm_set_default_fp_behaviours(float_status *s); -- 2.43.0
