Skip to contentSkip to conversation

cpu_arm: Implement irqchip property for ARM CPU

PATCH New Pavel Fedin 1 participant 3 messages Aug 25, 2015

lore
Share & tools
lore
#0 lore raw

v2 cover cpu_arm: Implement irqchip property for ARM CPU

ARMv7m CPU needs a link to NVIC instance for processing interrupts. Similarly ARMv8 needs a link to GICv3 for its CPU interface.

This series builds upon existing mechanism for linking irqchip and CPU, bringing the code up to date and making it reusable. Another small step towards complete GICv3 implementation.

v1 => v2:
- Set link to nvic after it has been initialized
- Changed object type to "sys-bus-device" because GICv2 and GICv3 do not share common ancestors above that.

Pavel Fedin (2):
cpu_arm: Rename 'nvic' to 'irqchip'
armv7m: Use irqchip property instead of direct assignment

 hw/arm/armv7m.c     |  5 ++---
 target-arm/cpu.c    |  6 ++++++
 target-arm/cpu.h    |  5 ++++-
 target-arm/helper.c | 12 ++++++------
 4 files changed, 18 insertions(+), 10 deletions(-)
Signature · 1 line
1.9.5.msysgit.0
#1 lore raw

PATCH v2 1/2 cpu_arm: Rename 'nvic' to 'irqchip'

This name seems to be more appropriate because ARMv8 also needs a link with GICv3 for CPU interface to work

---
 hw/arm/armv7m.c     |  2 +-
 target-arm/cpu.h    |  5 ++++-
 target-arm/helper.c | 12 ++++++------
 3 files changed, 11 insertions(+), 8 deletions(-)
hw/arm/armv7m.c +1 -1
index c6eab6d..19742b7 100644
@@ -194,7 +194,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
 
     nvic = qdev_create(NULL, "armv7m_nvic");
     qdev_prop_set_uint32(nvic, "num-irq", num_irq);
-    env->nvic = nvic;
+    env->irqchip = nvic;
     qdev_init_nofail(nvic);
     sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
                        qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
target-arm/cpu.h +4 -1
index 2e680da..7021b87 100644
@@ -496,7 +496,10 @@ typedef struct CPUARMState {
         uint32_t *dracr;
     } pmsav7;
 
-    void *nvic;
+    /* Some CPUs have an internal link to their interrupt controller.
+     * Examples are ARMv7m (NVIC) and ARMv8 (GICv3 CPU interface)
+     */
+    DeviceState *irqchip;
     const struct arm_boot_info *boot_info;
 } CPUARMState;
 
target-arm/helper.c +6 -6
index 1568aa6..104ac4b 100644
@@ -4785,7 +4785,7 @@ static void do_v7m_exception_exit(CPUARMState *env)
 
     type = env->regs[15];
     if (env->v7m.exception != 0)
-        armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
+        armv7m_nvic_complete_irq(env->irqchip, env->v7m.exception);
 
     /* Switch to the target stack.  */
     switch_v7m_sp(env, (type & 4) != 0);
@@ -4841,18 +4841,18 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
        one we're raising.  */
     switch (cs->exception_index) {
     case EXCP_UDEF:
-        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
+        armv7m_nvic_set_pending(env->irqchip, ARMV7M_EXCP_USAGE);
         return;
     case EXCP_SWI:
         /* The PC already points to the next instruction.  */
-        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
+        armv7m_nvic_set_pending(env->irqchip, ARMV7M_EXCP_SVC);
         return;
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
         /* TODO: if we implemented the MPU registers, this is where we
          * should set the MMFAR, etc from exception.fsr and exception.vaddress.
          */
-        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
+        armv7m_nvic_set_pending(env->irqchip, ARMV7M_EXCP_MEM);
         return;
     case EXCP_BKPT:
         if (semihosting_enabled()) {
@@ -4865,10 +4865,10 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
                 return;
             }
         }
-        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
+        armv7m_nvic_set_pending(env->irqchip, ARMV7M_EXCP_DEBUG);
         return;
     case EXCP_IRQ:
-        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
+        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->irqchip);
         break;
     case EXCP_EXCEPTION_EXIT:
         do_v7m_exception_exit(env);
Signature · 1 line
1.9.5.msysgit.0
#2 lore raw

PATCH v2 2/2 armv7m: Use irqchip property instead of direct assignment

In reply to Pavel Fedin

Implement property instead of direct assignment of cpu->env.irqchip

---
 hw/arm/armv7m.c  | 5 ++---
 target-arm/cpu.c | 6 ++++++
 2 files changed, 8 insertions(+), 3 deletions(-)
hw/arm/armv7m.c +2 -3
index 19742b7..8905e97 100644
@@ -170,7 +170,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
                       const char *kernel_filename, const char *cpu_model)
 {
     ARMCPU *cpu;
-    CPUARMState *env;
     DeviceState *nvic;
     qemu_irq *pic = g_new(qemu_irq, num_irq);
     int image_size;
@@ -188,14 +187,14 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    env = &cpu->env;
 
     armv7m_bitband_init();
 
     nvic = qdev_create(NULL, "armv7m_nvic");
     qdev_prop_set_uint32(nvic, "num-irq", num_irq);
-    env->irqchip = nvic;
     qdev_init_nofail(nvic);
+    object_property_set_link(OBJECT(cpu), OBJECT(nvic), "irqchip",
+                             &error_abort);
     sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
                        qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
     for (i = 0; i < num_irq; i++) {
target-arm/cpu.c +6 -0
index cc6c6f3..b9f3010 100644
@@ -447,6 +447,12 @@ static void arm_cpu_initfn(Object *obj)
     static bool inited;
     uint32_t Aff1, Aff0;
 
+    object_property_add_link(obj, "irqchip",
+                             "sys-bus-device", (Object **)&cpu->env.irqchip,
+                             object_property_allow_set_link,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
+                             &error_abort);
+
     cs->env_ptr = &cpu->env;
     cpu_exec_init(cs, &error_abort);
     cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
Signature · 1 line
1.9.5.msysgit.0