aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorRobbin Ehn <rehn@rivosinc.com>2024-01-12 21:57:22 +0100
committerRichard Henderson <richard.henderson@linaro.org>2024-01-23 13:22:46 +1000
commit6d913158b5023ac948b8fd649d77fc86e28072f6 (patch)
treecd0d174892f52f2ca23af83d7bf7838edfb30f48 /linux-user
parent8f8419d3255365121e3596307b98ab3d6dcbdf1a (diff)
downloadqemu-6d913158b5023ac948b8fd649d77fc86e28072f6.zip
qemu-6d913158b5023ac948b8fd649d77fc86e28072f6.tar.gz
qemu-6d913158b5023ac948b8fd649d77fc86e28072f6.tar.bz2
linux-user: Fixed cpu restore with pc 0 on SIGBUS
Commit f4e1168198 (linux-user: Split out host_sig{segv,bus}_handler) introduced a bug, when returning from host_sigbus_handler the PC is never set. Thus cpu_loop_exit_restore is called with a zero PC and we immediate get a SIGSEGV. Signed-off-by: Robbin Ehn <rehn@rivosinc.com> Fixes: f4e1168198 ("linux-user: Split out host_sig{segv,bus}_handler") Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> Message-Id: <33f27425878fb529b9e39ef22c303f6e0d90525f.camel@rivosinc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/signal.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b35d1e5..c9527ad 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -925,7 +925,7 @@ static void host_sigsegv_handler(CPUState *cpu, siginfo_t *info,
cpu_loop_exit_sigsegv(cpu, guest_addr, access_type, maperr, pc);
}
-static void host_sigbus_handler(CPUState *cpu, siginfo_t *info,
+static uintptr_t host_sigbus_handler(CPUState *cpu, siginfo_t *info,
host_sigcontext *uc)
{
uintptr_t pc = host_signal_pc(uc);
@@ -947,6 +947,7 @@ static void host_sigbus_handler(CPUState *cpu, siginfo_t *info,
sigprocmask(SIG_SETMASK, host_signal_mask(uc), NULL);
cpu_loop_exit_sigbus(cpu, guest_addr, access_type, pc);
}
+ return pc;
}
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
@@ -974,7 +975,7 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
host_sigsegv_handler(cpu, info, uc);
return;
case SIGBUS:
- host_sigbus_handler(cpu, info, uc);
+ pc = host_sigbus_handler(cpu, info, uc);
sync_sig = true;
break;
case SIGILL: