Prior to this patch, QEMU was only invalidating the TLB for the local processor on a TLB flush event, causing unstable behavoir in smp mode. This patch corrects the behavoir so that all TLBs are invalidated across the system.
Written by Derek Hower. Signed-off-by: Christopher Covington <c...@codeaurora.org> --- target-arm/helper.c | 68 +++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index be564b2..ff3c8f7 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -355,23 +355,35 @@ void init_cpreg_list(ARMCPU *cpu) g_list_free(keys); } -static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void arm_tlb_flush(CPUARMState *env, int flush_global) { - ARMCPU *cpu = arm_env_get_cpu(env); + CPUState* cpu; + CPU_FOREACH(cpu) { + tlb_flush(cpu, flush_global); + } +} +static void arm_tlb_flush_page(CPUARMState *env, target_ulong addr) +{ + CPUState* cpu; + CPU_FOREACH(cpu) { + tlb_flush_page(cpu, addr); + } +} + +static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +{ raw_write(env, ri, value); - tlb_flush(CPU(cpu), 1); /* Flush TLB as domain not tracked in TLB */ + arm_tlb_flush(env, 1);/* Flush TLB as domain not tracked in TLB */ } static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - ARMCPU *cpu = arm_env_get_cpu(env); - if (raw_read(env, ri) != value) { /* Unlike real hardware the qemu TLB uses virtual addresses, * not modified virtual addresses, so this causes a TLB flush. */ - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); raw_write(env, ri, value); } } @@ -379,15 +391,13 @@ static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - ARMCPU *cpu = arm_env_get_cpu(env); - if (raw_read(env, ri) != value && !arm_feature(env, ARM_FEATURE_MPU) && !extended_addresses_enabled(env)) { /* For VMSA (when not using the LPAE long descriptor page table * format) this register includes the ASID, so do a TLB flush. * For PMSA it is purely a process ID and no action is needed. */ - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); } raw_write(env, ri, value); } @@ -396,36 +406,28 @@ static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate all (TLBIALL) */ - ARMCPU *cpu = arm_env_get_cpu(env); - - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); } static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ - ARMCPU *cpu = arm_env_get_cpu(env); - - tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK); + arm_tlb_flush(env, value & TARGET_PAGE_MASK); } static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate by ASID (TLBIASID) */ - ARMCPU *cpu = arm_env_get_cpu(env); - - tlb_flush(CPU(cpu), value == 0); + arm_tlb_flush(env, value == 0); } static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ - ARMCPU *cpu = arm_env_get_cpu(env); - - tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK); + arm_tlb_flush_page(env, value & TARGET_PAGE_MASK); } /* IS variants of TLB operations must affect all cores */ @@ -1792,13 +1794,11 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - ARMCPU *cpu = arm_env_get_cpu(env); - if (arm_feature(env, ARM_FEATURE_LPAE)) { /* With LPAE the TTBCR could result in a change of ASID * via the TTBCR.A1 bit, so do a TLB flush. */ - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); } vmsa_ttbcr_raw_write(env, ri, value); } @@ -1818,11 +1818,10 @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri) static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - ARMCPU *cpu = arm_env_get_cpu(env); TCR *tcr = raw_ptr(env, ri); /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */ - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); tcr->raw_tcr = value; } @@ -1833,9 +1832,7 @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, * must flush the TLB. */ if (cpreg_field_is_64bit(ri)) { - ARMCPU *cpu = arm_env_get_cpu(env); - - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); } raw_write(env, ri, value); } @@ -2166,29 +2163,26 @@ static void tlbi_aa64_va_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate by VA (AArch64 version) */ - ARMCPU *cpu = arm_env_get_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); - tlb_flush_page(CPU(cpu), pageaddr); + arm_tlb_flush_page(env, pageaddr); } static void tlbi_aa64_vaa_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate by VA, all ASIDs (AArch64 version) */ - ARMCPU *cpu = arm_env_get_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); - tlb_flush_page(CPU(cpu), pageaddr); + arm_tlb_flush_page(env, pageaddr); } static void tlbi_aa64_asid_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Invalidate by ASID (AArch64 version) */ - ARMCPU *cpu = arm_env_get_cpu(env); int asid = extract64(value, 48, 16); - tlb_flush(CPU(cpu), asid == 0); + arm_tlb_flush(env, asid == 0); } static void tlbi_aa64_va_is_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -2271,8 +2265,6 @@ static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val) static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - ARMCPU *cpu = arm_env_get_cpu(env); - if (raw_read(env, ri) == value) { /* Skip the TLB flush if nothing actually changed; Linux likes * to do a lot of pointless SCTLR writes. @@ -2283,7 +2275,7 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, raw_write(env, ri, value); /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ - tlb_flush(CPU(cpu), 1); + arm_tlb_flush(env, 1); } static const ARMCPRegInfo v8_cp_reginfo[] = { -- Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project