qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-arm] [RFC PATCH] hw/intc/arm_gic_kvm.c: access the implemented APR


From: wanghaibin
Subject: [Qemu-arm] [RFC PATCH] hw/intc/arm_gic_kvm.c: access the implemented APRn
Date: Wed, 23 Aug 2017 18:22:33 +0800

Whether the APRn is implemented depends on how many priority
bits support. Compared with GICv3, There is no way to retrieve
this information directly from the register, so GICD_IPRIORITYR
access method is used here according to the SPEC:
To determine the number of priority bits implemented for SPIs,
software can write 0xFF to a writable
GICD_IPRIORITYR<n> priority field and read back the value stored.

Signed-off-by: wanghaibin <address@hidden>
---
 hw/intc/arm_gic_kvm.c | 56 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 47 insertions(+), 9 deletions(-)

diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index ae095d0..a2f3139 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -290,13 +290,30 @@ static void kvm_dist_put(GICState *s, uint32_t offset, 
int width,
     }
 }
 
+static int kvm_arm_gic_get_pri_bits(GICState *s)
+{
+    uint32_t reg = 0xff;
+
+    /* 
+     * To determine the number of priority bits implemented, Just wirte the 
0xff to 
+     * the first SPI(32) GICD_IPRIORITYR priority field and read back the 
value 
+     * stored. 
+     * Note: Assume that implementations support the same number of priority 
+     * bits for each PE
+     */
+    kvm_gicd_access(s, 0x400 + 0x20, 0, &reg, true);
+    kvm_gicd_access(s, 0x400 + 0x20, 0, &reg, false);
+
+    return 8 - ctz32(reg);
+}
+
 static void kvm_arm_gic_put(GICState *s)
 {
     uint32_t reg;
-    int i;
     int cpu;
     int num_cpu;
     int num_irq;
+    int num_pri_bits;
 
     /* Note: We do the restore in a slightly different order than the save
      * (where the order doesn't matter and is simply ordered according to the
@@ -326,6 +343,8 @@ static void kvm_arm_gic_put(GICState *s)
             abort();
     }
 
+    num_pri_bits = kvm_arm_gic_get_pri_bits(s);
+
     /* TODO: Consider checking compatibility with the IIDR ? */
 
     /* irq_state[n].enabled -> GICD_ISENABLERn */
@@ -353,7 +372,6 @@ static void kvm_arm_gic_put(GICState *s)
     kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
     kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
 
-
     /* s->priorityX[irq] -> ICD_IPRIORITYRn */
     kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
 
@@ -384,9 +402,18 @@ static void kvm_arm_gic_put(GICState *s)
         kvm_gicc_access(s, 0x1c, cpu, &reg, true);
 
         /* s->apr[n][cpu] -> GICC_APRn */
-        for (i = 0; i < 4; i++) {
-            reg = s->apr[i][cpu];
-            kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, true);
+        switch (num_pri_bits) {
+        case 7:
+            reg = s->apr[3][cpu];
+            kvm_gicc_access(s, 0xd0 + 3 * 4, cpu, &reg, true);
+            reg = s->apr[2][cpu];
+            kvm_gicc_access(s, 0xd0 + 2 * 4, cpu, &reg, true);
+        case 6:
+            reg = s->apr[1][cpu];
+            kvm_gicc_access(s, 0xd0 + 1 * 4, cpu, &reg, true);
+        default:
+            reg = s->apr[0][cpu];
+            kvm_gicc_access(s, 0xd0, cpu, &reg, true);
         }
     }
 }
@@ -396,6 +423,7 @@ static void kvm_arm_gic_get(GICState *s)
     uint32_t reg;
     int i;
     int cpu;
+    int num_pri_bits;
 
     /*****************************************************************
      * Distributor State
@@ -448,6 +476,7 @@ static void kvm_arm_gic_get(GICState *s)
     /* GICD_CPENDSGIRn -> s->sgi_pending */
     kvm_dist_get(s, 0xf10, 8, GIC_NR_SGIS, translate_sgisource);
 
+    num_pri_bits = kvm_arm_gic_get_pri_bits(s);
 
     /*****************************************************************
      * CPU Interface(s) State
@@ -470,10 +499,19 @@ static void kvm_arm_gic_get(GICState *s)
         kvm_gicc_access(s, 0x1c, cpu, &reg, false);
         s->abpr[cpu] = (reg & 0x7);
 
-        /* GICC_APRn -> s->apr[n][cpu] */
-        for (i = 0; i < 4; i++) {
-            kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, false);
-            s->apr[i][cpu] = reg;
+        /* s->apr[n][cpu] -> GICC_APRn */
+        switch (num_pri_bits) {
+        case 7:
+            kvm_gicc_access(s, 0xd0 + 3 * 4, cpu, &reg, false);
+            s->apr[3][cpu] = reg;
+            kvm_gicc_access(s, 0xd0 + 2 * 4, cpu, &reg, false);
+            s->apr[2][cpu] = reg;
+        case 6:
+            kvm_gicc_access(s, 0xd0 + 1 * 4, cpu, &reg, false);
+            s->apr[1][cpu] = reg;
+        default:
+            kvm_gicc_access(s, 0xd0, cpu, &reg, false);
+            s->apr[0][cpu] = reg;
         }
     }
 }
-- 
1.8.3.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]