[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 20/25] linux-user/ppc: Use force_sig_fault
From: |
Richard Henderson |
Subject: |
[PATCH v3 20/25] linux-user/ppc: Use force_sig_fault |
Date: |
Sat, 18 Sep 2021 18:57:13 -0700 |
Use the new function instead of setting up a target_siginfo_t
and calling queue_signal. Fill in the missing PC for SIGTRAP.
The fault address for POWERPC_EXCP_ISI is nip exactly, not nip - 4.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/ppc/cpu_loop.c | 146 +++++++++-----------------------------
1 file changed, 34 insertions(+), 112 deletions(-)
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index fa91ea0eed..2b006317ba 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -21,6 +21,8 @@
#include "qemu-common.h"
#include "qemu.h"
#include "cpu_loop-common.h"
+#include "signal-common.h"
+
static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
{
@@ -74,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
void cpu_loop(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
- int trapnr;
+ int trapnr, si_signo, si_code;
target_ulong ret;
for(;;) {
@@ -100,61 +101,14 @@ void cpu_loop(CPUPPCState *env)
"Aborting\n");
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
- /* XXX: check this. Seems bugged */
- switch (env->error_code & 0xFF000000) {
- case 0x40000000:
- case 0x42000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- case 0x04000000:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLADR;
- break;
- case 0x08000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_ACCERR;
- break;
- default:
- /* Let's send a regular segfault... */
- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
- env->error_code);
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- }
- info._sifields._sigfault._addr = env->spr[SPR_DAR];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+ env->spr[SPR_DAR]);
break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */
- /* XXX: check this */
- switch (env->error_code & 0xFF000000) {
- case 0x40000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- case 0x10000000:
- case 0x08000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_ACCERR;
- break;
- default:
- /* Let's send a regular segfault... */
- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
- env->error_code);
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- }
- info._sifields._sigfault._addr = env->nip - 4;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+ env->spr[SPR_DAR]);
break;
case POWERPC_EXCP_EXTERNAL: /* External input */
cpu_abort(cs, "External interrupt while in user mode. "
@@ -162,35 +116,30 @@ void cpu_loop(CPUPPCState *env)
break;
case POWERPC_EXCP_ALIGN: /* Alignment exception */
/* XXX: check this */
- info.si_signo = TARGET_SIGBUS;
- info.si_errno = 0;
- info.si_code = TARGET_BUS_ADRALN;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, env->nip);
break;
case POWERPC_EXCP_PROGRAM: /* Program exception */
case POWERPC_EXCP_HV_EMU: /* HV emulation */
/* XXX: check this */
switch (env->error_code & ~0xF) {
case POWERPC_EXCP_FP:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
+ si_signo = TARGET_SIGFPE;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_FP_OX:
- info.si_code = TARGET_FPE_FLTOVF;
+ si_code = TARGET_FPE_FLTOVF;
break;
case POWERPC_EXCP_FP_UX:
- info.si_code = TARGET_FPE_FLTUND;
+ si_code = TARGET_FPE_FLTUND;
break;
case POWERPC_EXCP_FP_ZX:
case POWERPC_EXCP_FP_VXZDZ:
- info.si_code = TARGET_FPE_FLTDIV;
+ si_code = TARGET_FPE_FLTDIV;
break;
case POWERPC_EXCP_FP_XX:
- info.si_code = TARGET_FPE_FLTRES;
+ si_code = TARGET_FPE_FLTRES;
break;
case POWERPC_EXCP_FP_VXSOFT:
- info.si_code = TARGET_FPE_FLTINV;
+ si_code = TARGET_FPE_FLTINV;
break;
case POWERPC_EXCP_FP_VXSNAN:
case POWERPC_EXCP_FP_VXISI:
@@ -199,51 +148,50 @@ void cpu_loop(CPUPPCState *env)
case POWERPC_EXCP_FP_VXVC:
case POWERPC_EXCP_FP_VXSQRT:
case POWERPC_EXCP_FP_VXCVI:
- info.si_code = TARGET_FPE_FLTSUB;
+ si_code = TARGET_FPE_FLTSUB;
break;
default:
EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
env->error_code);
+ si_code = 0;
break;
}
break;
case POWERPC_EXCP_INVAL:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_INVAL_INVAL:
- info.si_code = TARGET_ILL_ILLOPC;
+ si_code = TARGET_ILL_ILLOPC;
break;
case POWERPC_EXCP_INVAL_LSWX:
- info.si_code = TARGET_ILL_ILLOPN;
+ si_code = TARGET_ILL_ILLOPN;
break;
case POWERPC_EXCP_INVAL_SPR:
- info.si_code = TARGET_ILL_PRVREG;
+ si_code = TARGET_ILL_PRVREG;
break;
case POWERPC_EXCP_INVAL_FP:
- info.si_code = TARGET_ILL_COPROC;
+ si_code = TARGET_ILL_COPROC;
break;
default:
EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
env->error_code & 0xF);
- info.si_code = TARGET_ILL_ILLADR;
+ si_code = TARGET_ILL_ILLADR;
break;
}
break;
case POWERPC_EXCP_PRIV:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_PRIV_OPC:
- info.si_code = TARGET_ILL_PRVOPC;
+ si_code = TARGET_ILL_PRVOPC;
break;
case POWERPC_EXCP_PRIV_REG:
- info.si_code = TARGET_ILL_PRVREG;
+ si_code = TARGET_ILL_PRVREG;
break;
default:
EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
env->error_code & 0xF);
- info.si_code = TARGET_ILL_PRVOPC;
+ si_code = TARGET_ILL_PRVOPC;
break;
}
break;
@@ -256,28 +204,19 @@ void cpu_loop(CPUPPCState *env)
env->error_code);
break;
}
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(si_signo, si_code, env->nip);
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip);
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_DECR: /* Decrementer exception */
cpu_abort(cs, "Decrementer interrupt while in user mode. "
"Aborting\n");
@@ -298,13 +237,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Instruction TLB exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
break;
@@ -361,13 +293,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Hypervisor instruction segment exception "
"while in user mode. Aborting\n");
break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n");
@@ -450,10 +375,7 @@ void cpu_loop(CPUPPCState *env)
env->gpr[3] = ret;
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
--
2.25.1
- [PATCH v3 13/25] linux-user/microblaze: Use force_sig_fault, (continued)
- [PATCH v3 13/25] linux-user/microblaze: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 16/25] linux-user/mips: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 22/25] linux-user/s390x: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 24/25] linux-user/sparc: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 15/25] linux-user/mips: Improve do_break, Richard Henderson, 2021/09/18
- [PATCH v3 19/25] linux-user/openrisc: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 18/25] target/mips: Extract trap code into env->error_code, Richard Henderson, 2021/09/18
- [PATCH v3 23/25] linux-user/sh4: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 21/25] linux-user/riscv: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 25/25] linux-user/xtensa: Use force_sig_fault, Richard Henderson, 2021/09/18
- [PATCH v3 20/25] linux-user/ppc: Use force_sig_fault,
Richard Henderson <=
- Re: [PATCH v3 00/25] linux-user: Clean up siginfo_t handling, Richard Henderson, 2021/09/19