FVP_Base_AEMv8A platform: Fix cache maintenance operations
authorAlexei Fedorov <Alexei.Fedorov@arm.com>
Mon, 29 Jul 2019 16:22:53 +0000 (17:22 +0100)
committerPaul Beesley <paul.beesley@arm.com>
Fri, 16 Aug 2019 11:30:37 +0000 (11:30 +0000)
This patch fixes FVP_Base_AEMv8A model hang issue with
ARMv8.4+ with cache modelling enabled configuration.
Incorrect L1 cache flush operation to PoU, using CLIDR_EL1
LoUIS field, which is required by the architecture to be
zero for ARMv8.4-A with ARMv8.4-S2FWB feature is replaced
with L1 to L2 and L2 to L3 (if L3 is present) cache flushes.
FVP_Base_AEMv8A model can be configured with L3 enabled by
setting `cluster0.l3cache-size` and `cluster1.l3cache-size`
to non-zero values, and presence of L3 is checked in
`aem_generic_core_pwr_dwn` function by reading
CLIDR_EL1.Ctype3 field value.

Change-Id: If3de3d4eb5ed409e5b4ccdbc2fe6d5a01894a9af
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
include/arch/aarch64/arch.h
lib/cpus/aarch64/aem_generic.S

index fa857fb1b5c1341837a27f9bbcf2e05678c43278..2b4ae1ad7b2ba28f5491ebe535c3b71bd0377e5c 100644 (file)
 /* CLIDR definitions */
 #define LOUIS_SHIFT            U(21)
 #define LOC_SHIFT              U(24)
+#define CTYPE_SHIFT(n)         U(3 * (n - 1))
 #define CLIDR_FIELD_WIDTH      U(3)
 
 /* CSSELR definitions */
index 51b5ce91cb744b49701cad9b5442cb75c4f20104..6291e43e1ef53868a897ea8b72c6807e83cd7c62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,15 +18,43 @@ func aem_generic_core_pwr_dwn
        msr     sctlr_el3, x1
        isb
 
+       /* ---------------------------------------------
+        * AEM model supports L3 caches in which case L2
+        * will be private per core caches and flush
+        * from L1 to L2 is not sufficient.
+        * ---------------------------------------------
+        */
+       mrs     x1, clidr_el1
+
+       /* ---------------------------------------------
+        * Check if L3 cache is implemented.
+        * ---------------------------------------------
+        */
+       tst     x1, ((1 << CLIDR_FIELD_WIDTH) - 1) << CTYPE_SHIFT(3)
+
+       /* ---------------------------------------------
+        * There is no L3 cache, flush L1 to L2 only.
+        * ---------------------------------------------
+        */
        mov     x0, #DCCISW
+       b.eq    dcsw_op_level1
+
+       mov     x18, x30
 
        /* ---------------------------------------------
-        * Flush L1 cache to PoU.
+        * Flush L1 cache to L2.
         * ---------------------------------------------
         */
-       b       dcsw_op_louis
-endfunc aem_generic_core_pwr_dwn
+       bl      dcsw_op_level1
+       mov     x30, x18
 
+       /* ---------------------------------------------
+        * Flush L2 cache to L3.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       b       dcsw_op_level2
+endfunc aem_generic_core_pwr_dwn
 
 func aem_generic_cluster_pwr_dwn
        /* ---------------------------------------------
@@ -39,7 +67,7 @@ func aem_generic_cluster_pwr_dwn
        isb
 
        /* ---------------------------------------------
-        * Flush L1 and L2 caches to PoC.
+        * Flush all caches to PoC.
         * ---------------------------------------------
         */
        mov     x0, #DCCISW