summaryrefslogtreecommitdiffstats
path: root/target-arm/helper-a64.c
diff options
context:
space:
mode:
authorPeter Maydell2014-09-30 12:02:06 +0200
committerPeter Maydell2014-09-30 12:02:06 +0200
commit29429c7244c73eefada3d0ec6dd30c5698782d08 (patch)
treeca318448a3a953a6897001a4e04cb97f566f1456 /target-arm/helper-a64.c
parentMerge remote-tracking branch 'remotes/spice/tags/pull-spice-20140929-1' into ... (diff)
parenttarget-arm: Add support for VIRQ and VFIQ (diff)
downloadqemu-29429c7244c73eefada3d0ec6dd30c5698782d08.tar.gz
qemu-29429c7244c73eefada3d0ec6dd30c5698782d08.tar.xz
qemu-29429c7244c73eefada3d0ec6dd30c5698782d08.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140929' into staging
target-arm: * more EL2/EL3 preparation work * don't handle c15_cpar changes via tb_flush() * fix some unused function warnings in ARM devices * build the GDB XML for 32 bit CPUs into qemu-*-aarch64 * implement guest breakpoint support # gpg: Signature made Mon 29 Sep 2014 19:25:37 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20140929: target-arm: Add support for VIRQ and VFIQ target-arm: Add IRQ and FIQ routing to EL2 and 3 target-arm: A64: Emulate the SMC insn target-arm: Add a Hypervisor Trap exception type target-arm: A64: Emulate the HVC insn target-arm: A64: Correct updates to FAR and ESR on exceptions target-arm: Don't take interrupts targeting lower ELs target-arm: Break out exception masking to a separate func target-arm: A64: Refactor aarch64_cpu_do_interrupt target-arm: Add SCR_EL3 target-arm: Add HCR_EL2 target-arm: Don't handle c15_cpar changes via tb_flush() hw/input/tsc210x.c: Delete unused array tsc2101_rates hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries target-arm: Implement handling of breakpoint firing target-arm: Implement setting guest breakpoints Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm/helper-a64.c')
-rw-r--r--target-arm/helper-a64.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64786..8228e29486 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -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,23 +466,27 @@ 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;
-
switch (cs->exception_index) {
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT:
+ env->cp15.far_el[new_el] = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
- env->cp15.far_el[1]);
- break;
+ env->cp15.far_el[new_el]);
+ /* fall through */
case EXCP_BKPT:
case EXCP_UDEF:
case EXCP_SWI:
+ case EXCP_HVC:
+ case EXCP_HYP_TRAP:
+ case EXCP_SMC:
+ env->cp15.esr_el[new_el] = env->exception.syndrome;
break;
case EXCP_IRQ:
+ case EXCP_VIRQ:
addr += 0x80;
break;
case EXCP_FIQ:
+ case EXCP_VFIQ:
addr += 0x100;
break;
default:
@@ -488,15 +494,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 +511,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;