aboutsummaryrefslogtreecommitdiff
path: root/linux-user/main.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2013-09-03 20:12:13 +0100
committerPeter Maydell <peter.maydell@linaro.org>2013-09-10 19:11:28 +0100
commit1861c4543ffa6224d0661036afaa7ec1cf30e8bb (patch)
tree4c1e09a89143406e6efea36881333f6acbf3cbdb /linux-user/main.c
parent067d983127da5c05a365230b12f2f557ec721c97 (diff)
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
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 5c2f7b26b4..b6e434a203 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -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