From: Max Filippov <jcmvb...@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-sta...@nongnu.org Signed-off-by: Max Filippov <jcmvb...@gmail.com> (cherry picked from commit 1b3e71f8ee17ced609213d9b41758110f3c026e9) Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> --- target-xtensa/cpu.h | 6 ++++++ target-xtensa/op_helper.c | 6 ++++++ 2 files changed, 12 insertions(+) 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] |= -- 1.9.1