diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2014-09-30 11:02:06 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2014-09-30 11:02:06 +0100 |
| commit | 29429c7244c73eefada3d0ec6dd30c5698782d08 (patch) | |
| tree | ca318448a3a953a6897001a4e04cb97f566f1456 /target-arm/cpu.c | |
| parent | 70d3a7a7b8340d9f671c5aec4c6dd174fee2ef8e (diff) | |
| parent | 136e67e9b50b61fb03fedcea5c4fbe74cf44fdcc (diff) | |
| download | focaccia-qemu-29429c7244c73eefada3d0ec6dd30c5698782d08.tar.gz focaccia-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/cpu.c')
| -rw-r--r-- | target-arm/cpu.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 407f977742..8ab6d9532e 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -41,7 +41,9 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) static bool arm_cpu_has_work(CPUState *cs) { return cs->interrupt_request & - (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB); + (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD + | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ + | CPU_INTERRUPT_EXITTB); } static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque) @@ -173,11 +175,6 @@ static void arm_cpu_reset(CPUState *s) set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.standard_fp_status); tlb_flush(s, 1); - /* Reset is a state change for some CPUARMState fields which we - * bake assumptions about into translated code, so we need to - * tb_flush(). - */ - tb_flush(env); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { @@ -185,18 +182,17 @@ static void arm_cpu_reset(CPUState *s) } #endif + hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); } bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { CPUClass *cc = CPU_GET_CLASS(cs); - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; bool ret = false; if (interrupt_request & CPU_INTERRUPT_FIQ - && !(env->daif & PSTATE_F)) { + && arm_excp_unmasked(cs, EXCP_FIQ)) { cs->exception_index = EXCP_FIQ; cc->do_interrupt(cs); ret = true; @@ -211,12 +207,23 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) We avoid this by disabling interrupts when pc contains a magic address. */ if (interrupt_request & CPU_INTERRUPT_HARD - && !(env->daif & PSTATE_I) - && (!IS_M(env) || env->regs[15] < 0xfffffff0)) { + && arm_excp_unmasked(cs, EXCP_IRQ)) { cs->exception_index = EXCP_IRQ; cc->do_interrupt(cs); ret = true; } + if (interrupt_request & CPU_INTERRUPT_VIRQ + && arm_excp_unmasked(cs, EXCP_VIRQ)) { + cs->exception_index = EXCP_VIRQ; + cc->do_interrupt(cs); + ret = true; + } + if (interrupt_request & CPU_INTERRUPT_VFIQ + && arm_excp_unmasked(cs, EXCP_VFIQ)) { + cs->exception_index = EXCP_VFIQ; + cc->do_interrupt(cs); + ret = true; + } return ret; } @@ -225,21 +232,29 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) static void arm_cpu_set_irq(void *opaque, int irq, int level) { ARMCPU *cpu = opaque; + CPUARMState *env = &cpu->env; CPUState *cs = CPU(cpu); + static const int mask[] = { + [ARM_CPU_IRQ] = CPU_INTERRUPT_HARD, + [ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ, + [ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ, + [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ + }; switch (irq) { - case ARM_CPU_IRQ: - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + case ARM_CPU_VIRQ: + case ARM_CPU_VFIQ: + if (!arm_feature(env, ARM_FEATURE_EL2)) { + hw_error("%s: Virtual interrupt line %d with no EL2 support\n", + __func__, irq); } - break; + /* fall through */ + case ARM_CPU_IRQ: case ARM_CPU_FIQ: if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_FIQ); + cpu_interrupt(cs, mask[irq]); } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ); + cpu_reset_interrupt(cs, mask[irq]); } break; default: @@ -289,9 +304,12 @@ static void arm_cpu_initfn(Object *obj) #ifndef CONFIG_USER_ONLY /* Our inbound IRQ and FIQ lines */ if (kvm_enabled()) { - qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2); + /* VIRQ and VFIQ are unused with KVM but we add them to maintain + * the same interface as non-KVM CPUs. + */ + qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4); } else { - qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2); + qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4); } cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, |