diff --git a/docs/cpu-specific-build-macros.md b/docs/cpu-specific-build-macros.md index 0a575f7..eb23bcd 100644 --- a/docs/cpu-specific-build-macros.md +++ b/docs/cpu-specific-build-macros.md @@ -60,6 +60,13 @@ CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From r0p4 and onwards, this errata is enabled by default in hardware. +* `ERRATA_A53_855873`: This applies errata 855873 workaround to Cortex-A53 + CPUs. Though the erratum is present in every revision of the CPU, + this workaround is only applied to CPUs from r0p3 onwards, which feature + a chicken bit in CPUACTLR_EL1 to enable a hardware workaround. + Earlier revisions of the CPU have other errata which require the same + workaround in software, so they should be covered anyway. + For Cortex-A57, following errata build flags are defined : * `ERRATA_A57_806969`: This applies errata 806969 workaround to Cortex-A57 diff --git a/include/lib/cpus/aarch64/cortex_a53.h b/include/lib/cpus/aarch64/cortex_a53.h index 6976b80..484eb63 100644 --- a/include/lib/cpus/aarch64/cortex_a53.h +++ b/include/lib/cpus/aarch64/cortex_a53.h @@ -67,6 +67,7 @@ #define CPUACTLR_EL1 S3_1_C15_C2_0 /* Instruction def. */ #define CPUACTLR_DTAH (1 << 24) +#define CPUACTLR_ENDCCASCI (1 << 44) /******************************************************************************* * L2 Auxiliary Control register specific definitions. diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S index 1dd8a86..a36666b 100644 --- a/lib/cpus/aarch64/cortex_a53.S +++ b/lib/cpus/aarch64/cortex_a53.S @@ -129,6 +129,39 @@ b cpu_rev_var_ls endfunc check_errata_disable_non_temporal_hint + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #855873. + * + * This applies only to revisions >= r0p3 of Cortex A53. + * Earlier revisions of the core are affected as well, but don't + * have the chicken bit in the CPUACTLR register. It is expected that + * the rich OS takes care of that, especially as the workaround is + * shared with other erratas in those revisions of the CPU. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a53_855873_wa + /* + * Compare x0 against revision r0p3 and higher + */ + mov x17, x30 + bl check_errata_855873 + cbz x0, 1f + + mrs x1, CPUACTLR_EL1 + orr x1, x1, #CPUACTLR_ENDCCASCI + msr CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a53_855873_wa + +func check_errata_855873 + mov x1, #0x03 + b cpu_rev_var_hs +endfunc check_errata_855873 + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A53. * Shall clobber: x0-x19 @@ -150,6 +183,11 @@ bl a53_disable_non_temporal_hint #endif +#if ERRATA_A53_855873 + mov x0, x18 + bl errata_a53_855873_wa +#endif + /* --------------------------------------------- * Enable the SMP bit. * --------------------------------------------- @@ -238,6 +276,7 @@ */ report_errata ERRATA_A53_826319, cortex_a53, 826319 report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + report_errata ERRATA_A53_855873, cortex_a53, 855873 ldp x8, x30, [sp], #16 ret @@ -255,13 +294,15 @@ */ .section .rodata.cortex_a53_regs, "aS" cortex_a53_regs: /* The ascii list of register names to be reported */ - .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", "" + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", \ + "cpuactlr_el1", "" func cortex_a53_cpu_reg_dump adr x6, cortex_a53_regs mrs x8, CPUECTLR_EL1 mrs x9, CPUMERRSR_EL1 mrs x10, L2MERRSR_EL1 + mrs x11, CPUACTLR_EL1 ret endfunc cortex_a53_cpu_reg_dump diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S index 6a3669d..47cb6a2 100644 --- a/lib/cpus/aarch64/cpu_helpers.S +++ b/lib/cpus/aarch64/cpu_helpers.S @@ -234,6 +234,20 @@ ret endfunc cpu_rev_var_ls +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is higher than or same as a + * given value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_hs +func cpu_rev_var_hs + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, hs + ret +endfunc cpu_rev_var_hs + #if REPORT_ERRATA /* * void print_errata_status(void); diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk index 7d7db20..132ab6f 100644 --- a/lib/cpus/cpu-ops.mk +++ b/lib/cpus/cpu-ops.mk @@ -66,6 +66,12 @@ # erratum workaround is enabled by default in hardware. ERRATA_A53_836870 ?=0 +# Flag to apply errata 855873 during reset. This errata applies to all +# revisions of the Cortex A53 CPU, but this firmware workaround only works +# for revisions r0p3 and higher. Earlier revisions are taken care +# of by the rich OS. +ERRATA_A53_855873 ?=0 + # Flag to apply erratum 806969 workaround during reset. This erratum applies # only to revision r0p0 of the Cortex A57 cpu. ERRATA_A57_806969 ?=0 @@ -106,6 +112,10 @@ $(eval $(call assert_boolean,ERRATA_A53_836870)) $(eval $(call add_define,ERRATA_A53_836870)) +# Process ERRATA_A53_855873 flag +$(eval $(call assert_boolean,ERRATA_A53_855873)) +$(eval $(call add_define,ERRATA_A53_855873)) + # Process ERRATA_A57_806969 flag $(eval $(call assert_boolean,ERRATA_A57_806969)) $(eval $(call add_define,ERRATA_A57_806969)) diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 5ba1698..7571582 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -67,7 +67,8 @@ ${JUNO_INTERCONNECT_SOURCES} \ ${JUNO_SECURITY_SOURCES} -# Enable workarounds for selected Cortex-A57 erratas. +# Enable workarounds for selected Cortex-A53 and A57 erratas. +ERRATA_A53_855873 := 1 ERRATA_A57_806969 := 0 ERRATA_A57_813419 := 1 ERRATA_A57_813420 := 1