Commit 1861c454 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
Message-id: 1378235544-22290-14-git-send-email-peter.maydell@linaro.org
parent 067d9831
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -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