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

[xen master] xen/arm: Add Cortex-A77 erratum 1508412 handling



commit bd3ddaf6ee7fa312bd077305819105f84a34008d
Author:     Luca Fancellu <luca.fancellu@xxxxxxx>
AuthorDate: Mon Jul 17 13:25:46 2023 +0100
Commit:     Julien Grall <jgrall@xxxxxxxxxx>
CommitDate: Tue Aug 8 08:50:17 2023 +0100

    xen/arm: Add Cortex-A77 erratum 1508412 handling
    
    Cortex-A77 cores (r0p0, r1p0) could deadlock on a sequence of a
    store-exclusive or read of PAR_EL1 and a load with device or non-cacheable
    memory attributes.
    A workaround is available, but it depends on a firmware counterpart.
    
    The proposed workaround from the errata document is to modify the software
    running at EL1 and above to include a DMB SY before and after accessing
    PAR_EL1.
    
    In conjunction to the above, the firmware needs to use a specific write
    sequence to several IMPLEMENTATION DEFINED registers to have the hardware
    insert a DMB SY after all load-exclusive and store-exclusive instructions.
    
    Apply the workaround to Xen where PAR_EL1 is read, implementing an helper
    function to do that.
    Since Xen can be interrupted by irqs in any moment, add a barrier on
    entry/exit when we are running on the affected cores.
    
    A guest without the workaround can deadlock the system, so warn the users
    of Xen with the above type of cores to use only trusted guests, by
    printing a message on Xen startup.
    
    This is XSA-436 / CVE-2023-34320.
    
    Signed-off-by: Luca Fancellu <luca.fancellu@xxxxxxx>
    Reviewed-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
    Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx>
---
 SUPPORT.md                            |  2 ++
 docs/misc/arm/silicon-errata.txt      |  1 +
 xen/arch/arm/Kconfig                  | 21 +++++++++++++++++++++
 xen/arch/arm/arm64/entry.S            | 19 +++++++++++++++++++
 xen/arch/arm/cpuerrata.c              | 16 ++++++++++++----
 xen/arch/arm/domain.c                 |  2 +-
 xen/arch/arm/include/asm/arm64/page.h | 12 ++++++------
 xen/arch/arm/include/asm/cpufeature.h |  3 ++-
 xen/arch/arm/include/asm/sysregs.h    | 24 ++++++++++++++++++++++++
 9 files changed, 88 insertions(+), 12 deletions(-)

diff --git a/SUPPORT.md b/SUPPORT.md
index 35a6249e03..1c9f0b7d8c 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -39,8 +39,10 @@ supported in this document.
 
     Status: Supported
     Status, Cortex A57 r0p0-r1p1: Supported, not security supported
+    Status, Cortex A77 r0p0-r1p0: Supported, not security supported
 
 For the Cortex A57 r0p0 - r1p1, see Errata 832075.
+For the Cortex A77 r0p0 - r1p0, see Errata 1508412.
 
 ## Host hardware support
 
diff --git a/docs/misc/arm/silicon-errata.txt b/docs/misc/arm/silicon-errata.txt
index a7abcc1ba1..fffca09656 100644
--- a/docs/misc/arm/silicon-errata.txt
+++ b/docs/misc/arm/silicon-errata.txt
@@ -58,4 +58,5 @@ stable hypervisors.
 | ARM            | Cortex-A76      | #1286807        | ARM64_ERRATUM_1286807   
|
 | ARM            | Neoverse-N1     | #1165522        | N/A                     
|
 | ARM            | Neoverse-N1     | #1286807        | ARM64_ERRATUM_1286807   
|
+| ARM            | Cortex-A77      | #1508412        | ARM64_ERRATUM_1508412   
|
 | ARM            | MMU-500         | #842869         | N/A                     
