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
This commit is contained in:
parent
3f1beaca88
commit
7c1840b686
@ -9,60 +9,17 @@
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
/* Input 0 is IRQ and input 1 is FIQ. */
|
||||
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
switch (irq) {
|
||||
case ARM_PIC_CPU_IRQ:
|
||||
if (level) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
break;
|
||||
case ARM_PIC_CPU_FIQ:
|
||||
if (level) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_arm_pic_cpu_handler(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_PIC_CPU_IRQ:
|
||||
kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
|
||||
break;
|
||||
case ARM_PIC_CPU_FIQ:
|
||||
kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
|
||||
break;
|
||||
default:
|
||||
hw_error("kvm_arm_pic_cpu_handler: 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
|
||||
}
|
||||
|
||||
/* Backwards compatibility shim; this can disappear when all
|
||||
* board models have been updated to get IRQ and FIQ lines directly
|
||||
* from the ARMCPU object rather than by calling this function.
|
||||
*/
|
||||
qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
|
||||
}
|
||||
return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
|
||||
DeviceState *dev = DEVICE(cpu);
|
||||
qemu_irq *irqs = g_new(qemu_irq, 2);
|
||||
|
||||
irqs[0] = qdev_get_gpio_in(dev, ARM_CPU_IRQ);
|
||||
irqs[1] = qdev_get_gpio_in(dev, ARM_CPU_FIQ);
|
||||
return irqs;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -58,6 +58,9 @@
|
||||
/* ARM-specific interrupt pending bits. */
|
||||
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
|
||||
|
||||
/* Meanings of the ARMCPU object's two inbound GPIO lines */
|
||||
#define ARM_CPU_IRQ 0
|
||||
#define ARM_CPU_FIQ 1
|
||||
|
||||
typedef void ARMWriteCPFunc(void *opaque, int cp_info,
|
||||
int srcreg, int operand, uint32_t value);
|
||||
|
Loading…
Reference in New Issue
Block a user