From aceb9c9e54a02a8aef6dc808081c5feb296e7c8e Mon Sep 17 00:00:00 2001 From: Sona Mathew Date: Tue, 26 Sep 2023 17:49:51 -0500 Subject: [PATCH] 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 --- plat/arm/board/fvp/fvp_cpu_errata.mk | 3 +- services/std_svc/errata_abi/cpu_errata_info.h | 5 +- services/std_svc/errata_abi/errata_abi_main.c | 73 +++++++++++++++---- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/plat/arm/board/fvp/fvp_cpu_errata.mk b/plat/arm/board/fvp/fvp_cpu_errata.mk index 0e5954e98..009c3c45f 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_A715_H_INC := 1 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_A78C_H_INC)) $(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 3790d54a3..03e80b7ef 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 @@ struct em_cpu{ 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 3e652524e..9dda78d33 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 #include - /* * Global pointer that points to the specific * structure based on the MIDR part number @@ -26,7 +25,7 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { { .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 @@ struct em_cpu_list cpu_list[] = { }; +#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 @@ int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag) 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 @@ int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag) 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)