]> 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)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 10 Nov 2014 14:59:13 +0000 (17:59 +0300)
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>
target-xtensa/cpu.h
target-xtensa/op_helper.c

index beb5486fc7499814af762de06eb224654a47c282..ac463f27fe098beebabdd9272113266723556d0a 100644 (file)
@@ -472,6 +472,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] |=