xen/arm: vgic-v3: Allow AArch32 guest booting with GICv3
authorJulien Grall <julien.grall@arm.com>
Wed, 7 Dec 2016 12:33:53 +0000 (12:33 +0000)
committerStefano Stabellini <sstabellini@kernel.org>
Wed, 7 Dec 2016 22:49:42 +0000 (14:49 -0800)
AArch32 guest will use co-processor registers to access the GICv3 (see
8.5 in IHI 0069C). Some of the registers have to be trapped and emulated
(e.g ICC_SGI1R), this is the purpose of this patch.

The rest of the emulation already supports access required for AArch32
so nothing has to be changed there.

Note this is only enabling 32-bit guest using GICv3 on Xen ARM64. Further
work would be required to compile GICv3 and vGICv3 for Xen ARM32.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/arch/arm/traps.c
xen/arch/arm/vgic-v3.c
xen/include/asm-arm/cpregs.h
xen/include/asm-arm/perfc_defn.h

index 1fe02cb5ccbe64315f92d9782e15916f46ae4f72..eb85d92c6d6fa1e9981531b15bcd8025428f4258 100644 (file)
@@ -1875,6 +1875,18 @@ static void do_cp15_64(struct cpu_user_regs *regs,
             return inject_undef_exception(regs, hsr);
         break;
 
+    /*
+     * HCR_EL2.FMO or HCR_EL2.IMO
+     *
+     * GIC Architecture Specification (IHI 0069C): Section 4.6.3
+     */
+    case HSR_CPREG64(ICC_SGI1R):
+    case HSR_CPREG64(ICC_ASGI1R):
+    case HSR_CPREG64(ICC_SGI0R):
+        if ( !vgic_emulate(regs, hsr) )
+            return inject_undef_exception(regs, hsr);
+        break;
+
     /*
      * CPTR_EL2.T{0..9,12..13}
      *
index ed588ab0a358cf09419c0ae025be6150f617b491..d61479d5d408057c30fbd4b8a872ec4766389b07 100644 (file)
@@ -1335,12 +1335,32 @@ static bool vgic_v3_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr)
     }
 }
 
+static bool vgic_v3_emulate_cp64(struct cpu_user_regs *regs, union hsr hsr)
+{
+    struct hsr_cp64 cp64 = hsr.cp64;
+
+    if ( cp64.read )
+        perfc_incr(vgic_cp64_reads);
+    else
+        perfc_incr(vgic_cp64_writes);
+
+    switch ( hsr.bits & HSR_CP64_REGS_MASK )
+    {
+    case HSR_CPREG64(ICC_SGI1R):
+        return vreg_emulate_cp64(regs, hsr, vgic_v3_emulate_sgi1r);
+    default:
+        return false;
+    }
+}
+
 static bool vgic_v3_emulate_reg(struct cpu_user_regs *regs, union hsr hsr)
 {
     switch (hsr.ec)
     {
     case HSR_EC_SYSREG:
         return vgic_v3_emulate_sysreg(regs, hsr);
+    case HSR_EC_CP15_64:
+        return vgic_v3_emulate_cp64(regs, hsr);
     default:
         return false;
     }
index e5cb00cc2b2860fc24a036c6313d9a1e69a9130b..af45ec7a65e33a72b6877f72c53ca81d14579d41 100644 (file)
 /* CP15 CR11: DMA Operations for TCM Access */
 
 /* CP15 CR12:  */
+#define ICC_SGI1R       p15,0,c12       /* Interrupt Controller SGI Group 1 */
+#define ICC_ASGI1R      p15,1,c12       /* Interrupt Controller Alias SGI Group 1 Register */
+#define ICC_SGI0R       p15,2,c12       /* Interrupt Controller SGI Group 0 */
 #define VBAR            p15,0,c12,c0,0  /* Vector Base Address Register */
 #define HVBAR           p15,4,c12,c0,0  /* Hyp. Vector Base Address Register */
 
index 69fabe75299c6b28211154f8b218808c1eaaa937..5f957ee6ec954bde2df35f0f03de7f983b03ce32 100644 (file)
@@ -38,6 +38,8 @@ PERFCOUNTER(vgicd_reads,                "vgicd: read")
 PERFCOUNTER(vgicd_writes,               "vgicd: write")
 PERFCOUNTER(vgicr_reads,                "vgicr: read")
 PERFCOUNTER(vgicr_writes,               "vgicr: write")
+PERFCOUNTER(vgic_cp64_reads,            "vgic: cp64 read")
+PERFCOUNTER(vgic_cp64_writes,           "vgic: cp64 write")
 PERFCOUNTER(vgic_sysreg_reads,          "vgic: sysreg read")
 PERFCOUNTER(vgic_sysreg_writes,         "vgic: sysreg write")
 PERFCOUNTER(vgic_sgi_list  ,            "vgic: SGI send to list")