|
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index fd57a82dd2..57bd1d01d7 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -355,6 +355,27 @@ config ARM64_ERRATUM_1286807
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1508412
+       bool "Cortex-A77: 1508412: possible deadlock on sequence of NC/Device 
load and store exclusive or PAR read"
+       default y
+       depends on ARM_64
+       help
+         This option adds a workaround for Arm Cortex-A77 erratum 1508412.
+
+         Affected Cortex-A77 cores (r0p0, r1p0) could deadlock on a sequence
+         of a store-exclusive or read of PAR_EL1 and a load with device or
+         non-cacheable memory attributes. The workaround depends on a firmware
+         counterpart.
+
+         Xen guests must also have the workaround implemented or they can
+         deadlock the system.
+
+         Work around the issue by inserting DMB SY barriers around PAR_EL1
+         register reads and warning Xen users. The DMB barrier is sufficient
+         to prevent a speculative PAR_EL1 read.
+
+         If unsure, say Y.
+
 endmenu
 
 config ARM64_HARDEN_BRANCH_PREDICTOR
diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index 523c6d23d9..f963c923bb 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -134,6 +134,16 @@
  * position on the stack before.
  */
         .macro  entry, hyp, compat, save_x0_x1=1
+
+        /*
+         * Ensure any PAR_EL1 reads complete, in case we were interrupted
+         * between the PAR_EL1 read and the memory barrier for the erratum
+         * 1508412 workaround.
+         */
+        alternative_if ARM64_WORKAROUND_1508412
+        dmb sy
+        alternative_else_nop_endif
+
         sub     sp, sp, #(UREGS_SPSR_el1 - UREGS_LR) /* CPSR, PC, SP, LR */
 
         .if \hyp == 0         /* Guest mode */
@@ -503,6 +513,15 @@ return_from_trap:
 
         ldr     lr, [sp], #(UREGS_SPSR_el1 - UREGS_LR) /* CPSR, PC, SP, LR */
 
+        /*
+         * Ensure any device/NC reads complete, in case we were interrupted
+         * between the memory barrier for the erratum 1508412 workaround and
+         * any PAR_EL1 read.
+         */
+        alternative_if ARM64_WORKAROUND_1508412
+        dmb sy
+        alternative_else_nop_endif
+
         eret
         sb
 
diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c
index d0658aedb6..fcf32892a7 100644
--- a/xen/arch/arm/cpuerrata.c
+++ b/xen/arch/arm/cpuerrata.c
@@ -669,6 +669,14 @@ static const struct arm_cpu_capabilities arm_errata[] = {
         .capability = ARM64_WORKAROUND_AT_SPECULATE,
         MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
     },
