[Xen-devel] xen/arm: traps: Emulate ICC_SRE_EL1 as RAZ/WI

Message ID 1480959803-4206-1-git-send-email-julien.grall@arm.com
State New
Headers show

Commit Message

Julien Grall Dec. 5, 2016, 5:43 p.m.
Recent Linux kernel (4.4 and onwards [1]) is checking whether it is possible
to enable sysreg access (ICC_SRE_EL1.SRE) when the ID register
(ID_AA64PRF0_EL1.GIC) is reporting the presence of the sysreg interface.

When the guest has been configured to use GICv2, the hypervisor will
disable sysreg access for this vm (via ICC_SRE_EL2.Enable) and therefore
access to system register such as ICC_SRE_EL1 are trapped in EL2.

However, ICC_SRE_EL1 is not emulated by the hypervisor. This means that
Linux will crash as soon as it is trying to access ICC_SRE_EL1.

To solve this problem, Xen can implement ICC_SRE_EL1 as read-as-zero
write-ignore. The emulation will only be used when sysreg are disabled
for EL1.

[1]  963fcd409 "arm64: cpufeatures: Check ICC_EL1_SRE.SRE before
enabling ARM64_HAS_SYSREG_GIC_CPUIF"

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    I think this patch would need to be backported as recent Linux (4.4
    and onwards) are trying to access ICC_EL1_SRE during boot time.

    The first support of GICv2 on GICv3 was in Xen 4.6.
---
 xen/arch/arm/traps.c          | 14 ++++++++++++++
 xen/include/asm-arm/sysregs.h |  1 +
 2 files changed, 15 insertions(+)

Comments

Stefano Stabellini Dec. 5, 2016, 8:35 p.m. | #1
On Mon, 5 Dec 2016, Julien Grall wrote:
> Recent Linux kernel (4.4 and onwards [1]) is checking whether it is possible
> to enable sysreg access (ICC_SRE_EL1.SRE) when the ID register
> (ID_AA64PRF0_EL1.GIC) is reporting the presence of the sysreg interface.
> 
> When the guest has been configured to use GICv2, the hypervisor will
> disable sysreg access for this vm (via ICC_SRE_EL2.Enable) and therefore
> access to system register such as ICC_SRE_EL1 are trapped in EL2.
> 
> However, ICC_SRE_EL1 is not emulated by the hypervisor. This means that
> Linux will crash as soon as it is trying to access ICC_SRE_EL1.
> 
> To solve this problem, Xen can implement ICC_SRE_EL1 as read-as-zero
> write-ignore. The emulation will only be used when sysreg are disabled
> for EL1.
> 
> [1]  963fcd409 "arm64: cpufeatures: Check ICC_EL1_SRE.SRE before
> enabling ARM64_HAS_SYSREG_GIC_CPUIF"
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>

And applied


> ---
>     I think this patch would need to be backported as recent Linux (4.4
>     and onwards) are trying to access ICC_EL1_SRE during boot time.
> 
>     The first support of GICv2 on GICv3 was in Xen 4.6.
> ---
>  xen/arch/arm/traps.c          | 14 ++++++++++++++
>  xen/include/asm-arm/sysregs.h |  1 +
>  2 files changed, 15 insertions(+)
> 
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 8ff73fe..ae921d7 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -2280,6 +2280,20 @@ static void do_sysreg(struct cpu_user_regs *regs,
>          return inject_undef64_exception(regs, hsr.len);
>  
>      /*
> +     *  ICC_SRE_EL2.Enable = 0
> +     *
> +     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
> +     */
> +    case HSR_SYSREG_ICC_SRE_EL1:
> +        /*
> +         * Trapped when the guest is using GICv2 whilst the platform
> +         * interrupt controller is GICv3. In this case, the register
> +         * should be emulate as RAZ/WI to tell the guest to use the GIC
> +         * memory mapped interface (i.e GICv2 compatibility).
> +         */
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
>       * HCR_EL2.TIDCP
>       *
>       * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
> diff --git a/xen/include/asm-arm/sysregs.h b/xen/include/asm-arm/sysregs.h
> index 570f43e..887368e 100644
> --- a/xen/include/asm-arm/sysregs.h
> +++ b/xen/include/asm-arm/sysregs.h
> @@ -90,6 +90,7 @@
>  #define HSR_SYSREG_ICC_SGI1R_EL1  HSR_SYSREG(3,0,c12,c11,5)
>  #define HSR_SYSREG_ICC_ASGI1R_EL1 HSR_SYSREG(3,1,c12,c11,6)
>  #define HSR_SYSREG_ICC_SGI0R_EL1  HSR_SYSREG(3,2,c12,c11,7)
> +#define HSR_SYSREG_ICC_SRE_EL1    HSR_SYSREG(3,0,c12,c12,5)
>  #define HSR_SYSREG_CONTEXTIDR_EL1 HSR_SYSREG(3,0,c13,c0,1)
>  
>  #define HSR_SYSREG_PMCR_EL0       HSR_SYSREG(3,3,c9,c12,0)
> -- 
> 1.9.1
>

Patch

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 8ff73fe..ae921d7 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2280,6 +2280,20 @@  static void do_sysreg(struct cpu_user_regs *regs,
         return inject_undef64_exception(regs, hsr.len);
 
     /*
+     *  ICC_SRE_EL2.Enable = 0
+     *
+     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
+     */
+    case HSR_SYSREG_ICC_SRE_EL1:
+        /*
+         * Trapped when the guest is using GICv2 whilst the platform
+         * interrupt controller is GICv3. In this case, the register
+         * should be emulate as RAZ/WI to tell the guest to use the GIC
+         * memory mapped interface (i.e GICv2 compatibility).
+         */
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
      * HCR_EL2.TIDCP
      *
      * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
diff --git a/xen/include/asm-arm/sysregs.h b/xen/include/asm-arm/sysregs.h
index 570f43e..887368e 100644
--- a/xen/include/asm-arm/sysregs.h
+++ b/xen/include/asm-arm/sysregs.h
@@ -90,6 +90,7 @@ 
 #define HSR_SYSREG_ICC_SGI1R_EL1  HSR_SYSREG(3,0,c12,c11,5)
 #define HSR_SYSREG_ICC_ASGI1R_EL1 HSR_SYSREG(3,1,c12,c11,6)
 #define HSR_SYSREG_ICC_SGI0R_EL1  HSR_SYSREG(3,2,c12,c11,7)
+#define HSR_SYSREG_ICC_SRE_EL1    HSR_SYSREG(3,0,c12,c12,5)
 #define HSR_SYSREG_CONTEXTIDR_EL1 HSR_SYSREG(3,0,c13,c0,1)
 
 #define HSR_SYSREG_PMCR_EL0       HSR_SYSREG(3,3,c9,c12,0)