mirror of https://gitee.com/openkylin/qemu.git
linux-user/ppc: Use force_sig_fault
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. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220107213243.212806-20-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
b600705669
commit
d30e60e7b4
|
@ -76,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(;;) {
|
||||
|
@ -102,61 +101,10 @@ 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);
|
||||
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. "
|
||||
|
@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env)
|
|||
/* 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:
|
||||
|
@ -193,51 +140,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;
|
||||
|
@ -250,28 +196,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");
|
||||
|
@ -292,13 +229,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;
|
||||
|
@ -355,13 +285,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");
|
||||
|
@ -444,10 +367,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 */
|
||||
|
|
Loading…
Reference in New Issue