diff mbox

[58/88] target-xtensa: add missing window check for entry

Message ID 1420738472-23267-59-git-send-email-mdroth@linux.vnet.ibm.com
State New
Headers show

Commit Message

Michael Roth Jan. 8, 2015, 5:34 p.m. UTC
From: Max Filippov <jcmvbkbc@gmail.com>

Entry opcode needs to check if moving to new register frame would cause
register window overflow. Entry used in function prologue never
overflows because preceding windowed call* opcode writes return address
to the target register window frame, causing overflow exceptions at the
point of call. But when a sequence of entry opcodes is used for register
window spilling there may not be a call or other opcode that would cause
window check between entries and they would not raise overflow exception
themselves resulting in data corruption.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
(cherry picked from commit 1b3e71f8ee17ced609213d9b41758110f3c026e9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 target-xtensa/cpu.h       | 6 ++++++
 target-xtensa/op_helper.c | 6 ++++++
 2 files changed, 12 insertions(+)
diff mbox

Patch

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index d797d26..6e4e2b2 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -471,6 +471,12 @@  static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
         env->itlb[wi] + ei;
 }
 
+static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
+{
+    return env->sregs[WINDOW_START] |
+        (env->sregs[WINDOW_START] << env->config->nareg / 4);
+}
+
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _ring0
 #define MMU_MODE1_SUFFIX _ring1
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index dae1386..872e5a8 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -235,6 +235,12 @@  void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
                 pc, env->sregs[PS]);
         HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
     } else {
+        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
+            (env->sregs[WINDOW_BASE] + 1);
+
+        if (windowstart & ((1 << callinc) - 1)) {
+            HELPER(window_check)(env, pc, callinc);
+        }
         env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
         rotate_window(env, callinc);
         env->sregs[WINDOW_START] |=