aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2017-02-06 21:30:13 -0800
committerRichard Henderson <rth@twiddle.net>2017-02-14 08:14:58 +1100
commita0adc417a0b22e9b33a529133e04822753067f33 (patch)
tree084c668443a3dc56b89ec07b50e46066fcf8834a /linux-user
parentab9023385576389e68b937d744de8ef8a0a4dc7a (diff)
downloadqemu-a0adc417a0b22e9b33a529133e04822753067f33.zip
qemu-a0adc417a0b22e9b33a529133e04822753067f33.tar.gz
qemu-a0adc417a0b22e9b33a529133e04822753067f33.tar.bz2
linux-user: Fix openrisc cpu_loop
We need to handle EXCP_DEBUG and EXCP_INTERRUPT. We need to send signals to the guest using queue_signal. Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c95
1 files changed, 41 insertions, 54 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index e588f58..001f71c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2574,52 +2574,17 @@ kuser_fail:
void cpu_loop(CPUOpenRISCState *env)
{
CPUState *cs = CPU(openrisc_env_get_cpu(env));
- int trapnr, gdbsig;
+ int trapnr;
abi_long ret;
+ target_siginfo_t info;
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
- gdbsig = 0;
switch (trapnr) {
- case EXCP_RESET:
- qemu_log_mask(CPU_LOG_INT, "\nReset request, exit, pc is %#x\n", env->pc);
- exit(EXIT_FAILURE);
- break;
- case EXCP_BUSERR:
- qemu_log_mask(CPU_LOG_INT, "\nBus error, exit, pc is %#x\n", env->pc);
- gdbsig = TARGET_SIGBUS;
- break;
- case EXCP_DPF:
- case EXCP_IPF:
- cpu_dump_state(cs, stderr, fprintf, 0);
- gdbsig = TARGET_SIGSEGV;
- break;
- case EXCP_TICK:
- qemu_log_mask(CPU_LOG_INT, "\nTick time interrupt pc is %#x\n", env->pc);
- break;
- case EXCP_ALIGN:
- qemu_log_mask(CPU_LOG_INT, "\nAlignment pc is %#x\n", env->pc);
- gdbsig = TARGET_SIGBUS;
- break;
- case EXCP_ILLEGAL:
- qemu_log_mask(CPU_LOG_INT, "\nIllegal instructionpc is %#x\n", env->pc);
- gdbsig = TARGET_SIGILL;
- break;
- case EXCP_INT:
- qemu_log_mask(CPU_LOG_INT, "\nExternal interruptpc is %#x\n", env->pc);
- break;
- case EXCP_DTLBMISS:
- case EXCP_ITLBMISS:
- qemu_log_mask(CPU_LOG_INT, "\nTLB miss\n");
- break;
- case EXCP_RANGE:
- qemu_log_mask(CPU_LOG_INT, "\nRange\n");
- gdbsig = TARGET_SIGSEGV;
- break;
case EXCP_SYSCALL:
env->pc += 4; /* 0xc00; */
ret = do_syscall(env,
@@ -2636,32 +2601,54 @@ void cpu_loop(CPUOpenRISCState *env)
env->gpr[11] = ret;
}
break;
+ case EXCP_DPF:
+ case EXCP_IPF:
+ case EXCP_RANGE:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_ALIGN:
+ info.si_signo = TARGET_SIGBUS;
+ info.si_errno = 0;
+ info.si_code = TARGET_BUS_ADRALN;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_ILLEGAL:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPC;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
case EXCP_FPE:
- qemu_log_mask(CPU_LOG_INT, "\nFloating point error\n");
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
- case EXCP_TRAP:
- qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
- gdbsig = TARGET_SIGTRAP;
+ case EXCP_INTERRUPT:
+ /* We processed the pending cpu work above. */
break;
- case EXCP_NR:
- qemu_log_mask(CPU_LOG_INT, "\nNR\n");
+ case EXCP_DEBUG:
+ trapnr = gdb_handlesig(cs, TARGET_SIGTRAP);
+ if (trapnr) {
+ info.si_signo = trapnr;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ }
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
- EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
- trapnr);
- gdbsig = TARGET_SIGILL;
- break;
- }
- if (gdbsig) {
- gdb_handlesig(cs, gdbsig);
- if (gdbsig != TARGET_SIGTRAP) {
- exit(EXIT_FAILURE);
- }
+ g_assert_not_reached();
}
-
process_pending_signals(env);
}
}