Workaround for Cortex A78 erratum 1951500

Cortex A78 erratum 1951500 is a Cat B erratum that applies to revisions
r0p0, r1p0, and r1p1.  The workaround is to insert a DMB ST before
acquire atomic instructions without release semantics.  This workaround
works on revisions r1p0 and r1p1, in r0p0 there is no workaround.

SDEN can be found here:
https://documentation-service.arm.com/static/5fb66157ca04df4095c1cc2e

Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I47610cee75af6a127ea65edc4d5cffc7e6a2d0a3
This commit is contained in:
johpow01 2020-10-07 15:08:01 -05:00
parent e26c59d2c9
commit 3a2710dcab
4 changed files with 76 additions and 0 deletions

View File

@ -268,6 +268,10 @@ For Cortex-A78, the following errata build flags are defined :
- ``ERRATA_A78_1941498``: This applies errata 1941498 workaround to Cortex-A78
CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU.
- ``ERRATA_A78_1951500``: This applies errata 1951500 workaround to Cortex-A78
CPU. This needs to be enabled for revisions r1p0 and r1p1, r0p0 has the same
issue but there is no workaround for that revision.
For Neoverse N1, the following errata build flags are defined :
- ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1

View File

@ -30,4 +30,7 @@ int errata_needs_reporting(spinlock_t *lock, uint32_t *reported);
#define ERRATA_APPLIES 1
#define ERRATA_MISSING 2
/* Macro to get CPU revision code for checking errata version compatibility. */
#define CPU_REV(r, p) ((r << 4) | p)
#endif /* ERRATA_REPORT_H */

View File

@ -72,6 +72,60 @@ func check_errata_1941498
b cpu_rev_var_ls
endfunc check_errata_1941498
/* --------------------------------------------------
* Errata Workaround for A78 Erratum 1951500.
* This applies to revisions r1p0 and r1p1 of A78.
* The issue also exists in r0p0 but there is no fix
* in that revision.
* Inputs:
* x0: variant[4:7] and revision[0:3] of current cpu.
* Shall clobber: x0-x17
* --------------------------------------------------
*/
func errata_a78_1951500_wa
/* Compare x0 against revisions r1p0 - r1p1 */
mov x17, x30
bl check_errata_1951500
cbz x0, 1f
msr S3_6_c15_c8_0, xzr
ldr x0, =0x10E3900002
msr S3_6_c15_c8_2, x0
ldr x0, =0x10FFF00083
msr S3_6_c15_c8_3, x0
ldr x0, =0x2001003FF
msr S3_6_c15_c8_1, x0
mov x0, #1
msr S3_6_c15_c8_0, x0
ldr x0, =0x10E3800082
msr S3_6_c15_c8_2, x0
ldr x0, =0x10FFF00083
msr S3_6_c15_c8_3, x0
ldr x0, =0x2001003FF
msr S3_6_c15_c8_1, x0
mov x0, #2
msr S3_6_c15_c8_0, x0
ldr x0, =0x10E3800200
msr S3_6_c15_c8_2, x0
ldr x0, =0x10FFF003E0
msr S3_6_c15_c8_3, x0
ldr x0, =0x2001003FF
msr S3_6_c15_c8_1, x0
isb
1:
ret x17
endfunc errata_a78_1951500_wa
func check_errata_1951500
/* Applies to revisions r1p0 and r1p1. */
mov x1, #CPU_REV(1, 0)
mov x2, #CPU_REV(1, 1)
b cpu_rev_var_range
endfunc check_errata_1951500
/* -------------------------------------------------
* The CPU Ops reset function for Cortex-A78
* -------------------------------------------------
@ -91,6 +145,11 @@ func cortex_a78_reset_func
bl errata_a78_1941498_wa
#endif
#if ERRATA_A78_1951500
mov x0, x18
bl errata_a78_1951500_wa
#endif
#if ENABLE_AMU
/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
mrs x0, actlr_el3
@ -147,6 +206,7 @@ func cortex_a78_errata_report
*/
report_errata ERRATA_A78_1688305, cortex_a78, 1688305
report_errata ERRATA_A78_1941498, cortex_a78, 1941498
report_errata ERRATA_A78_1951500, cortex_a78, 1951500
ldp x8, x30, [sp], #16
ret

View File

@ -298,6 +298,11 @@ ERRATA_A78_1688305 ?=0
# to revisions r0p0, r1p0, and r1p1 of the A78 cpu.
ERRATA_A78_1941498 ?=0
# Flag to apply erratum 1951500 workaround during reset. This erratum applies
# to revisions r1p0 and r1p1 of the A78 cpu. The issue is present in r0p0 as
# well but there is no workaround for that revision.
ERRATA_A78_1951500 ?=0
# Flag to apply T32 CLREX workaround during reset. This erratum applies
# only to r0p0 and r1p0 of the Neoverse N1 cpu.
ERRATA_N1_1043202 ?=0
@ -583,6 +588,10 @@ $(eval $(call add_define,ERRATA_A78_1688305))
$(eval $(call assert_boolean,ERRATA_A78_1941498))
$(eval $(call add_define,ERRATA_A78_1941498))
# Process ERRATA_A78_1951500 flag
$(eval $(call assert_boolean,ERRATA_A78_1951500))
$(eval $(call add_define,ERRATA_A78_1951500))
# Process ERRATA_N1_1043202 flag
$(eval $(call assert_boolean,ERRATA_N1_1043202))
$(eval $(call add_define,ERRATA_N1_1043202))