From: Sona Mathew Date: Sat, 19 Nov 2022 00:05:38 +0000 (-0600) Subject: feat(errata_abi): errata management firmware interface X-Git-Tag: baikal/aarch64/sdk5.10~1^2~26^2~4 X-Git-Url: https://git.baikalelectronics.ru/sdk/?a=commitdiff_plain;h=ffea3844c00daf8dee466840a4932cac04b3eb57;p=arm-tf.git feat(errata_abi): errata management firmware interface This patch adds the errata management firmware interface for lower ELs to discover details about CPU erratum. Based on the CPU erratum identifier the interface enables the OS to find the mitigation of an erratum in EL3. The ABI can only be present in a system that is compliant with SMCCCv1.1 or higher. This implements v1.0 of the errata ABI spec. For details on all possible return values, refer the design documentation below: ABI design documentation: https://developer.arm.com/documentation/den0100/1-0?lang=en Signed-off-by: Sona Mathew Change-Id: I70f0e2569cf92e6e02ad82e3e77874546232b89a --- diff --git a/Makefile b/Makefile index 7368ca59b..21d65cfed 100644 --- a/Makefile +++ b/Makefile @@ -1163,6 +1163,7 @@ $(eval $(call assert_booleans,\ SIMICS_BUILD \ FEATURE_DETECTION \ TRNG_SUPPORT \ + ERRATA_ABI_SUPPORT \ CONDITIONAL_CMO \ ))) @@ -1295,6 +1296,7 @@ $(eval $(call add_defines,\ TRUSTED_BOARD_BOOT \ CRYPTO_SUPPORT \ TRNG_SUPPORT \ + ERRATA_ABI_SUPPORT \ USE_COHERENT_MEM \ USE_DEBUGFS \ ARM_IO_IN_DTB \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 9b5cf55bc..f380a493b 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -91,6 +91,10 @@ ifneq (${ENABLE_SPE_FOR_NS},0) BL31_SOURCES += lib/extensions/spe/spe.c endif +ifeq (${ERRATA_ABI_SUPPORT},1) +BL31_SOURCES += services/std_svc/errata_abi/errata_abi_main.c +endif + ifneq (${ENABLE_FEAT_AMU},0) BL31_SOURCES += ${AMU_SOURCES} endif diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk index fb0161c28..ec75d88ac 100644 --- a/bl32/sp_min/sp_min.mk +++ b/bl32/sp_min/sp_min.mk @@ -46,6 +46,10 @@ BL32_SOURCES += services/std_svc/trng/trng_main.c \ services/std_svc/trng/trng_entropy_pool.c endif +ifeq (${ERRATA_ABI_SUPPORT}, 1) +BL32_SOURCES += services/std_svc/errata_abi/errata_abi_main.c +endif + ifneq (${ENABLE_SYS_REG_TRACE_FOR_NS},0) BL32_SOURCES += lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c endif diff --git a/changelog.yaml b/changelog.yaml index c969b2c56..9114dadb5 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -662,6 +662,9 @@ subsections: - title: TRNG scope: trng + - title: ERRATA_ABI + scope: errata_abi + - title: Libraries subsections: diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h index 8678bf3d8..3691497fa 100644 --- a/include/arch/aarch32/arch.h +++ b/include/arch/aarch32/arch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,8 +16,10 @@ #define MIDR_IMPL_SHIFT U(24) #define MIDR_VAR_SHIFT U(20) #define MIDR_VAR_BITS U(4) +#define MIDR_VAR_MASK U(0xf) #define MIDR_REV_SHIFT U(0) #define MIDR_REV_BITS U(4) +#define MIDR_REV_MASK U(0xf) #define MIDR_PN_MASK U(0xfff) #define MIDR_PN_SHIFT U(4) diff --git a/include/services/errata_abi_svc.h b/include/services/errata_abi_svc.h new file mode 100644 index 000000000..12500661b --- /dev/null +++ b/include/services/errata_abi_svc.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ERRATA_ABI_SVC_H +#define ERRATA_ABI_SVC_H + +#include + +#define ARM_EM_VERSION U(0x840000F0) +#define ARM_EM_FEATURES U(0x840000F1) +#define ARM_EM_CPU_ERRATUM_FEATURES U(0x840000F2) + +/* EM version numbers */ +#define EM_VERSION_MAJOR (0x1) +#define EM_VERSION_MINOR (0x0) + +/* EM CPU_ERRATUM_FEATURES return codes */ +#define EM_HIGHER_EL_MITIGATION (3) +#define EM_NOT_AFFECTED (2) +#define EM_AFFECTED (1) +#define EM_SUCCESS (0) +#define EM_NOT_SUPPORTED (-1) +#define EM_INVALID_PARAMETERS (-2) +#define EM_UNKNOWN_ERRATUM (-3) + +#if ERRATA_ABI_SUPPORT +bool is_errata_fid(uint32_t smc_fid); +#else +static inline bool is_errata_fid(uint32_t smc_fid) +{ + return false; +} +#endif /* ERRATA_ABI_SUPPORT */ +uintptr_t errata_abi_smc_handler( + uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags +); +#endif /* ERRATA_ABI_SVC_H */ + diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 8ec16fa60..0916d1d4c 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -291,6 +291,9 @@ SDEI_SUPPORT := 0 # True Random Number firmware Interface support TRNG_SUPPORT := 0 +# Check to see if Errata ABI is supported +ERRATA_ABI_SUPPORT := 0 + # SMCCC PCI support SMC_PCI_SUPPORT := 0 diff --git a/services/std_svc/errata_abi/cpu_errata_info.h b/services/std_svc/errata_abi/cpu_errata_info.h new file mode 100644 index 000000000..168bc9556 --- /dev/null +++ b/services/std_svc/errata_abi/cpu_errata_info.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ERRATA_CPUSPEC_H +#define ERRATA_CPUSPEC_H + +#include +#include + +#if __aarch64__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#define MAX_ERRATA_ENTRIES 15 + +#define ERRATA_LIST_END (MAX_ERRATA_ENTRIES - 1) + +#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX, false} + +#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + +#define RXPX_RANGE(x, y, z) (((x >= y) && (x <= z)) ? true : false) + +/* + * CPU specific values for errata handling + */ + +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 */ +}; + +struct em_cpu_list{ + /* field to hold cpu specific part number defined in midr reg */ + unsigned long cpu_partnumber; + struct em_cpu cpu_errata_list[MAX_ERRATA_ENTRIES]; +}; + +int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag); +#endif /* ERRATA_CPUSPEC_H */ diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c new file mode 100644 index 000000000..80fc39a56 --- /dev/null +++ b/services/std_svc/errata_abi/errata_abi_main.c @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "cpu_errata_info.h" +#include +#include +#include +#include + +/* + * Global pointer that points to the specific + * structure based on the MIDR part number + */ +struct em_cpu_list *cpu_ptr; + +extern uint8_t cpu_get_rev_var(void); + +/* Structure array that holds CPU specific errata information */ +struct em_cpu_list cpu_list[] = { +#if CORTEX_A9_H_INC +{ + .cpu_partnumber = CORTEX_A9_MIDR, + .cpu_errata_list = { + [0] = {794073, 0x00, 0xFF, ERRATA_A9_794073}, + [1 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A9_H_INC */ + +#if CORTEX_A15_H_INC +{ + .cpu_partnumber = CORTEX_A15_MIDR, + .cpu_errata_list = { + [0] = {816470, 0x30, 0xFF, ERRATA_A15_816470}, + [1] = {827671, 0x30, 0xFF, ERRATA_A15_827671}, + [2 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A15_H_INC */ + +#if CORTEX_A17_H_INC +{ + .cpu_partnumber = CORTEX_A17_MIDR, + .cpu_errata_list = { + [0] = {852421, 0x00, 0x12, ERRATA_A17_852421}, + [1] = {852423, 0x00, 0x12, ERRATA_A17_852423}, + [2 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A17_H_INC */ + +#if CORTEX_A35_H_INC +{ + .cpu_partnumber = CORTEX_A35_MIDR, + .cpu_errata_list = { + [0] = {855472, 0x00, 0x00, ERRATA_A35_855472}, + [1 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A35_H_INC */ + +#if CORTEX_A53_H_INC +{ + .cpu_partnumber = CORTEX_A53_MIDR, + .cpu_errata_list = { + [0] = {819472, 0x00, 0x01, ERRATA_A53_819472}, + [1] = {824069, 0x00, 0x02, ERRATA_A53_824069}, + [2] = {826319, 0x00, 0x02, ERRATA_A53_826319}, + [3] = {827319, 0x00, 0x02, ERRATA_A53_827319}, + [4] = {835769, 0x00, 0x04, ERRATA_A53_835769}, + [5] = {836870, 0x00, 0x03, ERRATA_A53_836870}, + [6] = {843419, 0x00, 0x04, ERRATA_A53_843419}, + [7] = {855873, 0x03, 0xFF, ERRATA_A53_855873}, + [8] = {1530924, 0x00, 0xFF, ERRATA_A53_1530924}, + [9 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A53_H_INC */ + +#if CORTEX_A55_H_INC +{ + .cpu_partnumber = CORTEX_A55_MIDR, + .cpu_errata_list = { + [0] = {768277, 0x00, 0x00, ERRATA_A55_768277}, + [1] = {778703, 0x00, 0x00, ERRATA_A55_778703}, + [2] = {798797, 0x00, 0x00, ERRATA_A55_798797}, + [3] = {846532, 0x00, 0x01, ERRATA_A55_846532}, + [4] = {903758, 0x00, 0x01, ERRATA_A55_903758}, + [5] = {1221012, 0x00, 0x10, ERRATA_A55_1221012}, + [6] = {1530923, 0x00, 0xFF, ERRATA_A55_1530923}, + [7 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A55_H_INC */ + +#if CORTEX_A57_H_INC +{ + .cpu_partnumber = CORTEX_A57_MIDR, + .cpu_errata_list = { + [0] = {806969, 0x00, 0x00, ERRATA_A57_806969}, + [1] = {813419, 0x00, 0x00, ERRATA_A57_813419}, + [2] = {813420, 0x00, 0x00, ERRATA_A57_813420}, + [3] = {814670, 0x00, 0x00, ERRATA_A57_814670}, + [4] = {817169, 0x00, 0x01, ERRATA_A57_817169}, + [5] = {826974, 0x00, 0x11, ERRATA_A57_826974}, + [6] = {826977, 0x00, 0x11, ERRATA_A57_826977}, + [7] = {828024, 0x00, 0x11, ERRATA_A57_828024}, + [8] = {829520, 0x00, 0x12, ERRATA_A57_829520}, + [9] = {833471, 0x00, 0x12, ERRATA_A57_833471}, + [10] = {859972, 0x00, 0x13, ERRATA_A57_859972}, + [11] = {1319537, 0x00, 0xFF, ERRATA_A57_1319537}, + [12 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A57_H_INC */ + +#if CORTEX_A72_H_INC +{ + .cpu_partnumber = CORTEX_A72_MIDR, + .cpu_errata_list = { + [0] = {859971, 0x00, 0x03, ERRATA_A72_859971}, + [1] = {1319367, 0x00, 0xFF, ERRATA_A72_1319367}, + [2 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A72_H_INC */ + +#if CORTEX_A73_H_INC +{ + .cpu_partnumber = CORTEX_A73_MIDR, + .cpu_errata_list = { + [0] = {852427, 0x00, 0x00, ERRATA_A73_852427}, + [1] = {855423, 0x00, 0x01, ERRATA_A73_855423}, + [2 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A73_H_INC */ + +#if CORTEX_A75_H_INC +{ + .cpu_partnumber = CORTEX_A75_MIDR, + .cpu_errata_list = { + [0] = {764081, 0x00, 0x00, ERRATA_A75_764081}, + [1] = {790748, 0x00, 0x00, ERRATA_A75_790748}, + [2 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A75_H_INC */ + +#if CORTEX_A76_H_INC +{ + .cpu_partnumber = CORTEX_A76_MIDR, + .cpu_errata_list = { + [0] = {1073348, 0x00, 0x10, ERRATA_A76_1073348}, + [1] = {1130799, 0x00, 0x20, ERRATA_A76_1130799}, + [2] = {1165522, 0x00, 0xFF, ERRATA_A76_1165522}, + [3] = {1220197, 0x00, 0x20, ERRATA_A76_1220197}, + [4] = {1257314, 0x00, 0x30, ERRATA_A76_1257314}, + [5] = {1262606, 0x00, 0x30, ERRATA_A76_1262606}, + [6] = {1262888, 0x00, 0x30, ERRATA_A76_1262888}, + [7] = {1275112, 0x00, 0x30, ERRATA_A76_1275112}, + [8] = {1791580, 0x00, 0x40, ERRATA_A76_1791580}, + [9] = {1868343, 0x00, 0x40, ERRATA_A76_1868343}, + [10] = {1946160, 0x30, 0x41, ERRATA_A76_1946160}, + [11 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A76_H_INC */ + +#if CORTEX_A77_H_INC +{ + .cpu_partnumber = CORTEX_A77_MIDR, + .cpu_errata_list = { + [0] = {1508412, 0x00, 0x10, ERRATA_A77_1508412}, + [1] = {1791578, 0x00, 0x11, ERRATA_A77_1791578}, + [2] = {1800714, 0x00, 0x11, ERRATA_A77_1800714}, + [3] = {1925769, 0x00, 0x11, ERRATA_A77_1925769}, + [4] = {1946167, 0x00, 0x11, ERRATA_A77_1946167}, + [5] = {2356587, 0x00, 0x11, ERRATA_A77_2356587}, + [6] = {2743100, 0x00, 0x11, ERRATA_A77_2743100}, + [7 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A77_H_INC */ + +#if CORTEX_A78_H_INC +{ + .cpu_partnumber = CORTEX_A78_MIDR, + .cpu_errata_list = { + [0] = {1688305, 0x00, 0x10, ERRATA_A78_1688305}, + [1] = {1821534, 0x00, 0x10, ERRATA_A78_1821534}, + [2] = {1941498, 0x00, 0x11, ERRATA_A78_1941498}, + [3] = {1951500, 0x10, 0x11, ERRATA_A78_1951500}, + [4] = {1952683, 0x00, 0x00, ERRATA_A78_1952683}, + [5] = {2132060, 0x00, 0x12, ERRATA_A78_2132060}, + [6] = {2242635, 0x10, 0x12, ERRATA_A78_2242635}, + [7] = {2376745, 0x00, 0x12, ERRATA_A78_2376745}, + [8] = {2395406, 0x00, 0x12, ERRATA_A78_2395406}, + [9] = {2742426, 0x00, 0x12, ERRATA_A78_2742426}, + [10] = {2772019, 0x00, 0x12, ERRATA_A78_2772019}, + [11] = {2779479, 0x00, 0x12, ERRATA_A78_2779479}, + [12 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A78_H_INC */ + +#if CORTEX_A78_AE_H_INC +{ + .cpu_partnumber = CORTEX_A78_AE_MIDR, + .cpu_errata_list = { + [0] = {1941500, 0x00, 0x01, ERRATA_A78_AE_1941500}, + [1] = {1951502, 0x00, 0x01, ERRATA_A78_AE_1951502}, + [2] = {2376748, 0x00, 0x01, ERRATA_A78_AE_2376748}, + [3] = {2395408, 0x00, 0x01, ERRATA_A78_AE_2395408}, + [4 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A78_AE_H_INC */ + +#if CORTEX_A78C_H_INC +{ + .cpu_partnumber = CORTEX_A78C_MIDR, + .cpu_errata_list = { + [0] = {2132064, 0x01, 0x02, ERRATA_A78C_2132064}, + [1] = {2242638, 0x01, 0x02, ERRATA_A78C_2242638}, + [2] = {2376749, 0x01, 0x02, ERRATA_A78C_2376749}, + [3] = {2395411, 0x01, 0x02, ERRATA_A78C_2395411}, + [4] = {2772121, 0x00, 0x02, ERRATA_A78C_2772121}, + [5] = {2779484, 0x01, 0x02, ERRATA_A78C_2779484}, + [6 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A78C_H_INC */ + +#if CORTEX_X1_H_INC +{ + .cpu_partnumber = CORTEX_X1_MIDR, + .cpu_errata_list = { + [0] = {1688305, 0x00, 0x10, ERRATA_X1_1688305}, + [1] = {1821534, 0x00, 0x10, ERRATA_X1_1821534}, + [2] = {1827429, 0x00, 0x10, ERRATA_X1_1827429}, + [3 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_X1_H_INC */ + +#if NEOVERSE_N1_H_INC +{ + .cpu_partnumber = NEOVERSE_N1_MIDR, + .cpu_errata_list = { + [0] = {1073348, 0x00, 0x10, ERRATA_N1_1073348}, + [1] = {1130799, 0x00, 0x20, ERRATA_N1_1130799}, + [2] = {1165347, 0x00, 0x20, ERRATA_N1_1165347}, + [3] = {1207823, 0x00, 0x20, ERRATA_N1_1207823}, + [4] = {1220197, 0x00, 0x20, ERRATA_N1_1220197}, + [5] = {1257314, 0x00, 0x30, ERRATA_N1_1257314}, + [6] = {1262606, 0x00, 0x30, ERRATA_N1_1262606}, + [7] = {1262888, 0x00, 0x30, ERRATA_N1_1262888}, + [8] = {1275112, 0x00, 0x30, ERRATA_N1_1275112}, + [9] = {1315703, 0x00, 0x30, ERRATA_N1_1315703}, + [10] = {1542419, 0x30, 0x40, ERRATA_N1_1542419}, + [11] = {1868343, 0x00, 0x40, ERRATA_N1_1868343}, + [12] = {1946160, 0x30, 0x41, ERRATA_N1_1946160}, + [13] = {2743102, 0x00, 0x41, ERRATA_N1_2743102}, + [14 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* NEOVERSE_N1_H_INC */ + +#if NEOVERSE_V1_H_INC +{ + .cpu_partnumber = NEOVERSE_V1_MIDR, + .cpu_errata_list = { + [0] = {1618635, 0x00, 0x0F, ERRATA_V1_1618635}, + [1] = {1774420, 0x00, 0x10, ERRATA_V1_1774420}, + [2] = {1791573, 0x00, 0x10, ERRATA_V1_1791573}, + [3] = {1852267, 0x00, 0x10, ERRATA_V1_1852267}, + [4] = {1925756, 0x00, 0x11, ERRATA_V1_1925756}, + [5] = {1940577, 0x10, 0x11, ERRATA_V1_1940577}, + [6] = {1966096, 0x10, 0x11, ERRATA_V1_1966096}, + [7] = {2108267, 0x00, 0x11, ERRATA_V1_2108267}, + [8] = {2139242, 0x00, 0x11, ERRATA_V1_2139242}, + [9] = {2216392, 0x10, 0x11, ERRATA_V1_2216392}, + [10] = {2294912, 0x00, 0x11, ERRATA_V1_2294912}, + [11] = {2372203, 0x00, 0x11, ERRATA_V1_2372203}, + [12] = {2743093, 0x00, 0x12, ERRATA_V1_2743093}, + [13] = {2779461, 0x00, 0x12, ERRATA_V1_2779461}, + [14 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* NEOVERSE_V1_H_INC */ + +#if CORTEX_A710_H_INC +{ + .cpu_partnumber = CORTEX_A710_MIDR, + .cpu_errata_list = { + [0] = {1987031, 0x00, 0x20, ERRATA_A710_1987031}, + [1] = {2008768, 0x00, 0x20, ERRATA_A710_2008768}, + [2] = {2017096, 0x00, 0x20, ERRATA_A710_2017096}, + [3] = {2055002, 0x10, 0x20, ERRATA_A710_2055002}, + [4] = {2058056, 0x00, 0x10, ERRATA_A710_2058056}, + [5] = {2081180, 0x00, 0x20, ERRATA_A710_2081180}, + [6] = {2083908, 0x20, 0x20, ERRATA_A710_2083908}, + [7] = {2136059, 0x00, 0x20, ERRATA_A710_2136059}, + [8] = {2147715, 0x20, 0x20, ERRATA_A710_2147715}, + [9] = {2216384, 0x00, 0x20, ERRATA_A710_2216384}, + [10] = {2267065, 0x00, 0x20, ERRATA_A710_2267065}, + [11] = {2282622, 0x00, 0x21, ERRATA_A710_2282622}, + [12] = {2291219, 0x00, 0x20, ERRATA_A710_2291219}, + [13] = {2371105, 0x00, 0x20, ERRATA_A710_2371105}, + [14] = {2768515, 0x00, 0x21, ERRATA_A710_2768515} + } +}, +#endif /* CORTEX_A710_H_INC */ + +#if NEOVERSE_N2_H_INC +{ + .cpu_partnumber = NEOVERSE_N2_MIDR, + .cpu_errata_list = { + [0] = {2002655, 0x00, 0x00, ERRATA_N2_2002655}, + [1] = {2025414, 0x00, 0x00, ERRATA_N2_2025414}, + [2] = {2067956, 0x00, 0x00, ERRATA_N2_2067956}, + [3] = {2138953, 0x00, 0x00, ERRATA_N2_2138953}, + [4] = {2138956, 0x00, 0x00, ERRATA_N2_2138956}, + [5] = {2138958, 0x00, 0x00, ERRATA_N2_2138958}, + [6] = {2189731, 0x00, 0x00, ERRATA_N2_2189731}, + [7] = {2242400, 0x00, 0x00, ERRATA_N2_2242400}, + [8] = {2242415, 0x00, 0x00, ERRATA_N2_2242415}, + [9] = {2280757, 0x00, 0x00, ERRATA_N2_2280757}, + [10] = {2326639, 0x00, 0x00, ERRATA_N2_2326639}, + [11] = {2376738, 0x00, 0x00, ERRATA_N2_2376738}, + [12] = {2388450, 0x00, 0x00, ERRATA_N2_2388450}, + [13] = {2743089, 0x00, 0x02, ERRATA_N2_2743089}, + [14 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* NEOVERSE_N2_H_INC */ + +#if CORTEX_X2_H_INC +{ + .cpu_partnumber = CORTEX_X2_MIDR, + .cpu_errata_list = { + [0] = {2002765, 0x00, 0x20, ERRATA_X2_2002765}, + [1] = {2017096, 0x00, 0x20, ERRATA_X2_2017096}, + [2] = {2058056, 0x00, 0x20, ERRATA_X2_2058056}, + [3] = {2081180, 0x00, 0x20, ERRATA_X2_2081180}, + [4] = {2083908, 0x00, 0x20, ERRATA_X2_2083908}, + [5] = {2147715, 0x20, 0x20, ERRATA_X2_2147715}, + [6] = {2216384, 0x00, 0x20, ERRATA_X2_2216384}, + [7] = {2282622, 0x00, 0x21, ERRATA_X2_2282622}, + [8] = {2371105, 0x00, 0x21, ERRATA_X2_2371105}, + [9] = {2768515, 0x00, 0x21, ERRATA_X2_2768515}, + [10 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_X2_H_INC */ + +#if CORTEX_A510_H_INC +{ + .cpu_partnumber = CORTEX_A510_MIDR, + .cpu_errata_list = { + [0] = {1922240, 0x00, 0x00, ERRATA_A510_1922240}, + [1] = {2041909, 0x02, 0x02, ERRATA_A510_2041909}, + [2] = {2042739, 0x00, 0x02, ERRATA_A510_2042739}, + [3] = {2172148, 0x00, 0x10, ERRATA_A510_2172148}, + [4] = {2218950, 0x00, 0x10, ERRATA_A510_2218950}, + [5] = {2250311, 0x00, 0x10, ERRATA_A510_2250311}, + [6] = {2288014, 0x00, 0x10, ERRATA_A510_2288014}, + [7] = {2347730, 0x00, 0x11, ERRATA_A510_2347730}, + [8] = {2371937, 0x00, 0x11, ERRATA_A510_2371937}, + [9] = {2666669, 0x00, 0x11, ERRATA_A510_2666669}, + [10] = {2684597, 0x00, 0x12, ERRATA_A510_2684597}, + [11 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A510_H_INC */ +}; + +/* + * Function to do binary search and check for the specific errata ID + * in the array of structures specific to the cpu identified. + */ +int32_t binary_search(struct em_cpu_list *ptr, uint32_t erratum_id, + uint8_t rxpx_val) +{ + int low_index = 0U, mid_index = 0U; + + int high_index = MAX_ERRATA_ENTRIES - 1; + + while (low_index <= high_index) { + mid_index = (low_index + high_index) / 2; + if (erratum_id < ptr->cpu_errata_list[mid_index].em_errata_id) { + high_index = mid_index - 1; + } else if (erratum_id > ptr->cpu_errata_list[mid_index].em_errata_id) { + low_index = mid_index + 1; + } else if (erratum_id == ptr->cpu_errata_list[mid_index].em_errata_id) { + + if (RXPX_RANGE(rxpx_val, ptr->cpu_errata_list[mid_index].em_rxpx_lo, \ + ptr->cpu_errata_list[mid_index].em_rxpx_hi)) { + if (ptr->cpu_errata_list[mid_index].errata_enabled) { + return EM_HIGHER_EL_MITIGATION; + } + return EM_AFFECTED; + } + return EM_NOT_AFFECTED; + } + } + /* no matching errata ID */ + return EM_UNKNOWN_ERRATUM; +} + +/* 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) +{ + /* + * Read MIDR value and extract the revision, variant and partnumber + */ + static uint32_t midr_val, cpu_partnum; + static uint8_t cpu_rxpx_val; + 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 */ + midr_val = read_midr(); + + /* Extract revision and variant from the MIDR register */ + cpu_rxpx_val = cpu_get_rev_var(); + + /* Extract the cpu partnumber and check if the cpu is in the cpu list */ + cpu_partnum = EXTRACT_PARTNUM(midr_val); + + for (uint8_t i = 0; i < size_cpulist; i++) { + cpu_ptr = &cpu_list[i]; + uint16_t partnum_extracted = EXTRACT_PARTNUM(cpu_ptr->cpu_partnumber); + + if (partnum_extracted == cpu_partnum) { + /* + * If the midr value is in the cpu list, binary search + * for the errata ID and specific revision in the list. + */ + ret_val = binary_search(cpu_ptr, errata_id, cpu_rxpx_val); + break; + } + } + return ret_val; +} + +/* Predicate indicating that a function id is part of EM_ABI */ +bool is_errata_fid(uint32_t smc_fid) +{ + return ((smc_fid == ARM_EM_VERSION) || + (smc_fid == ARM_EM_FEATURES) || + (smc_fid == ARM_EM_CPU_ERRATUM_FEATURES)); + +} + +bool validate_spsr_mode(void) +{ + /* In AArch64, if the caller is EL1, return true */ + + #if __aarch64__ + if (GET_EL(read_spsr_el3()) == MODE_EL1) { + return true; + } + return false; + #else + + /* In AArch32, if in system/svc mode, return true */ + uint8_t read_el_state = GET_M32(read_spsr()); + + if ((read_el_state == (MODE32_svc)) || (read_el_state == MODE32_sys)) { + return true; + } + return false; + #endif /* __aarch64__ */ +} + +uintptr_t errata_abi_smc_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, u_register_t x4, + void *cookie, void *handle, u_register_t flags) +{ + int32_t ret_id = EM_UNKNOWN_ERRATUM; + + switch (smc_fid) { + case ARM_EM_VERSION: + SMC_RET1(handle, MAKE_SMCCC_VERSION( + EM_VERSION_MAJOR, EM_VERSION_MINOR + )); + break; /* unreachable */ + case ARM_EM_FEATURES: + if (is_errata_fid((uint32_t)x1)) { + SMC_RET1(handle, EM_SUCCESS); + } + + SMC_RET1(handle, EM_NOT_SUPPORTED); + break; /* unreachable */ + case ARM_EM_CPU_ERRATUM_FEATURES: + + /* + * If the forward flag is greater than zero and the calling EL + * is EL1 in AArch64 or in system mode or svc mode in case of AArch32, + * return Invalid Parameters. + */ + if (((uint32_t)x2 != 0) && (validate_spsr_mode())) { + SMC_RET1(handle, EM_INVALID_PARAMETERS); + } + ret_id = verify_errata_implemented((uint32_t)x1, (uint32_t)x2); + SMC_RET1(handle, ret_id); + break; /* unreachable */ + default: + { + WARN("Unimplemented Errata ABI Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, EM_UNKNOWN_ERRATUM); + break; /* unreachable */ + } + } +} diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c index 2884a3b9e..e782d09d2 100644 --- a/services/std_svc/std_svc_setup.c +++ b/services/std_svc/std_svc_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -177,6 +178,13 @@ static uintptr_t std_svc_smc_handler(uint32_t smc_fid, } #endif /* TRNG_SUPPORT */ +#if ERRATA_ABI_SUPPORT + if (is_errata_fid(smc_fid)) { + return errata_abi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif /* ERRATA_ABI_SUPPORT */ + #if ENABLE_RME if (is_rmmd_el3_fid(smc_fid)) {