Apply errata workarounds only when major/minor revisions match.
authorSoby Mathew <soby.mathew@arm.com>
Mon, 22 Sep 2014 11:11:36 +0000 (12:11 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Wed, 29 Oct 2014 17:38:56 +0000 (17:38 +0000)
Prior to this patch, the errata workarounds were applied for any version
of the CPU in the release build and in the debug build an assert
failure resulted when the revision did not match. This patch applies
errata workarounds in the Cortex-A57 reset handler only if the 'variant'
and 'revision' fields read from the MIDR_EL1 match. In the debug build,
a warning message is printed for each errata workaround which is not
applied.

The patch modifies the register usage in 'reset_handler` so
as to adhere to ARM procedure calling standards.

Fixes ARM-software/tf-issues#242

Change-Id: I51b1f876474599db885afa03346e38a476f84c29

docs/cpu-errata-workarounds.md
include/lib/aarch64/arch.h
lib/cpus/aarch64/cortex_a57.S
lib/cpus/aarch64/cpu_helpers.S

index 8285d89d3b51ffe92daa168d87f7c8babd4d06a0..09f7c72d1c5e59efe7e5478077ffcacf4afc9acf 100644 (file)
@@ -5,7 +5,7 @@ ARM Trusted Firmware exports a series of build flags which control the
 errata workarounds that are applied to each CPU by the reset handler. The
 errata details can be found in the CPU specifc errata documents published
 by ARM. The errata workarounds are implemented for a particular revision
-or a set of processor revisions. This check is done in the debug build.
+or a set of processor revisions. This is checked by reset handler at runtime.
 Each errata workaround is identified by its `ID` as specified in the processor's
 errata notice document. The format of the define used to enable/disable the
 errata is `ERRATA_<Processor name>_<ID>` where the `Processor name`
@@ -13,7 +13,10 @@ is either `A57` for the `Cortex_A57` CPU or `A53` for `Cortex_A53` CPU.
 
 All workarounds are disabled by default. The platform is reponsible for
 enabling these workarounds according to its requirement by defining the
-errata workaround build flags in the platform specific makefile.
+errata workaround build flags in the platform specific makefile. In case
+these workarounds are enabled for the wrong CPU revision then the errata
+workaround is not applied. In the DEBUG build, this is indicated by
+printing a warning to the crash console.
 
 In the current implementation, a platform which has more than 1 variant
 with different revisions of a processor has no runtime mechanism available
@@ -22,12 +25,12 @@ for it to specify which errata workarounds should be enabled or not.
 The value of the build flags are 0 by default, that is, disabled. Any other
 value will enable it.
 
-For Cortex A57, following errata build flags are defined :
+For Cortex-A57, following errata build flags are defined :
 
-*   `ERRATA_A57_806969`: This applies errata 806969 workaround to cortex a57
+*   `ERRATA_A57_806969`: This applies errata 806969 workaround to Cortex-A57
      CPU. This needs to be enabled only for revision r0p0 of the CPU.
 
-*   `ERRATA_A57_813420`: This applies errata 813420 workaround to cortex a57
+*   `ERRATA_A57_813420`: This applies errata 813420 workaround to Cortex-A57
      CPU. This needs to be enabled only for revision r0p0 of the CPU.
 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
index e5b2bf8ca2c930c58e663714c48ae56c0c29cc1d..476c9c5c0d235c98402ec3121c584ecd88924c20 100644 (file)
@@ -38,7 +38,9 @@
 #define MIDR_IMPL_MASK         0xff
 #define MIDR_IMPL_SHIFT                0x18
 #define MIDR_VAR_SHIFT         20
+#define MIDR_VAR_BITS          4
 #define MIDR_REV_SHIFT         0
+#define MIDR_REV_BITS          4
 #define MIDR_PN_MASK           0xfff
 #define MIDR_PN_SHIFT          0x4
 
index 3e55297802200faa2bc66ddbe11e00421248a988..e7774974a4df4885f4c4bd0219fa9dd23330e457 100644 (file)
@@ -81,33 +81,79 @@ func cortex_a57_disable_ext_debug
        dsb     sy
        ret
 
-func cortex_a57_reset_func
-#if ERRATA_A57_806969 || ERRATA_A57_813420
-       /* ---------------------------------------------
-        * Ensure that the following errata is only
-        * applied on r0p0 parts.
-        * ---------------------------------------------
+       /* --------------------------------------------------
+        * Errata Workaround for Cortex A57 Errata #806969.
+        * This applies only to revision r0p0 of Cortex A57.
+        * Inputs:
+        * x0: variant[4:7] and revision[0:3] of current cpu.
+        * --------------------------------------------------
         */
-#if ASM_ASSERTION
-       mrs     x0, midr_el1
-       ubfx    x1, x0, #MIDR_VAR_SHIFT, #4
-       ubfx    x2, x0, #MIDR_REV_SHIFT, #4
-       orr     x0, x1, x2
-       cmp     x0, #0
-       ASM_ASSERT(eq)
+func errata_a57_806969_wa
+       /*
+        * Compare x0 against revision r0p0
+        */
+       cbz     x0, apply_806969
+#if DEBUG
+       b       print_revision_warning
+#else
+       ret
 #endif
-       mov     x1, xzr
-#if ERRATA_A57_806969
+apply_806969:
+       mrs     x1, CPUACTLR_EL1
        orr     x1, x1, #CPUACTLR_NO_ALLOC_WBWA
+       msr     CPUACTLR_EL1, x1
+       ret
+
+
+       /* ---------------------------------------------------
+        * Errata Workaround for Cortex A57 Errata #813420.
+        * This applies only to revision r0p0 of Cortex A57.
+        * Inputs:
+        * x0: variant[4:7] and revision[0:3] of current cpu.
+        * ---------------------------------------------------
+        */
+func errata_a57_813420_wa
+       /*
+        * Compare x0 against revision r0p0
+        */
+       cbz     x0, apply_813420
+#if DEBUG
+       b       print_revision_warning
+#else
+       ret
 #endif
-#if ERRATA_A57_813420
+apply_813420:
+       mrs     x1, CPUACTLR_EL1
        orr     x1, x1, #CPUACTLR_DCC_AS_DCCI
-#endif
-       mrs     x0, CPUACTLR_EL1
-       orr     x0, x0, x1
-       msr     CPUACTLR_EL1, x0
+       msr     CPUACTLR_EL1, x1
+       ret
+
+       /* -------------------------------------------------
+        * The CPU Ops reset function for Cortex-A57.
+        * -------------------------------------------------
+        */
+func cortex_a57_reset_func
+       mov     x19, x30
+       mrs     x0, midr_el1
+
+       /*
+        * Extract the variant[20:23] and revision[0:3] from x0
+        * and pack it in x20[0:7] as variant[4:7] and revision[0:3].
+        * First extract x0[16:23] to x20[0:7] and zero fill the rest.
+        * Then extract x0[0:3] into x20[0:3] retaining other bits.
+        */
+       ubfx    x20, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+       bfxil   x20, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+
+#if ERRATA_A57_806969
+       mov     x0, x20
+       bl      errata_a57_806969_wa
 #endif
 
+#if ERRATA_A57_813420
+       mov     x0, x20
+       bl      errata_a57_813420_wa
+#endif
        /* ---------------------------------------------
         * As a bare minimum enable the SMP bit.
         * ---------------------------------------------
@@ -116,8 +162,12 @@ func cortex_a57_reset_func
        orr     x0, x0, #CPUECTLR_SMP_BIT
        msr     CPUECTLR_EL1, x0
        isb
-       ret
+       ret     x19
 
+       /* ----------------------------------------------------
+        * The CPU Ops core power down function for Cortex-A57.
+        * ----------------------------------------------------
+        */
 func cortex_a57_core_pwr_dwn
        mov     x18, x30
 
@@ -153,6 +203,10 @@ func cortex_a57_core_pwr_dwn
        mov     x30, x18
        b       cortex_a57_disable_ext_debug
 
+       /* -------------------------------------------------------
+        * The CPU Ops cluster power down function for Cortex-A57.
+        * -------------------------------------------------------
+        */
 func cortex_a57_cluster_pwr_dwn
        mov     x18, x30
 
index 46584b3f77caa716d31db80c5ec98ebe124cd5eb..f053d44f3d7cfc09e8bca080748f9fc38c39f360 100644 (file)
@@ -45,7 +45,7 @@
         */
        .globl  reset_handler
 func reset_handler
-       mov     x10, x30
+       mov     x19, x30
 
        bl      plat_reset_handler
 
@@ -58,10 +58,11 @@ func reset_handler
 
        /* Get the cpu_ops reset handler */
        ldr     x2, [x0, #CPU_RESET_FUNC]
+       mov     x30, x19
        cbz     x2, 1f
-       blr     x2
+       b     x2
 1:
-       ret     x10
+       ret
 
 #endif /* IMAGE_BL1 || (IMAGE_BL31 && RESET_TO_BL31) */
 
@@ -191,3 +192,29 @@ func get_cpu_ops_ptr
        sub     x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
 error_exit:
        ret
+
+#if DEBUG
+       /*
+        * This function prints a warning message to the crash console
+        * if the CPU revision/part number does not match the errata
+        * workaround enabled in the build.
+        * Clobber: x30, x0 - x5
+        */
+.section .rodata.rev_warn_str, "aS"
+rev_warn_str:
+       .asciz "Warning: Skipping Errata workaround for non matching CPU revision number.\n"
+
+       .globl  print_revision_warning
+func print_revision_warning
+       mov     x5, x30
+       /* Ensure the console is initialized */
+       bl      plat_crash_console_init
+       /* Check if the console is initialized */
+       cbz     x0, 1f
+       /* The console is initialized */
+       adr     x4, rev_warn_str
+       bl      asm_print_str
+1:
+       ret     x5
+#endif
+