hexagon_modify_ssr() flushed the softtlb on any change to SSR.EX, UM, GM, or ASID, but only ASID affects translation. EX/UM/GM just pick the mode, which is already captured in mmu_idx.
EX toggles on every exception entry/rte, so the flush created a feedback loop where a TLB miss wiped the softtlb and guaranteed the next accesses missed too. Rename hex_mmu_mode_change() to hex_mmu_asid_change() to match what now triggers it, and narrow it to this thread's mmu indices: the ASID lives in the thread's private SSR, so other CPUs are unaffected. Reviewed-by: Pierrick Bouvier <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/hex_mmu.h | 2 +- target/hexagon/cpu_helper.c | 17 +++-------------- target/hexagon/hex_mmu.c | 7 ++++--- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/target/hexagon/hex_mmu.h b/target/hexagon/hex_mmu.h index 0c49404448c..9b6ea5b967b 100644 --- a/target/hexagon/hex_mmu.h +++ b/target/hexagon/hex_mmu.h @@ -17,7 +17,7 @@ extern void hex_tlb_invalidate_asid(CPUHexagonState *env, uint32_t asid); extern uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA); extern void hex_mmu_on(CPUHexagonState *env); extern void hex_mmu_off(CPUHexagonState *env); -extern void hex_mmu_mode_change(CPUHexagonState *env); +extern void hex_mmu_asid_change(CPUHexagonState *env); extern bool hex_tlb_find_match(CPUHexagonState *env, uint32_t VA, MMUAccessType access_type, hwaddr *PA, int *prot, uint64_t *size, int32_t *excp, int mmu_idx); diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c index 919fcbc7c97..baffe6bbaa9 100644 --- a/target/hexagon/cpu_helper.c +++ b/target/hexagon/cpu_helper.c @@ -192,27 +192,17 @@ unsigned hexagon_hvx_select_context(CPUHexagonState *env, uint32_t ssr) void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old) { - bool old_EX, old_UM, old_GM, old_IE; - bool new_EX, new_UM, new_GM, new_IE; + bool old_EX, old_IE; + bool new_EX, new_IE; uint8_t old_asid, new_asid; g_assert(bql_locked()); old_EX = GET_SSR_FIELD(SSR_EX, old); - old_UM = GET_SSR_FIELD(SSR_UM, old); - old_GM = GET_SSR_FIELD(SSR_GM, old); old_IE = GET_SSR_FIELD(SSR_IE, old); new_EX = GET_SSR_FIELD(SSR_EX, new); - new_UM = GET_SSR_FIELD(SSR_UM, new); - new_GM = GET_SSR_FIELD(SSR_GM, new); new_IE = GET_SSR_FIELD(SSR_IE, new); - if ((old_EX != new_EX) || - (old_UM != new_UM) || - (old_GM != new_GM)) { - hex_mmu_mode_change(env); - } - bool xa_changed = GET_SSR_FIELD(SSR_XA, new) != GET_SSR_FIELD(SSR_XA, old); bool xe_changed = GET_SSR_FIELD(SSR_XE, new) != GET_SSR_FIELD(SSR_XE, old); @@ -228,8 +218,7 @@ void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old) old_asid = GET_SSR_FIELD(SSR_ASID, old); new_asid = GET_SSR_FIELD(SSR_ASID, new); if (new_asid != old_asid) { - CPUState *cs = env_cpu(env); - tlb_flush(cs); + hex_mmu_asid_change(env); } /* See if the interrupts have been enabled or we have exited EX mode */ diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c index 2e0e4ab705b..9a0e29ae212 100644 --- a/target/hexagon/hex_mmu.c +++ b/target/hexagon/hex_mmu.c @@ -73,11 +73,12 @@ void hex_mmu_off(CPUHexagonState *env) tlb_flush(cs); } -void hex_mmu_mode_change(CPUHexagonState *env) +void hex_mmu_asid_change(CPUHexagonState *env) { - qemu_log_mask(CPU_LOG_MMU, "Hexagon mode change!\n"); CPUState *cs = env_cpu(env); - tlb_flush(cs); + + qemu_log_mask(CPU_LOG_MMU, "Hexagon ASID change!\n"); + tlb_flush_by_mmuidx(cs, MMU_IDX_ALL); } bool hex_tlb_find_match(CPUHexagonState *env, uint32_t VA, -- 2.34.1
