]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target-xtensa: add missing window check for entry
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 7 Nov 2014 18:11:07 +0000 (21:11 +0300)
committerMichael Roth <mdroth@linux.vnet.ibm.com>
Wed, 7 Jan 2015 20:31:19 +0000 (14:31 -0600)
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
target-xtensa/op_helper.c

index d797d2649a63c80e1e4bb699d35ba258be07b7f2..6e4e2b2ed981386902e3645af4cad7ab00976b84 100644 (file)
@@ -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
index dae13866efb16a9ef64fd2ea743bcf46bf2a1b4d..872e5a823b88b9e34aa849045f5637acf0755281 100644 (file)
@@ -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] |=