refactor(errata-abi): workaround platforms non-arm interconnect
The workarounds for these below mentioned errata are not implemented
in EL3, but the flags can be enabled/disabled at a platform level
based on arm/non-arm interconnect IP flag. The ABI helps assist the
Kernel in the process of mitigation for the following errata:
Cortex-A715: erratum 2701951
Neoverse V2: erratum 2719103
Cortex-A710: erratum 2701952
Cortex-X2: erratum 2701952
Neoverse N2: erratum 2728475
Neoverse V1: erratum 2701953
Cortex-A78: erratum 2712571
Cortex-A78AE: erratum 2712574
Cortex-A78C: erratum 2712575
Change-Id: Ie86b7212d731a79e2a0c07649e69234e733cd78d
Signed-off-by: Sona Mathew <sonarebecca.mathew@arm.com>
diff --git a/plat/arm/board/fvp/fvp_cpu_errata.mk b/plat/arm/board/fvp/fvp_cpu_errata.mk
index 0e5954e..009c3c4 100644
--- a/plat/arm/board/fvp/fvp_cpu_errata.mk
+++ b/plat/arm/board/fvp/fvp_cpu_errata.mk
@@ -9,6 +9,7 @@
# for platforms that need to enable errata based on non-arm interconnect IP.
ifeq (${ERRATA_ABI_SUPPORT}, 1)
+ifeq (${ERRATA_NON_ARM_INTERCONNECT}, 1)
ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0)
CORTEX_A78_H_INC := 1
NEOVERSE_N2_H_INC := 1
@@ -19,7 +20,6 @@
CORTEX_A78C_H_INC := 1
CORTEX_X2_H_INC := 1
$(eval $(call add_define, CORTEX_A78_H_INC))
-$(eval $(call add_define, NEOVERSE_N1_H_INC))
$(eval $(call add_define, NEOVERSE_N2_H_INC))
$(eval $(call add_define, NEOVERSE_V1_H_INC))
$(eval $(call add_define, CORTEX_A78_AE_H_INC))
@@ -29,3 +29,4 @@
$(eval $(call add_define, CORTEX_X2_H_INC))
endif
endif
+endif
diff --git a/services/std_svc/errata_abi/cpu_errata_info.h b/services/std_svc/errata_abi/cpu_errata_info.h
index 3790d54..03e80b7 100644
--- a/services/std_svc/errata_abi/cpu_errata_info.h
+++ b/services/std_svc/errata_abi/cpu_errata_info.h
@@ -28,7 +28,7 @@
#define ERRATA_LIST_END (MAX_PLAT_CPU_ERRATA_ENTRIES - 1)
/* Default values for unused memory in the array */
-#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX, false, false}
+#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX}
#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
@@ -41,9 +41,6 @@
unsigned int em_errata_id;
unsigned char em_rxpx_lo; /* lowest revision of errata applicable for the cpu */
unsigned char em_rxpx_hi; /* highest revision of errata applicable for the cpu */
- bool errata_enabled; /* indicate if errata enabled */
- /* flag to indicate if errata query is based out of non-arm interconnect */
- bool non_arm_interconnect;
};
struct em_cpu_list{
diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c
index 3e65252..9dda78d 100644
--- a/services/std_svc/errata_abi/errata_abi_main.c
+++ b/services/std_svc/errata_abi/errata_abi_main.c
@@ -13,7 +13,6 @@
#include <services/errata_abi_svc.h>
#include <smccc_helpers.h>
-
/*
* Global pointer that points to the specific
* structure based on the MIDR part number
@@ -26,7 +25,7 @@
{
.cpu_partnumber = CORTEX_A78_MIDR,
.cpu_errata_list = {
- [0] = {2712571, 0x00, 0x12, ERRATA_A78_2712571, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2712571, 0x00, 0x12},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -36,7 +35,7 @@
{
.cpu_partnumber = CORTEX_A78_AE_MIDR,
.cpu_errata_list = {
- [0] = {2712574, 0x00, 0x02, ERRATA_A78_AE_2712574, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2712574, 0x00, 0x02},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -46,7 +45,7 @@
{
.cpu_partnumber = CORTEX_A78C_MIDR,
.cpu_errata_list = {
- [0] = {2712575, 0x01, 0x02, ERRATA_A78C_2712575, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2712575, 0x01, 0x02},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -56,7 +55,7 @@
{
.cpu_partnumber = NEOVERSE_V1_MIDR,
.cpu_errata_list = {
- [0] = {2701953, 0x00, 0x11, ERRATA_V1_2701953, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2701953, 0x00, 0x11},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -66,7 +65,7 @@
{
.cpu_partnumber = CORTEX_A710_MIDR,
.cpu_errata_list = {
- [0] = {2701952, 0x00, 0x21, ERRATA_A710_2701952, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2701952, 0x00, 0x21},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -76,7 +75,7 @@
{
.cpu_partnumber = NEOVERSE_N2_MIDR,
.cpu_errata_list = {
- [0] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2728475, 0x00, 0x02},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -86,7 +85,7 @@
{
.cpu_partnumber = CORTEX_X2_MIDR,
.cpu_errata_list = {
- [0] = {2701952, 0x00, 0x21, ERRATA_X2_2701952, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2701952, 0x00, 0x21},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -96,7 +95,7 @@
{
.cpu_partnumber = NEOVERSE_V2_MIDR,
.cpu_errata_list = {
- [0] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2719103, 0x00, 0x01},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -106,7 +105,7 @@
{
.cpu_partnumber = CORTEX_A715_MIDR,
.cpu_errata_list = {
- [0] = {2701951, 0x00, 0x11, ERRATA_A715_2701951, ERRATA_NON_ARM_INTERCONNECT},
+ [0] = {2701951, 0x00, 0x11},
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
@@ -114,6 +113,48 @@
};
+#if ERRATA_NON_ARM_INTERCONNECT
+
+/* Check if the errata is enabled for non-arm interconnect */
+static int32_t non_arm_interconnect_errata(uint32_t errata_id, long rev_var)
+{
+ int32_t ret_val = EM_UNKNOWN_ERRATUM;
+
+ /* Determine the number of cpu listed in the cpu list */
+ uint8_t size_cpulist = ARRAY_SIZE(cpu_list);
+
+ /* Read the midr reg to extract cpu, revision and variant info */
+ uint32_t midr_val = read_midr();
+
+ for (uint8_t i = 0U; i < size_cpulist; i++) {
+ cpu_ptr = &cpu_list[i];
+ /*
+ * If the cpu partnumber in the cpu list, matches the midr
+ * part number, check to see if the errata ID matches
+ */
+ if (EXTRACT_PARTNUM(midr_val) == EXTRACT_PARTNUM(cpu_ptr->cpu_partnumber)) {
+
+ struct em_cpu *ptr = NULL;
+
+ for (int j = 0; j < MAX_PLAT_CPU_ERRATA_ENTRIES; j++) {
+ ptr = &cpu_ptr->cpu_errata_list[j];
+ assert(ptr != NULL);
+ if (errata_id == ptr->em_errata_id) {
+ if (RXPX_RANGE(rev_var, ptr->em_rxpx_lo, ptr->em_rxpx_hi)) {
+ ret_val = EM_AFFECTED;
+ break;
+ }
+ ret_val = EM_NOT_AFFECTED;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return ret_val;
+}
+#endif
+
/* Function to check if the errata exists for the specific CPU and rxpx */
int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag)
{
@@ -123,6 +164,14 @@
long rev_var;
ret_val = EM_UNKNOWN_ERRATUM;
+ rev_var = cpu_get_rev_var();
+
+#if ERRATA_NON_ARM_INTERCONNECT
+ ret_val = non_arm_interconnect_errata(errata_id, rev_var);
+ if (ret_val != EM_UNKNOWN_ERRATUM) {
+ return ret_val;
+ }
+#endif
cpu_ops = get_cpu_ops_ptr();
assert(cpu_ops != NULL);
@@ -133,11 +182,9 @@
end = cpu_ops->errata_list_end;
assert(end != NULL);
- rev_var = cpu_get_rev_var();
-
end--; /* point to the last erratum entry of the queried cpu */
- while (entry <= end) {
+ while ((entry <= end) && (ret_val == EM_UNKNOWN_ERRATUM)) {
if (entry->id == errata_id) {
if (entry->check_func(rev_var)) {
if (entry->chosen)