From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37594) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZN1v1-0001nm-EG for qemu-devel@nongnu.org; Wed, 05 Aug 2015 12:52:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZN1uz-0004ty-V9 for qemu-devel@nongnu.org; Wed, 05 Aug 2015 12:51:55 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:55200) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZN1uz-0004tp-NL for qemu-devel@nongnu.org; Wed, 05 Aug 2015 12:51:53 -0400 From: Christopher Covington Date: Wed, 5 Aug 2015 12:51:14 -0400 Message-Id: <1438793483-12721-6-git-send-email-cov@codeaurora.org> In-Reply-To: <1438793483-12721-1-git-send-email-cov@codeaurora.org> References: <1438793483-12721-1-git-send-email-cov@codeaurora.org> Subject: [Qemu-devel] [RFC 05/14] Fixed TLB invalidate ops. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Christopher Covington 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 --- 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