aboutsummaryrefslogtreecommitdiff
path: root/target-arm/cpu.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2013-08-20 14:54:28 +0100
committerPeter Maydell <peter.maydell@linaro.org>2013-08-20 14:54:28 +0100
commit7c1840b686e34ed138414ff0fe395a63f031387e (patch)
tree8ebb9da43ec797b4fa5683de41624dba9c7d8105 /target-arm/cpu.c
parent3f1beaca88bffa4828cc86beb89ff70474516d91 (diff)
target-arm: Make IRQ and FIQ gpio lines on the CPU object
Now that ARMCPU is a subclass of DeviceState, we can make the CPU's inbound IRQ and FIQ lines be simply gpio lines, which means we can remove the odd arm_pic shim. We retain the arm_pic_init_cpu() function as a backwards compatibility shim layer so we can convert the board models to get the IRQ and FIQ lines directly from the ARMCPU object one at a time. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1375977856-25046-2-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'target-arm/cpu.c')
-rw-r--r--target-arm/cpu.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 5a7566b8fc..6f56aa86db 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -23,7 +23,9 @@
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
#endif
+#include "hw/arm/arm.h"
#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -129,6 +131,55 @@ static void arm_cpu_reset(CPUState *s)
tb_flush(env);
}
+#ifndef CONFIG_USER_ONLY
+static void arm_cpu_set_irq(void *opaque, int irq, int level)
+{
+ ARMCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
+
+ switch (irq) {
+ case ARM_CPU_IRQ:
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+ break;
+ case ARM_CPU_FIQ:
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+ }
+ break;
+ default:
+ hw_error("arm_cpu_set_irq: Bad interrupt line %d\n", irq);
+ }
+}
+
+static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
+{
+#ifdef CONFIG_KVM
+ ARMCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
+ int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+
+ switch (irq) {
+ case ARM_CPU_IRQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+ break;
+ case ARM_CPU_FIQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+ break;
+ default:
+ hw_error("arm_cpu_kvm_set_irq: Bad interrupt line %d\n", irq);
+ }
+ kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
+ kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+#endif
+}
+#endif
+
static inline void set_feature(CPUARMState *env, int feature)
{
env->features |= 1ULL << feature;
@@ -145,6 +196,15 @@ static void arm_cpu_initfn(Object *obj)
cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
g_free, g_free);
+#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);
+ } else {
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
+ }
+#endif
+
if (tcg_enabled() && !inited) {
inited = true;
arm_translate_init();