+#ifdef CONFIG_ARM64_ERRATUM_1508412
+    {
+        /* Cortex-A77 r0p0 - r1p0 */
+        .desc = "ARM erratum 1508412 (hypervisor portion)",
+        .capability = ARM64_WORKAROUND_1508412,
+        MIDR_RANGE(MIDR_CORTEX_A77, 0, 1),
+    },
+#endif
     {
         /* Cortex-A55 (All versions as erratum is open in SDEN v14) */
         .desc = "ARM erratum 1530923",
@@ -687,11 +695,11 @@ void __init enable_errata_workarounds(void)
 {
     enable_cpu_capabilities(arm_errata);
 
-#ifdef CONFIG_ARM64_ERRATUM_832075
-    if ( cpus_have_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) )
+#if defined(CONFIG_ARM64_ERRATUM_832075) || 
defined(CONFIG_ARM64_ERRATUM_1508412)
+    if ( cpus_have_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||
+         cpus_have_cap(ARM64_WORKAROUND_1508412) )
     {
-        printk_once("**** This CPU is affected by the errata 832075.           
           ****\n"
-                    "**** Guests without CPU erratum workarounds can deadlock 
the system! ****\n"
+        printk_once("**** Guests without CPU erratum workarounds can deadlock 
the system! ****\n"
                     "**** Only trusted guests should be used.                  
           ****\n");
 
         /* Taint the machine has being insecure */
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 3ae86ca620..6113ca785c 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -131,7 +131,7 @@ static void ctxt_switch_from(struct vcpu *p)
     p->arch.ttbr1 = READ_SYSREG64(TTBR1_EL1);
     if ( is_32bit_domain(p->domain) )
         p->arch.dacr = READ_SYSREG(DACR32_EL2);
-    p->arch.par = READ_SYSREG64(PAR_EL1);
+    p->arch.par = read_sysreg_par();
 #if defined(CONFIG_ARM_32)
     p->arch.mair0 = READ_CP32(MAIR0);
     p->arch.mair1 = READ_CP32(MAIR1);
diff --git a/xen/arch/arm/include/asm/arm64/page.h 
b/xen/arch/arm/include/asm/arm64/page.h
index 4f58c0382a..e944985ee0 100644
--- a/xen/arch/arm/include/asm/arm64/page.h
+++ b/xen/arch/arm/include/asm/arm64/page.h
@@ -37,11 +37,11 @@ static inline void invalidate_icache_local(void)
 /* Ask the MMU to translate a VA for us */
 static inline uint64_t __va_to_par(vaddr_t va)
 {
-    uint64_t par, tmp = READ_SYSREG64(PAR_EL1);
+    uint64_t par, tmp = read_sysreg_par();
 
     asm volatile ("at s1e2r, %0;" : : "r" (va));
     isb();
-    par = READ_SYSREG64(PAR_EL1);
+    par = read_sysreg_par();
     WRITE_SYSREG64(tmp, PAR_EL1);
     return par;
 }
@@ -49,28 +49,28 @@ static inline uint64_t __va_to_par(vaddr_t va)
 /* Ask the MMU to translate a Guest VA for us */
 static inline uint64_t gva_to_ma_par(vaddr_t va, unsigned int flags)
 {
-    uint64_t par, tmp = READ_SYSREG64(PAR_EL1);
+    uint64_t par, tmp = read_sysreg_par();
 
     if ( (flags & GV2M_WRITE) == GV2M_WRITE )
         asm volatile ("at s12e1w, %0;" : : "r" (va));
     else
         asm volatile ("at s12e1r, %0;" : : "r" (va));
     isb();
-    par = READ_SYSREG64(PAR_EL1);
+    par = read_sysreg_par();
     WRITE_SYSREG64(tmp, PAR_EL1);
     return par;
 }
 
 static inline uint64_t gva_to_ipa_par(vaddr_t va, unsigned int flags)
 {
-    uint64_t par, tmp = READ_SYSREG64(PAR_EL1);
+    uint64_t par, tmp = read_sysreg_par();
 
     if ( (flags & GV2M_WRITE) == GV2M_WRITE )
         asm volatile ("at s1e1w, %0;" : : "r" (va));
     else
         asm volatile ("at s1e1r, %0;" : : "r" (va));
     isb();
-    par = READ_SYSREG64(PAR_EL1);
+    par = read_sysreg_par();
     WRITE_SYSREG64(tmp, PAR_EL1);
     return par;
 }
diff --git a/xen/arch/arm/include/asm/cpufeature.h 
b/xen/arch/arm/include/asm/cpufeature.h
index 894f278a4a..8011076b8c 100644
--- a/xen/arch/arm/include/asm/cpufeature.h
+++ b/xen/arch/arm/include/asm/cpufeature.h
@@ -75,8 +75,9 @@
 #define ARM_WORKAROUND_BHB_LOOP_32 14
 #define ARM_WORKAROUND_BHB_SMCC_3 15
 #define ARM_HAS_SB 16
+#define ARM64_WORKAROUND_1508412 17
 
-#define ARM_NCAPS           17
+#define ARM_NCAPS           18
 
 #ifndef __ASSEMBLY__
 
diff --git a/xen/arch/arm/include/asm/sysregs.h 
b/xen/arch/arm/include/asm/sysregs.h
index 5c5c51bbcd..61e30c9e51 100644
--- a/xen/arch/arm/include/asm/sysregs.h
+++ b/xen/arch/arm/include/asm/sysregs.h
@@ -9,6 +9,30 @@
 # error "unknown ARM variant"
 #endif
 
+#ifndef __ASSEMBLY__
+
+#include <asm/alternative.h>
+
+static inline register_t read_sysreg_par(void)
+{
+    register_t par_el1;
+
+    /*
+     * On Cortex-A77 r0p0 and r1p0, read access to PAR_EL1 shall include a
+     * DMB SY before and after accessing it, as part of the workaround for the
+     * errata 1508412.
+     */
+    asm volatile(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412,
+                 CONFIG_ARM64_ERRATUM_1508412));
+    par_el1 = READ_SYSREG64(PAR_EL1);
+    asm volatile(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412,
+                 CONFIG_ARM64_ERRATUM_1508412));
+
+    return par_el1;
+}
+
+#endif /*  !__ASSEMBLY__  */
+
 #endif /* __ASM_ARM_SYSREGS_H */
 /*
  * Local variables:
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.