linux-user: Add cpu loop for AArch64

Add the main linux-user cpu loop for AArch64. Since AArch64
has a different system call interface, doesn't need to worry
about FPA emulation and may in the future keep the prefetch/data
abort information in different system registers, it's simplest
just to use a completely separate loop from the 32 bit ARM
target, rather than peppering it with ifdefs.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1378235544-22290-14-git-send-email-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2013-09-03 20:12:13 +01:00
parent 067d983127
commit 1861c4543f
1 changed files with 82 additions and 0 deletions

View File

@ -449,6 +449,9 @@ void cpu_loop(CPUX86State *env)
__r; \
})
#ifdef TARGET_ABI32
/* Commpage handling -- there is no commpage for AArch64 */
/*
* See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
* Input:
@ -582,6 +585,7 @@ do_kernel_trap(CPUARMState *env)
return 0;
}
#endif
static int do_strex(CPUARMState *env)
{
@ -661,6 +665,7 @@ done:
return segv;
}
#ifdef TARGET_ABI32
void cpu_loop(CPUARMState *env)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
@ -873,6 +878,83 @@ void cpu_loop(CPUARMState *env)
}
}
#else
/* AArch64 main loop */
void cpu_loop(CPUARMState *env)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
int trapnr, sig;
target_siginfo_t info;
uint32_t addr;
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_arm_exec(env);
cpu_exec_end(cs);
switch (trapnr) {
case EXCP_SWI:
env->xregs[0] = do_syscall(env,
env->xregs[8],
env->xregs[0],
env->xregs[1],
env->xregs[2],
env->xregs[3],
env->xregs[4],
env->xregs[5],
0, 0);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_UDEF:
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
break;
case EXCP_PREFETCH_ABORT:
addr = env->cp15.c6_insn;
goto do_segv;
case EXCP_DATA_ABORT:
addr = env->cp15.c6_data;
do_segv:
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = addr;
queue_signal(env, info.si_signo, &info);
break;
case EXCP_DEBUG:
case EXCP_BKPT:
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig) {
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP_STREX:
if (do_strex(env)) {
addr = env->cp15.c6_data;
goto do_segv;
}
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
cpu_dump_state(cs, stderr, fprintf, 0);
abort();
}
process_pending_signals(env);
}
}
#endif /* ndef TARGET_ABI32 */
#endif
#ifdef TARGET_UNICORE32