From 3d0be8a5c135dadcfbd68ed354007a8cece98849 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 10 Apr 2012 02:48:18 +0400 Subject: target-xtensa: fix tb invalidation for IBREAK and LOOP Instruction breakpoint/zero overhead loop handling code is built into TBs pointed to by IBREAKA/LEND SRs. When these or related SRs get changed TBs at virtual addresses corresponding to their old and their new values must be invalidated. Virtual address range is passed to the tb_invalidate_phys_page_range, which is incorrect in system emulation mode. To fix it use guest TLB/MMU to translate virtual address to physical address. However the guest may not have virtual-to-physical mapping at the moment of IBREAKA/LEND change, thus this fix is not 100% accurate. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/op_helper.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'target-xtensa/op_helper.c') diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index a6dd72da29..364dc19bc0 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -98,6 +98,18 @@ void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_id env = saved_env; } +static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) +{ + uint32_t paddr; + uint32_t page_size; + unsigned access; + int ret = xtensa_get_physical_addr(env, vaddr, 2, 0, + &paddr, &page_size, &access); + if (ret == 0) { + tb_invalidate_phys_addr(paddr); + } +} + void HELPER(exception)(uint32_t excp) { env->exception_index = excp; @@ -357,8 +369,7 @@ void HELPER(movsp)(uint32_t pc) void HELPER(wsr_lbeg)(uint32_t v) { if (env->sregs[LBEG] != v) { - tb_invalidate_phys_page_range( - env->sregs[LEND] - 1, env->sregs[LEND], 0); + tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1); env->sregs[LBEG] = v; } } @@ -366,11 +377,9 @@ void HELPER(wsr_lbeg)(uint32_t v) void HELPER(wsr_lend)(uint32_t v) { if (env->sregs[LEND] != v) { - tb_invalidate_phys_page_range( - env->sregs[LEND] - 1, env->sregs[LEND], 0); + tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1); env->sregs[LEND] = v; - tb_invalidate_phys_page_range( - env->sregs[LEND] - 1, env->sregs[LEND], 0); + tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1); } } @@ -691,8 +700,7 @@ void HELPER(wsr_ibreakenable)(uint32_t v) for (i = 0; i < env->config->nibreak; ++i) { if (change & (1 << i)) { - tb_invalidate_phys_page_range( - env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0); + tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]); } } env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1); @@ -701,9 +709,8 @@ void HELPER(wsr_ibreakenable)(uint32_t v) void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v) { if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) { - tb_invalidate_phys_page_range( - env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0); - tb_invalidate_phys_page_range(v, v + 1, 0); + tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]); + tb_invalidate_virtual_addr(env, v); } env->sregs[IBREAKA + i] = v; } -- cgit v1.2.1