diff mbox

[2/4] target-xtensa: fix tb invalidation for IBREAK and LOOP

Message ID 1334011700-32425-3-git-send-email-jcmvbkbc@gmail.com
State New
Headers show

Commit Message

Max Filippov April 9, 2012, 10:48 p.m. UTC
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 <jcmvbkbc@gmail.com>
---
 target-xtensa/op_helper.c |   29 ++++++++++++++++++-----------
 target-xtensa/translate.c |    2 ++
 2 files changed, 20 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index cdef0db..1b7e51f 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -99,6 +99,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;
@@ -358,8 +370,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;
     }
 }
@@ -367,11 +378,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);
     }
 }
 
@@ -692,8 +701,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);
@@ -702,9 +710,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;
 }
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e0ff72b..90c7f46 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -459,11 +459,13 @@  static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     gen_helper_wsr_lbeg(s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     gen_helper_wsr_lend(s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)