7452f5d
From 7700d225b357c66a6949834f069ea3949890119b Mon Sep 17 00:00:00 2001
7452f5d
From: Christoffer Dall <christoffer.dall@linaro.org>
7452f5d
Date: Mon, 18 Nov 2013 19:26:33 -0800
7452f5d
Subject: [PATCH] arm_gic: Add GICC_APRn state to the GICState
7452f5d
7452f5d
The GICC_APRn registers are not currently supported by the ARM GIC v2.0
7452f5d
emulation.  This patch adds the missing state.
7452f5d
7452f5d
Note that we also change the number of APRs to use a define GIC_NR_APRS
7452f5d
based on the maximum number of preemption levels.  This patch also adds
7452f5d
RAZ/WI accessors for the four registers on the emulated CPU interface.
7452f5d
7452f5d
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7452f5d
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
7452f5d
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7452f5d
(cherry picked from commit a9d477c4e3d614409a48d12f34624c2dd9f1ec2d)
7452f5d
---
7452f5d
 hw/intc/arm_gic.c                |  5 +++++
7452f5d
 hw/intc/arm_gic_common.c         |  5 +++--
7452f5d
 include/hw/intc/arm_gic_common.h | 19 +++++++++++++++++++
7452f5d
 3 files changed, 27 insertions(+), 2 deletions(-)
7452f5d
7452f5d
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
7452f5d
index d31892d..9ca3f03 100644
7452f5d
--- a/hw/intc/arm_gic.c
7452f5d
+++ b/hw/intc/arm_gic.c
7452f5d
@@ -678,6 +678,8 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
7452f5d
         return s->current_pending[cpu];
7452f5d
     case 0x1c: /* Aliased Binary Point */
7452f5d
         return s->abpr[cpu];
7452f5d
+    case 0xd0: case 0xd4: case 0xd8: case 0xdc:
7452f5d
+        return s->apr[(offset - 0xd0) / 4][cpu];
7452f5d
     default:
7452f5d
         qemu_log_mask(LOG_GUEST_ERROR,
7452f5d
                       "gic_cpu_read: Bad offset %x\n", (int)offset);
7452f5d
@@ -705,6 +707,9 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
7452f5d
             s->abpr[cpu] = (value & 0x7);
7452f5d
         }
7452f5d
         break;
7452f5d
+    case 0xd0: case 0xd4: case 0xd8: case 0xdc:
7452f5d
+        qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n");
7452f5d
+        break;
7452f5d
     default:
7452f5d
         qemu_log_mask(LOG_GUEST_ERROR,
7452f5d
                       "gic_cpu_write: Bad offset %x\n", (int)offset);
7452f5d
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
7452f5d
index 7966985..ec6286b 100644
7452f5d
--- a/hw/intc/arm_gic_common.c
7452f5d
+++ b/hw/intc/arm_gic_common.c
7452f5d
@@ -58,8 +58,8 @@ static const VMStateDescription vmstate_gic_irq_state = {
7452f5d
 
7452f5d
 static const VMStateDescription vmstate_gic = {
7452f5d
     .name = "arm_gic",
7452f5d
-    .version_id = 6,
7452f5d
-    .minimum_version_id = 6,
7452f5d
+    .version_id = 7,
7452f5d
+    .minimum_version_id = 7,
7452f5d
     .pre_save = gic_pre_save,
7452f5d
     .post_load = gic_post_load,
7452f5d
     .fields = (VMStateField[]) {
7452f5d
@@ -78,6 +78,7 @@ static const VMStateDescription vmstate_gic = {
7452f5d
         VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
7452f5d
         VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU),
7452f5d
         VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU),
7452f5d
+        VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU),
7452f5d
         VMSTATE_END_OF_LIST()
7452f5d
     }
7452f5d
 };
7452f5d
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
7452f5d
index 983c3cf..89384c2 100644
7452f5d
--- a/include/hw/intc/arm_gic_common.h
7452f5d
+++ b/include/hw/intc/arm_gic_common.h
7452f5d
@@ -31,6 +31,9 @@
7452f5d
 /* Maximum number of possible CPU interfaces, determined by GIC architecture */
7452f5d
 #define GIC_NCPU 8
7452f5d
 
7452f5d
+#define MAX_NR_GROUP_PRIO 128
7452f5d
+#define GIC_NR_APRS (MAX_NR_GROUP_PRIO / 32)
7452f5d
+
7452f5d
 typedef struct gic_irq_state {
7452f5d
     /* The enable bits are only banked for per-cpu interrupts.  */
7452f5d
     uint8_t enabled;
7452f5d
@@ -75,6 +78,22 @@ typedef struct GICState {
7452f5d
     uint8_t  bpr[GIC_NCPU];
7452f5d
     uint8_t  abpr[GIC_NCPU];
7452f5d
 
7452f5d
+    /* The APR is implementation defined, so we choose a layout identical to
7452f5d
+     * the KVM ABI layout for QEMU's implementation of the gic:
7452f5d
+     * If an interrupt for preemption level X is active, then
7452f5d
+     *   APRn[X mod 32] == 0b1,  where n = X / 32
7452f5d
+     * otherwise the bit is clear.
7452f5d
+     *
7452f5d
+     * TODO: rewrite the interrupt acknowlege/complete routines to use
7452f5d
+     * the APR registers to track the necessary information to update
7452f5d
+     * s->running_priority[] on interrupt completion (ie completely remove
7452f5d
+     * last_active[][] and running_irq[]). This will be necessary if we ever
7452f5d
+     * want to support TCG<->KVM migration, or TCG guests which can
7452f5d
+     * do power management involving powering down and restarting
7452f5d
+     * the GIC.
7452f5d
+     */
7452f5d
+    uint32_t apr[GIC_NR_APRS][GIC_NCPU];
7452f5d
+
7452f5d
     uint32_t num_cpu;
7452f5d
 
7452f5d
     MemoryRegion iomem; /* Distributor */