Commit 9e729b57 authored by Edgar E. Iglesias's avatar Edgar E. Iglesias Committed by Peter Maydell
Browse files

target-arm: A64: Refactor aarch64_cpu_do_interrupt



Introduce new_el and new_mode in preparation for future patches
that add support for taking exceptions to and from EL2 and 3.
No functional change.

Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarEdgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-4-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 64e0e2de
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -500,6 +500,12 @@ void pmccntr_sync(CPUARMState *env);
#define PSTATE_MODE_EL1t 4
#define PSTATE_MODE_EL0t 0

/* Map EL and handler into a PSTATE_MODE.  */
static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
{
    return (el << 2) | handler;
}

/* Return the current PSTATE value. For the moment we don't support 32<->64 bit
 * interprocessing, so we don't attempt to sync with the cpsr state used by
 * the 32 bit decoder.
@@ -755,6 +761,7 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
}

void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);

/* Interface between CPU and Interrupt controller.  */
void armv7m_nvic_set_pending(void *opaque, int irq);
+13 −11
Original line number Diff line number Diff line
@@ -443,10 +443,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
{
    ARMCPU *cpu = ARM_CPU(cs);
    CPUARMState *env = &cpu->env;
    target_ulong addr = env->cp15.vbar_el[1];
    unsigned int new_el = arm_excp_target_el(cs, cs->exception_index);
    target_ulong addr = env->cp15.vbar_el[new_el];
    unsigned int new_mode = aarch64_pstate_mode(new_el, true);
    int i;

    if (arm_current_pl(env) == 0) {
    if (arm_current_pl(env) < new_el) {
        if (env->aarch64) {
            addr += 0x400;
        } else {
@@ -464,14 +466,14 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                      env->exception.syndrome);
    }

    env->cp15.esr_el[1] = env->exception.syndrome;
    env->cp15.far_el[1] = env->exception.vaddress;
    env->cp15.esr_el[new_el] = env->exception.syndrome;
    env->cp15.far_el[new_el] = env->exception.vaddress;

    switch (cs->exception_index) {
    case EXCP_PREFETCH_ABORT:
    case EXCP_DATA_ABORT:
        qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
                      env->cp15.far_el[1]);
                      env->cp15.far_el[new_el]);
        break;
    case EXCP_BKPT:
    case EXCP_UDEF:
@@ -488,15 +490,15 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
    }

    if (is_a64(env)) {
        env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env);
        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
        aarch64_save_sp(env, arm_current_pl(env));
        env->elr_el[1] = env->pc;
        env->elr_el[new_el] = env->pc;
    } else {
        env->banked_spsr[0] = cpsr_read(env);
        if (!env->thumb) {
            env->cp15.esr_el[1] |= 1 << 25;
            env->cp15.esr_el[new_el] |= 1 << 25;
        }
        env->elr_el[1] = env->regs[15];
        env->elr_el[new_el] = env->regs[15];

        for (i = 0; i < 15; i++) {
            env->xregs[i] = env->regs[i];
@@ -505,9 +507,9 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
        env->condexec_bits = 0;
    }

    pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
    pstate_write(env, PSTATE_DAIF | new_mode);
    env->aarch64 = 1;
    aarch64_restore_sp(env, 1);
    aarch64_restore_sp(env, new_el);

    env->pc = addr;
    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+13 −0
Original line number Diff line number Diff line
@@ -3704,6 +3704,11 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
    return 0;
}

unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
{
    return 1;
}

#else

/* Map CPU modes onto saved register banks.  */
@@ -3759,6 +3764,14 @@ void switch_mode(CPUARMState *env, int mode)
    env->spsr = env->banked_spsr[i];
}

/*
 * Determine the target EL for a given exception type.
 */
unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
{
    return 1;
}

static void v7m_push(CPUARMState *env, uint32_t val)
{
    CPUState *cs = CPU(arm_env_get_cpu(env));