From 60136b485cc9e08717de9b6237be9fb8b4c254b9 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 5 Mar 2018 14:08:43 -0500 Subject: [PATCH] target/arm: Extend PAR format determination Now that do_ats_write() is entirely in control of whether to generate a 32-bit PAR or a 64-bit PAR, we can make it use the correct (complicated) condition for doing so. Backports commit 1313e2d7e2cd8b21741e0cf542eb09dfc4188f79 from qemu --- qemu/target/arm/helper.c | 34 +++++++++++++++++++++++++++++----- qemu/target/arm/internals.h | 2 +- qemu/target/arm/op_helper.c | 3 +-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 023d4698..5a092946 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -1925,16 +1925,41 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, int prot; bool ret; uint64_t par64; + bool format64 = false; MemTxAttrs attrs = {0}; ARMMMUFaultInfo fi = {0}; ARMCacheAttrs cacheattrs = {0}; ret = get_phys_addr(env, value, access_type, mmu_idx, &phys_addr, &attrs, &prot, &page_size, &fi, &cacheattrs); - /* TODO: this is not the correct condition to use to decide whether - * to report a PAR in 64-bit or 32-bit format. - */ - if (arm_s1_regime_using_lpae_format(env, mmu_idx)) { + + if (is_a64(env)) { + format64 = true; + } else if (arm_feature(env, ARM_FEATURE_LPAE)) { + /* + * ATS1Cxx: + * * TTBCR.EAE determines whether the result is returned using the + * 32-bit or the 64-bit PAR format + * * Instructions executed in Hyp mode always use the 64bit format + * + * ATS1S2NSOxx uses the 64bit format if any of the following is true: + * * The Non-secure TTBCR.EAE bit is set to 1 + * * The implementation includes EL2, and the value of HCR.VM is 1 + * + * ATS1Hx always uses the 64bit format (not supported yet). + */ + format64 = arm_s1_regime_using_lpae_format(env, mmu_idx); + + if (arm_feature(env, ARM_FEATURE_EL2)) { + if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) { + format64 |= env->cp15.hcr_el2 & HCR_VM; + } else { + format64 |= arm_current_el(env) == 2; + } + } + } + + if (format64) { /* Create a 64-bit PAR */ par64 = (1 << 11); /* LPAE bit always set */ if (!ret) { @@ -9045,7 +9070,6 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address, return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr, attrs, prot, page_size, fi, cacheattrs); - return ret; } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr, attrs, prot, page_size, fi); diff --git a/qemu/target/arm/internals.h b/qemu/target/arm/internals.h index aab68826..f720bee1 100644 --- a/qemu/target/arm/internals.h +++ b/qemu/target/arm/internals.h @@ -692,7 +692,7 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi) /* Do a page table walk and add page to TLB if possible */ bool arm_tlb_fill(CPUState *cpu, vaddr address, MMUAccessType access_type, int mmu_idx, - uint32_t *fsr, ARMMMUFaultInfo *fi); + ARMMMUFaultInfo *fi); /* Return true if the stage 1 translation regime is using LPAE format page * tables */ diff --git a/qemu/target/arm/op_helper.c b/qemu/target/arm/op_helper.c index cf6dfb9c..9c9fb44a 100644 --- a/qemu/target/arm/op_helper.c +++ b/qemu/target/arm/op_helper.c @@ -175,10 +175,9 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { bool ret; - uint32_t fsr = 0; ARMMMUFaultInfo fi = {0}; - ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fsr, &fi); + ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fi); if (unlikely(ret)) { ARMCPU *cpu = ARM_CPU(cs->uc, cs);