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>
This commit is contained in:
Robbin Ehn 2024-01-12 21:57:22 +01:00 committed by Richard Henderson
parent 8f8419d325
commit 6d913158b5

View File

@ -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); 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) host_sigcontext *uc)
{ {
uintptr_t pc = host_signal_pc(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); sigprocmask(SIG_SETMASK, host_signal_mask(uc), NULL);
cpu_loop_exit_sigbus(cpu, guest_addr, access_type, pc); 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) 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); host_sigsegv_handler(cpu, info, uc);
return; return;
case SIGBUS: case SIGBUS:
host_sigbus_handler(cpu, info, uc); pc = host_sigbus_handler(cpu, info, uc);
sync_sig = true; sync_sig = true;
break; break;
case SIGILL: case SIGILL: