[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 1/8] target/xtensa: fix flush_window_regs
From: |
Max Filippov |
Subject: |
[Qemu-devel] [PULL 1/8] target/xtensa: fix flush_window_regs |
Date: |
Mon, 2 Apr 2018 10:13:47 -0700 |
flush_window_regs uses wrong stack frame to save overflow registers in
call8 and call12 frames, which results in wrong register values in
callers of a function that received a signal.
Reimplement flush_window_regs closely following window overflow
sequence.
Signed-off-by: Max Filippov <address@hidden>
---
linux-user/signal.c | 55 +++++++++++++++++++++++------------------------------
1 file changed, 24 insertions(+), 31 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 2ea3e0321f4d..33d5ced30c98 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -7094,52 +7094,45 @@ static abi_ulong get_sigframe(struct target_sigaction
*sa,
static int flush_window_regs(CPUXtensaState *env)
{
- const uint32_t nareg_mask = env->config->nareg - 1;
uint32_t wb = env->sregs[WINDOW_BASE];
- uint32_t ws = (xtensa_replicate_windowstart(env) >> (wb + 1)) &
- ((1 << env->config->nareg / 4) - 1);
- uint32_t d = ctz32(ws) + 1;
- uint32_t sp;
- abi_long ret = 0;
-
- wb += d;
- ws >>= d;
+ uint32_t ws = xtensa_replicate_windowstart(env) >> (wb + 1);
+ unsigned d = ctz32(ws) + 1;
+ unsigned i;
+ int ret = 0;
- xtensa_sync_phys_from_window(env);
- sp = env->phys_regs[(wb * 4 + 1) & nareg_mask];
+ for (i = d; i < env->config->nareg / 4; i += d) {
+ uint32_t ssp, osp;
+ unsigned j;
- while (ws && ret == 0) {
- int d;
- int i;
- int idx;
+ ws >>= d;
+ xtensa_rotate_window(env, d);
if (ws & 0x1) {
- ws >>= 1;
+ ssp = env->regs[5];
d = 1;
} else if (ws & 0x2) {
- ws >>= 2;
+ ssp = env->regs[9];
+ ret |= get_user_ual(osp, env->regs[1] - 12);
+ osp -= 32;
d = 2;
- for (i = 0; i < 4; ++i) {
- idx = (wb * 4 + 4 + i) & nareg_mask;
- ret |= put_user_ual(env->phys_regs[idx], sp + (i - 12) * 4);
- }
} else if (ws & 0x4) {
- ws >>= 3;
+ ssp = env->regs[13];
+ ret |= get_user_ual(osp, env->regs[1] - 12);
+ osp -= 48;
d = 3;
- for (i = 0; i < 8; ++i) {
- idx = (wb * 4 + 4 + i) & nareg_mask;
- ret |= put_user_ual(env->phys_regs[idx], sp + (i - 16) * 4);
- }
} else {
g_assert_not_reached();
}
- sp = env->phys_regs[((wb + d) * 4 + 1) & nareg_mask];
- for (i = 0; i < 4; ++i) {
- idx = (wb * 4 + i) & nareg_mask;
- ret |= put_user_ual(env->phys_regs[idx], sp + (i - 4) * 4);
+
+ for (j = 0; j < 4; ++j) {
+ ret |= put_user_ual(env->regs[j], ssp - 16 + j * 4);
+ }
+ for (j = 4; j < d * 4; ++j) {
+ ret |= put_user_ual(env->regs[j], osp - 16 + j * 4);
}
- wb += d;
}
+ xtensa_rotate_window(env, d);
+ g_assert(env->sregs[WINDOW_BASE] == wb);
return ret == 0;
}
--
2.11.0
- [Qemu-devel] [PULL 0/8] xtensa-specific and generic fixes for linux-user, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 1/8] target/xtensa: fix flush_window_regs,
Max Filippov <=
- [Qemu-devel] [PULL 2/8] target/xtensa: linux-user: rewind pc for restarted syscall, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 3/8] linux-user: call cpu_copy under clone_lock, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 4/8] linux-user: fix mq_getsetattr implementation, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 5/8] target/xtensa: linux-user: fix sysv IPC structures, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 6/8] linux-user: fix error propagation in clock_gettime, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 7/8] linux-user: implement clock_settime, Max Filippov, 2018/04/02
- [Qemu-devel] [PULL 8/8] target/xtensa: linux-user: fix fadvise64 call, Max Filippov, 2018/04/02
- Re: [Qemu-devel] [PULL 0/8] xtensa-specific and generic fixes for linux-user, Peter Maydell, 2018/04/03