fix(errata-abi): add support for handling split workarounds

Certain erratum workarounds like Neoverse N1 1542419, need a part
of their mitigation done in EL3 and the rest in lower EL. But currently
such workarounds return HIGHER_EL_MITIGATION which indicates that the
erratum has already been mitigated by a higher EL(EL3 in this case)
which causes the lower EL to not apply it's part of the mitigation.

This patch fixes this issue by adding support for split workarounds
so that on certain errata we return AFFECTED even though EL3 has
applied it's workaround. This is done by reusing the chosen field of
erratum_entry structure into a bitfield that has two bitfields -
Bit 0 indicates that the erratum has been enabled in build,
Bit 1 indicates that the erratum is a split workaround and should
return AFFECTED instead of HIGHER_EL_MITIGATION.

SDEN documentation:
https://developer.arm.com/documentation/SDEN885747/latest

Signed-off-by: Arvind Ram Prakash <arvind.ramprakash@arm.com>
Change-Id: Iec94d665b5f55609507a219a7d1771eb75e7f4a7
This commit is contained in:
Arvind Ram Prakash 2025-02-24 17:22:01 -06:00
parent f2d12fce88
commit bbff267b6f
4 changed files with 33 additions and 9 deletions

View file

@ -235,10 +235,11 @@
* _chosen:
* Compile time flag on whether the erratum is included
*
* _apply_at_reset:
* Whether the erratum should be automatically applied at reset
* _split_wa:
* Flag that indicates whether an erratum has split workaround or not.
* Default value is 0.
*/
.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req
.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _split_wa=0
#if REPORT_ERRATA || ERRATA_ABI_SUPPORT
.pushsection .rodata.errata_entries
.align 3
@ -250,7 +251,8 @@
/* Will fit CVEs with up to 10 character in the ID field */
.word \_id
.hword \_cve
.byte \_chosen
/* bit magic that appends chosen field based on _split_wa */
.byte ((\_chosen * 0b11) & ((\_split_wa << 1) | \_chosen))
.byte 0x0 /* alignment */
.popsection
#endif
@ -276,14 +278,20 @@
* _chosen:
* Compile time flag on whether the erratum is included
*
* _split_wa:
* Flag that indicates whether an erratum has split workaround or not.
* Default value is 0.
*
* in body:
* clobber x0 to x7 (please only use those)
* argument x7 - cpu_rev_var
*
* _wa clobbers: x0-x8 (PCS compliant)
*/
.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req
add_erratum_entry \_cpu, \_cve, \_id, \_chosen
.macro workaround_reset_start _cpu:req, _cve:req, _id:req, \
_chosen:req, _split_wa=0
add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_split_wa
.if \_chosen
/* put errata directly into the reset function */

View file

@ -42,6 +42,12 @@ struct erratum_entry {
uint32_t id;
/* Denote CVEs with their year or errata with 0 */
uint16_t cve;
/*
* a bitfield:
* bit 0 - denotes if the erratum is enabled in build.
* bit 1 - denotes if the erratum workaround is split and
* also needs to be implemented at a lower EL.
*/
uint8_t chosen;
uint8_t _alignment;
} __packed;
@ -96,4 +102,11 @@ bool errata_ich_vmcr_el2_applies(void);
/* Macro to get CPU revision code for checking errata version compatibility. */
#define CPU_REV(r, p) ((r << 4) | p)
/* Used for errata that have split workaround */
#define SPLIT_WA 1
/* chosen bitfield entries */
#define WA_ENABLED_MASK BIT(0)
#define SPLIT_WA_MASK BIT(1)
#endif /* ERRATA_H */

View file

@ -116,7 +116,7 @@ workaround_reset_end neoverse_n1, ERRATUM(1315703)
check_erratum_ls neoverse_n1, ERRATUM(1315703), CPU_REV(3, 0)
workaround_reset_start neoverse_n1, ERRATUM(1542419), ERRATA_N1_1542419
workaround_reset_start neoverse_n1, ERRATUM(1542419), ERRATA_N1_1542419, SPLIT_WA
/* Apply instruction patching sequence */
ldr x0, =0x0
msr CPUPSELR_EL3, x0

View file

@ -197,8 +197,11 @@ int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag)
while ((entry <= end) && (ret_val == EM_UNKNOWN_ERRATUM)) {
if (entry->id == errata_id) {
if (entry->check_func(rev_var)) {
if (entry->chosen)
return EM_HIGHER_EL_MITIGATION;
if (entry->chosen & WA_ENABLED_MASK)
if (entry->chosen & SPLIT_WA_MASK)
return EM_AFFECTED;
else
return EM_HIGHER_EL_MITIGATION;
else
return EM_AFFECTED;
}