diff options
34 files changed, 1059 insertions, 235 deletions
@@ -922,11 +922,20 @@ ifeq (${ENABLE_RME},1) endif endif +ifneq (${ENABLE_SME_FOR_NS},0) + ifeq (${ENABLE_SVE_FOR_NS},0) + $(error "ENABLE_SME_FOR_NS requires ENABLE_SVE_FOR_NS") + endif +endif + # Secure SME/SVE requires the non-secure component as well ifeq (${ENABLE_SME_FOR_SWD},1) ifeq (${ENABLE_SME_FOR_NS},0) $(error "ENABLE_SME_FOR_SWD requires ENABLE_SME_FOR_NS") endif + ifeq (${ENABLE_SVE_FOR_SWD},0) + $(error "ENABLE_SME_FOR_SWD requires ENABLE_SVE_FOR_SWD") + endif endif ifeq (${ENABLE_SVE_FOR_SWD},1) ifeq (${ENABLE_SVE_FOR_NS},0) @@ -1174,6 +1183,8 @@ $(eval $(call assert_booleans,\ SIMICS_BUILD \ FEATURE_DETECTION \ TRNG_SUPPORT \ + ERRATA_ABI_SUPPORT \ + ERRATA_NON_ARM_INTERCONNECT \ CONDITIONAL_CMO \ RAS_FFH_SUPPORT \ ))) @@ -1308,6 +1319,8 @@ $(eval $(call add_defines,\ TRUSTED_BOARD_BOOT \ CRYPTO_SUPPORT \ TRNG_SUPPORT \ + ERRATA_ABI_SUPPORT \ + ERRATA_NON_ARM_INTERCONNECT \ USE_COHERENT_MEM \ USE_DEBUGFS \ ARM_IO_IN_DTB \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 9b5cf55bc..d7c9a521d 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 @@ -101,12 +105,10 @@ endif ifneq (${ENABLE_SME_FOR_NS},0) BL31_SOURCES += lib/extensions/sme/sme.c -BL31_SOURCES += lib/extensions/sve/sve.c -else +endif ifneq (${ENABLE_SVE_FOR_NS},0) BL31_SOURCES += lib/extensions/sve/sve.c endif -endif ifneq (${ENABLE_MPAM_FOR_LOWER_ELS},0) BL31_SOURCES += lib/extensions/mpam/mpam.c 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/docs/about/release-information.rst b/docs/about/release-information.rst index cd52460b9..0ba0a7aa0 100644 --- a/docs/about/release-information.rst +++ b/docs/about/release-information.rst @@ -67,7 +67,7 @@ after which it will be removed. | | Date | after | | | | | Release | | +================================+=============+=========+=========================================================+ -| plat_convert_pk() function | Nov'22 | 2.9 | Platform conversion to manage specific PK hash | +| None at this time | | | | +--------------------------------+-------------+---------+---------------------------------------------------------+ Removal of Deprecated Drivers @@ -82,8 +82,6 @@ after which it will be removed. | | Date | after | | | | | Release | | +================================+=============+=========+=========================================================+ -| io_dummy driver | Nov'22 | 2.9 | No more used by any upstream platform | -+--------------------------------+-------------+---------+---------------------------------------------------------+ | CryptoCell-712 | 2.9 | 3.0 | No longer maintained. | +--------------------------------+-------------+---------+---------------------------------------------------------+ | CryptoCell-713 | 2.9 | 3.0 | No longer maintained. | diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst index 0f1f92aea..758d62be9 100644 --- a/docs/design/cpu-specific-build-macros.rst +++ b/docs/design/cpu-specific-build-macros.rst @@ -317,6 +317,11 @@ For Cortex-A78, the following errata build flags are defined : CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2, and it is still open. +- ``ERRATA_A78_2712571``: This applies erratum 2712571 workaround to Cortex-A78 + CPU, this erratum affects system configurations that do not use an ARM + interconnect IP. This needs to be enabled for revisions r0p0, r1p0, r1p1 + and r1p2 and it is still open. + - ``ERRATA_A78_2742426``: This applies erratum 2742426 workaround to Cortex-A78 CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1 and r1p2 and it is still open. @@ -347,6 +352,11 @@ For Cortex-A78 AE, the following errata build flags are defined : Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is still open. +- ``ERRATA_A78_AE_2712574`` : This applies erratum 2712574 workaround to + Cortex-A78 AE CPU. This erratum affects system configurations that do not use + an ARM interconnect IP. This needs to be enabled for revisions r0p0, r0p1 and + r0p2. This erratum is still open. + For Cortex-A78C, the following errata build flags are defined : - ``ERRATA_A78C_1827430`` : This applies errata 1827430 workaround to @@ -373,6 +383,11 @@ For Cortex-A78C, the following errata build flags are defined : Cortex-A78C CPU. This needs to be enabled for revisions r0p1 and r0p2. This erratum is still open. +- ``ERRATA_A78C_2712575`` : This applies erratum 2712575 workaround to + Cortex-A78C CPU, this erratum affects system configurations that do not use + an ARM interconnect IP. This needs to be enabled for revisions r0p1 and r0p2 + and is still open. + - ``ERRATA_A78C_2772121`` : This applies errata 2772121 workaround to Cortex-A78C CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2. This erratum is still open. @@ -488,6 +503,11 @@ For Neoverse V1, the following errata build flags are defined : CPU. This needs to be enabled for revisions r0p0, r1p0 and r1p1 of the CPU. It is still open. +- ``ERRATA_V1_2701953``: This applies erratum 2701953 workaround to Neoverse-V1 + CPU, this erratum affects system configurations that do not use an ARM + interconnect IP. This needs to be enabled for revisions r0p0, r1p0 and r1p1. + It has been fixed in r1p2. + - ``ERRATA_V1_2743093``: This applies errata 2743093 workaround to Neoverse-V1 CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1 and r1p2 of the CPU. It is still open. @@ -500,6 +520,13 @@ For Neoverse V1, the following errata build flags are defined : CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, r1p2 of the CPU. It is still open. +For Neoverse V2, the following errata build flags are defined : + +- ``ERRATA_V2_2719103``: This applies errata 2719103 workaround to Neoverse-V2 + CPU, this affects system configurations that do not use and ARM interconnect + IP. This needs to be enabled for revisions r0p0 and r0p1. It has been fixed + in r0p2. + For Cortex-A710, the following errata build flags are defined : - ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to @@ -558,6 +585,11 @@ For Cortex-A710, the following errata build flags are defined : Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 of the CPU and is fixed in r2p1. +- ``ERRATA_A710_2701952``: This applies erratum 2701952 workaround to Cortex-A710 + CPU, and applies to system configurations that do not use and ARM + interconnect IP. This needs to be enabled for r0p0, r1p0, r2p0 and r2p1 and + is still open. + - ``ERRATA_A710_2768515``: This applies errata 2768515 workaround to Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 of the CPU and is still open. @@ -610,6 +642,11 @@ For Neoverse N2, the following errata build flags are defined : CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2. It is fixed in r0p3. +- ``ERRATA_N2_2728475``: This applies erratum 2728475 workaround to Neoverse-N2 + CPU, this erratum affects system configurations that do not use and ARM + interconnect IP. This needs to be enabled for revisions r0p0, r0p1 and r0p2. + It is fixed in r0p3. + For Cortex-X2, the following errata build flags are defined : - ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2 @@ -647,6 +684,11 @@ For Cortex-X2, the following errata build flags are defined : CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 of the CPU and is fixed in r2p1. +- ``ERRATA_X2_2701952``: This applies erratum 2701952 workaround to Cortex-X2 + CPU and affects system configurations that do not use an ARM interconnect IP. + This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 and is + still open. + - ``ERRATA_X2_2768515``: This applies errata 2768515 workaround to Cortex-X2 CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 of the CPU and is still open. @@ -709,6 +751,13 @@ For Cortex-A510, the following errata build flags are defined : Cortex-A510 CPU. This needs to be applied to revision r0p0, r0p1, r0p2, r0p3, r1p0, r1p1 and r1p2. It is fixed in r1p3. +For Cortex-A715, the following errata build flags are defined : + +- ``ERRATA_A715_2701951``: This applies erratum 2701951 workaround to Cortex-A715 + CPU and affects system configurations that do not use an ARM interconnect + IP. This needs to be applied to revisions r0p0, r1p0 and r1p1. It is fixed + in r1p2. + DSU Errata Workarounds ---------------------- diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst index 97f355045..2c9b76a01 100644 --- a/docs/design/firmware-design.rst +++ b/docs/design/firmware-design.rst @@ -1759,6 +1759,10 @@ BL image during boot. DRAM 0xffffffff +----------+ + | EL3 TZC | + 0xffe00000 |----------| (secure) + | AP TZC | + 0xff000000 +----------+ : : 0x82100000 |----------| |HW_CONFIG | @@ -1800,6 +1804,10 @@ BL image during boot. DRAM 0xffffffff +--------------+ + | EL3 TZC | + 0xffe00000 |--------------| (secure) + | AP TZC | + 0xff000000 +--------------+ : : 0x82100000 |--------------| | HW_CONFIG | @@ -1840,7 +1848,10 @@ BL image during boot. DRAM 0xffffffff +----------+ - | BL32 | (secure) + | EL3 TZC | + 0xffe00000 |----------| (secure) + | AP TZC | + | (BL32) | 0xff000000 +----------+ | | 0x82100000 |----------| @@ -1880,6 +1891,20 @@ BL image during boot. :: + DRAM + 0xFFFFFFFF +----------+ + | SCP TZC | + 0xFFE00000 |----------| + | EL3 TZC | + 0xFFC00000 |----------| (secure) + | AP TZC | + 0xFF000000 +----------+ + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Flash0 0x0C000000 +----------+ : : @@ -1909,9 +1934,14 @@ BL image during boot. :: DRAM - 0xFFE00000 +----------+ - | BL32 | (secure) - 0xFF000000 |----------| + 0xFFFFFFFF +----------+ + | SCP TZC | + 0xFFE00000 |----------| + | EL3 TZC | + 0xFFC00000 |----------| (secure) + | AP TZC | + | (BL32) | + 0xFF000000 +----------+ | | : : (non-secure) | | diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 3694b1c47..4eafb392b 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -436,7 +436,8 @@ Common build options (SME), SVE, and FPU/SIMD for the non-secure world only. These features share registers so are enabled together. Using this option without ENABLE_SME_FOR_SWD=1 will cause SME, SVE, and FPU/SIMD instructions in secure - world to trap to EL3. SME is an optional architectural feature for AArch64 + world to trap to EL3. Requires ``ENABLE_SVE_FOR_NS`` to be set as SME is a + superset of SVE. SME is an optional architectural feature for AArch64 and TF-A support is experimental. At this time, this build option cannot be used on systems that have SPD=spmd/SPM_MM or ENABLE_RME, and attempting to build with these options will fail. This flag can take the values 0 to 2, to @@ -450,10 +451,9 @@ Common build options align with the ``FEATURE_DETECTION`` mechanism. Default is 0. - ``ENABLE_SME_FOR_SWD``: Boolean option to enable the Scalable Matrix - Extension for secure world use along with SVE and FPU/SIMD, ENABLE_SME_FOR_NS - must also be set to use this. If enabling this, the secure world MUST - handle context switching for SME, SVE, and FPU/SIMD registers to ensure that - no data is leaked to non-secure world. This is experimental. Default is 0. + Extension for secure world. Used along with SVE and FPU/SIMD. + ENABLE_SME_FOR_NS and ENABLE_SVE_FOR_SWD must also be set to use this. + This is experimental. Default is 0. - ``ENABLE_SPE_FOR_NS`` : Numeric value to enable Statistical Profiling extensions. This is an optional architectural feature for AArch64. @@ -469,17 +469,15 @@ Common build options This is to avoid corruption of the Non-secure world data in the Z-registers which are aliased by the SIMD and FP registers. The build option is not compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an - assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` enabled. - This flag can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` - mechanism. The default is 2 but is automatically disabled when - ENABLE_SME_FOR_NS is enabled ( set to 1 or 2) since SME encompasses SVE. - At this time, this build option cannot be used on systems that have SPM_MM - enabled. + assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` + enabled. This flag can take the values 0 to 2, to align with the + ``FEATURE_DETECTION`` mechanism. At this time, this build option cannot be + used on systems that have SPM_MM enabled. The default is 1. - ``ENABLE_SVE_FOR_SWD``: Boolean option to enable SVE for the Secure world. SVE is an optional architectural feature for AArch64. Note that this option - requires ENABLE_SVE_FOR_NS to be enabled. The default is 0 and it - is automatically disabled when the target architecture is AArch32. + requires ENABLE_SVE_FOR_NS to be enabled. The default is 0 and it is + automatically disabled when the target architecture is AArch32. - ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection checks in GCC. Allowed values are "all", "strong", "default" and "none". The @@ -1131,6 +1129,13 @@ Common build options means platform hook won't be checked and CMOs will always be performed when related functions are called. +- ``ERRATA_ABI_SUPPORT``: Boolean option to enable support for Errata management + firmware interface for the BL31 image. By default its disabled (``0``). + +- ``ERRATA_NON_ARM_INTERCONNECT``: Boolean option to enable support for the + errata mitigation for platforms with a non-arm interconnect using the errata + ABI. By default its disabled (``0``). + GICv3 driver options -------------------- diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt index 9428fe97d..80012e7b8 100644 --- a/docs/global_substitutions.txt +++ b/docs/global_substitutions.txt @@ -69,3 +69,4 @@ .. |UEFI| replace:: :term:`UEFI` .. |WDOG| replace:: :term:`WDOG` .. |XLAT| replace:: :term:`XLAT` +.. |ERRATA_ABI| replace:: :term:`ERRATA_ABI` diff --git a/docs/glossary.rst b/docs/glossary.rst index 12c6ab756..58b7d999b 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -70,6 +70,9 @@ You can find additional definitions in the `Arm Glossary`_. EHF Exception Handling Framework + ERRATA_ABI + Errata management firmware interface + FCONF Firmware Configuration Framework diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 168d0ebc9..2c7480001 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -330,6 +330,8 @@ void gicv3_cpuif_enable(unsigned int proc_num) /* Enable Group1 Secure interrupts */ write_icc_igrpen1_el3(read_icc_igrpen1_el3() | IGRPEN1_EL3_ENABLE_G1S_BIT); + /* and restore the original */ + write_scr_el3(scr_el3); isb(); /* Add DSB to ensure visibility of System register writes */ dsb(); diff --git a/drivers/io/io_dummy.c b/drivers/io/io_dummy.c deleted file mode 100644 index 4f0cda6da..000000000 --- a/drivers/io/io_dummy.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <assert.h> -#include <string.h> - -#include <common/debug.h> -#include <drivers/io/io_driver.h> -#include <drivers/io/io_dummy.h> -#include <drivers/io/io_storage.h> - -struct file_state { - int in_use; - size_t size; -}; - -static struct file_state current_file = {0}; - -/* Identify the device type as dummy */ -static io_type_t device_type_dummy(void) -{ - return IO_TYPE_DUMMY; -} - -/* Dummy device functions */ -static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); -static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, - io_entity_t *entity); -static int dummy_block_len(io_entity_t *entity, size_t *length); -static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, - size_t length, size_t *length_read); -static int dummy_block_close(io_entity_t *entity); -static int dummy_dev_close(io_dev_info_t *dev_info); - - -static const io_dev_connector_t dummy_dev_connector = { - .dev_open = dummy_dev_open -}; - - -static const io_dev_funcs_t dummy_dev_funcs = { - .type = device_type_dummy, - .open = dummy_block_open, - .seek = NULL, - .size = dummy_block_len, - .read = dummy_block_read, - .write = NULL, - .close = dummy_block_close, - .dev_init = NULL, - .dev_close = dummy_dev_close, -}; - - -static const io_dev_info_t dummy_dev_info = { - .funcs = &dummy_dev_funcs, - .info = (uintptr_t)NULL -}; - - -/* Open a connection to the dummy device */ -static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)), - io_dev_info_t **dev_info) -{ - assert(dev_info != NULL); - *dev_info = (io_dev_info_t *)&dummy_dev_info; - - return 0; -} - - -/* Close a connection to the dummy device */ -static int dummy_dev_close(io_dev_info_t *dev_info) -{ - return 0; -} - - -/* Open a file on the dummy device */ -static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, - io_entity_t *entity) -{ - int result; - const io_block_spec_t *block_spec = (io_block_spec_t *)spec; - - if (current_file.in_use == 0) { - assert(block_spec != NULL); - assert(entity != NULL); - - current_file.in_use = 1; - current_file.size = block_spec->length; - entity->info = (uintptr_t)¤t_file; - result = 0; - } else { - WARN("A Dummy device is already active. Close first.\n"); - result = -ENOMEM; - } - - return result; -} - - -/* Return the size of a file on the dummy device */ -static int dummy_block_len(io_entity_t *entity, size_t *length) -{ - assert(entity != NULL); - assert(length != NULL); - - *length = ((struct file_state *)entity->info)->size; - - return 0; -} - - -/* Read data from a file on the dummy device */ -static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, - size_t length, size_t *length_read) -{ - assert(length_read != NULL); - - *length_read = length; - - return 0; -} - - -/* Close a file on the dummy device */ -static int dummy_block_close(io_entity_t *entity) -{ - assert(entity != NULL); - - entity->info = 0; - current_file.in_use = 0; - - return 0; -} - - -/* Exported functions */ - -/* Register the dummy driver with the IO abstraction */ -int register_io_dev_dummy(const io_dev_connector_t **dev_con) -{ - int result; - - assert(dev_con != NULL); - - result = io_register_device(&dummy_dev_info); - if (result == 0) - *dev_con = &dummy_dev_connector; - - return result; -} 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/drivers/io/io_dummy.h b/include/drivers/io/io_dummy.h deleted file mode 100644 index edfc6993e..000000000 --- a/include/drivers/io/io_dummy.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef IO_DUMMY_H -#define IO_DUMMY_H - -int register_io_dev_dummy(const struct io_dev_connector **dev_con); - -#endif /* IO_DUMMY_H */ diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h index 8f30ed050..31793832d 100644 --- a/include/drivers/io/io_storage.h +++ b/include/drivers/io/io_storage.h @@ -19,7 +19,6 @@ typedef enum { IO_TYPE_INVALID, IO_TYPE_SEMIHOSTING, IO_TYPE_MEMMAP, - IO_TYPE_DUMMY, IO_TYPE_FIRMWARE_IMAGE_PACKAGE, IO_TYPE_BLOCK, IO_TYPE_MTD, 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 <lib/smccc.h> + +#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/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk index 82a4890cf..e16c8e495 100644 --- a/lib/cpus/cpu-ops.mk +++ b/lib/cpus/cpu-ops.mk @@ -324,6 +324,11 @@ CPU_FLAG_LIST += ERRATA_A78_2376745 # to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. It is still open. CPU_FLAG_LIST += ERRATA_A78_2395406 +# Flag to apply erratum 2712571 workaround for non-arm interconnect ip. This +# erratum applies to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. +# It is fixed in r1p2. +CPU_FLAG_LIST += ERRATA_A78_2712571 + # Flag to apply erratum 2742426 workaround during reset. This erratum # applies to revisions r0p0, r1p0, r1p1 and r1p2 of the A78 cpu. It is still # open. @@ -362,6 +367,11 @@ CPU_FLAG_LIST += ERRATA_A78C_1827430 # to revision r0p0 of the A78C cpu. It is fixed in r0p1. CPU_FLAG_LIST += ERRATA_A78C_1827440 +# Flag to apply erratum 2712574 workaround for non-arm interconnect ip. This +# erratum applies to revisions r0p0, r0p1 and r0p2 of the A78 AE cpu. +# It is still open. +CPU_FLAG_LIST += ERRATA_A78_AE_2712574 + # Flag to apply erratum 2132064 workaround during reset. This erratum applies # to revisions r0p1 and r0p2 of the A78C cpu. It is still open. CPU_FLAG_LIST += ERRATA_A78C_2132064 @@ -378,6 +388,11 @@ CPU_FLAG_LIST += ERRATA_A78C_2376749 # to revisions r0p1 and r0p2 of the A78C cpu. It is still open. CPU_FLAG_LIST += ERRATA_A78C_2395411 +# Flag to apply erratum 2712575 workaround for non-arm interconnect ip. This +# erratum applies to revisions r0p1 and r0p2 of the A78C cpu. +# It is still open. +CPU_FLAG_LIST += ERRATA_A78C_2712575 + # Flag to apply erratum 2772121 workaround during powerdown. This erratum # applies to revisions r0p0, r0p1 and r0p2 of the A78C cpu. It is still open. CPU_FLAG_LIST += ERRATA_A78C_2772121 @@ -509,6 +524,11 @@ CPU_FLAG_LIST += ERRATA_V1_2294912 # to revisions r0p0, r1p0 and r1p1 of the Neoverse V1 cpu and is still open. CPU_FLAG_LIST += ERRATA_V1_2372203 +# Flag to apply erratum 2701953 workaround to non-arm interconnect ip. This +# erratum applies to revisions r0p0, r1p0, r1p1 of the Neoverse V1 cpu, +# it is fixed in r1p2. +CPU_FLAG_LIST += ERRATA_V1_2701953 + # Flag to apply erratum 2743093 workaround during powerdown. This erratum # applies to revisions r0p0, r1p0, r1p1 and r1p2 of the Neoverse V1 cpu and is # still open. @@ -581,6 +601,11 @@ CPU_FLAG_LIST += ERRATA_A710_2008768 # to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. CPU_FLAG_LIST += ERRATA_A710_2371105 +# Flag to apply erratum 2701952 workaround for non-arm interconnect ip. This +# erratum applies to revision r0p0, r1p0, r2p0, r2p1 of the Cortex-A710 cpu +# and is still open. +CPU_FLAG_LIST += ERRATA_A710_2701952 + # Flag to apply erratum 2768515 workaround during power down. This erratum # applies to revision r0p0, r1p0, r2p0 and r2p1 of the Cortex-A710 cpu and is # still open. @@ -638,6 +663,11 @@ CPU_FLAG_LIST += ERRATA_N2_2376738 # to revision r0p0 of the Neoverse N2 cpu, it is fixed in r0p1. CPU_FLAG_LIST += ERRATA_N2_2388450 +# Flag to apply erratum 2728475 workaround for non-arm interconnect ip. This +# erratum applies to r0p0, r0p1, r0p2 of the Neoverse N2 cpu, it is fixed in +# r0p3. +CPU_FLAG_LIST += ERRATA_N2_2728475 + # Flag to apply erratum 2743089 workaround during during powerdown. This erratum # applies to all revisions <= r0p2 of the Neoverse N2 cpu, it is fixed in r0p3. CPU_FLAG_LIST += ERRATA_N2_2743089 @@ -682,6 +712,11 @@ CPU_FLAG_LIST += ERRATA_X2_2282622 # to revision r0p0, r1p0 and r2p0 of the Cortex-X2 cpu and is fixed in r2p1. CPU_FLAG_LIST += ERRATA_X2_2371105 +# Flag to apply erratum 2701952 workaround for non-arm interconnect ip. This +# erratum applies to revisions r0p0, r1p0, r2p0, r2p1 of the Cortex-x2 cpu +# and is still open. +CPU_FLAG_LIST += ERRATA_X2_2701952 + # Flag to apply erratum 2768515 workaround during power down. This erratum # applies to revision r0p0, r1p0, r2p0 and r2p1 of the Cortex-X2 cpu and is # still open. @@ -743,6 +778,14 @@ CPU_FLAG_LIST += ERRATA_A510_2666669 # Cortex-A510 cpu and is fixed in r1p3. CPU_FLAG_LIST += ERRATA_A510_2684597 +# Flag to apply erratum 2719103 workaround for non-arm interconnect ip. This +# erratum applies to revisions r0p0, rop1. Fixed in r0p2. +CPU_FLAG_LIST += ERRATA_V2_2719103 + +# Flag to apply erratum 2701951 workaround for non-arm interconnect ip. +# This erratum applies to revisions r0p0, r1p0, and r1p1. Its is fixed in r1p2. +CPU_FLAG_LIST += ERRATA_A715_2701951 + # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0. # Applying the workaround results in higher DSU power consumption on idle. CPU_FLAG_LIST += ERRATA_DSU_798953 diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index e107f5ad6..2a9bb5924 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -517,12 +517,13 @@ static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) amu_enable(el2_unused, ctx); } - /* Enable SME, SVE, and FPU/SIMD for non-secure world. */ + /* Enable SVE and FPU/SIMD */ + if (is_feat_sve_supported()) { + sve_enable(ctx); + } + if (is_feat_sme_supported()) { sme_enable(ctx); - } else if (is_feat_sve_supported()) { - /* Enable SVE and FPU/SIMD for non-secure world. */ - sve_enable(ctx); } if (is_feat_mpam_supported()) { @@ -553,22 +554,7 @@ static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) static void manage_extensions_secure(cpu_context_t *ctx) { #if IMAGE_BL31 - - if (is_feat_sme_supported()) { - if (ENABLE_SME_FOR_SWD) { - /* - * Enable SME, SVE, FPU/SIMD in secure context, secure manager - * must ensure SME, SVE, and FPU/SIMD context properly managed. - */ - sme_enable(ctx); - } else { - /* - * Disable SME, SVE, FPU/SIMD in secure context so non-secure - * world can safely use the associated registers. - */ - sme_disable(ctx); - } - } else if (is_feat_sve_supported()) { + if (is_feat_sve_supported()) { if (ENABLE_SVE_FOR_SWD) { /* * Enable SVE and FPU in secure context, secure manager must @@ -585,6 +571,21 @@ static void manage_extensions_secure(cpu_context_t *ctx) } } + if (is_feat_sme_supported()) { + if (ENABLE_SME_FOR_SWD) { + /* + * Enable SME, SVE, FPU/SIMD in secure context, secure manager + * must ensure SME, SVE, and FPU/SIMD context properly managed. + */ + sme_enable(ctx); + } else { + /* + * Disable SME, SVE, FPU/SIMD in secure context so non-secure + * world can safely use the associated registers. + */ + sme_disable(ctx); + } + } #endif /* IMAGE_BL31 */ } diff --git a/lib/extensions/sme/sme.c b/lib/extensions/sme/sme.c index f888d12c4..3423dbaf5 100644 --- a/lib/extensions/sme/sme.c +++ b/lib/extensions/sme/sme.c @@ -65,9 +65,6 @@ void sme_enable(cpu_context_t *context) /* Reset CPTR_EL3 value. */ write_cptr_el3(cptr_el3); isb(); - - /* Enable SVE/FPU in addition to SME. */ - sve_enable(context); } void sme_disable(cpu_context_t *context) diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index fd9ad92c3..f9077eb9b 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -292,6 +292,12 @@ SDEI_SUPPORT := 0 # True Random Number firmware Interface support TRNG_SUPPORT := 0 +# Check to see if Errata ABI is supported +ERRATA_ABI_SUPPORT := 0 + +# Check to enable Errata ABI for platforms with non-arm interconnect +ERRATA_NON_ARM_INTERCONNECT := 0 + # SMCCC PCI support SMC_PCI_SUPPORT := 0 @@ -402,14 +408,6 @@ SVE_VECTOR_LEN := 2048 # SME defaults to disabled ENABLE_SME_FOR_NS := 0 ENABLE_SME_FOR_SWD := 0 - -# If SME is enabled then force SVE off -ifneq (${ENABLE_SME_FOR_NS},0) - override ENABLE_SVE_FOR_NS := 0 - override ENABLE_SVE_FOR_SWD := 0 -endif - -# SME2 defaults to disabled ENABLE_SME2_FOR_NS := 0 SANITIZE_UB := off diff --git a/plat/arm/board/fvp/fvp_cpu_errata.mk b/plat/arm/board/fvp/fvp_cpu_errata.mk new file mode 100644 index 000000000..944571dd5 --- /dev/null +++ b/plat/arm/board/fvp/fvp_cpu_errata.mk @@ -0,0 +1,61 @@ +# +# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +#/* +# * TODO: below lines of code to be removed +# * after abi and framework are synchronized +# */ + +ifeq (${ERRATA_ABI_SUPPORT}, 1) +# enable the cpu macros for errata abi interface +ifeq (${ARCH}, aarch64) +ifeq (${HW_ASSISTED_COHERENCY}, 0) +CORTEX_A35_H_INC := 1 +CORTEX_A53_H_INC := 1 +CORTEX_A57_H_INC := 1 +CORTEX_A72_H_INC := 1 +CORTEX_A73_H_INC := 1 +$(eval $(call add_define, CORTEX_A35_H_INC)) +$(eval $(call add_define, CORTEX_A53_H_INC)) +$(eval $(call add_define, CORTEX_A57_H_INC)) +$(eval $(call add_define, CORTEX_A72_H_INC)) +$(eval $(call add_define, CORTEX_A73_H_INC)) +else +ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0) +CORTEX_A76_H_INC := 1 +CORTEX_A77_H_INC := 1 +CORTEX_A78_H_INC := 1 +NEOVERSE_N1_H_INC := 1 +NEOVERSE_V1_H_INC := 1 +CORTEX_A78_AE_H_INC := 1 +CORTEX_A510_H_INC := 1 +CORTEX_A710_H_INC := 1 +CORTEX_A715_H_INC := 1 +CORTEX_A78C_H_INC := 1 +CORTEX_X2_H_INC := 1 +$(eval $(call add_define, CORTEX_A76_H_INC)) +$(eval $(call add_define, CORTEX_A77_H_INC)) +$(eval $(call add_define, CORTEX_A78_H_INC)) +$(eval $(call add_define, NEOVERSE_N1_H_INC)) +$(eval $(call add_define, NEOVERSE_V1_H_INC)) +$(eval $(call add_define, CORTEX_A78_AE_H_INC)) +$(eval $(call add_define, CORTEX_A510_H_INC)) +$(eval $(call add_define, CORTEX_A710_H_INC)) +$(eval $(call add_define, CORTEX_A715_H_INC)) +$(eval $(call add_define, CORTEX_A78C_H_INC)) +$(eval $(call add_define, CORTEX_X2_H_INC)) +endif +CORTEX_A55_H_INC := 1 +CORTEX_A75_H_INC := 1 +$(eval $(call add_define, CORTEX_A55_H_INC)) +$(eval $(call add_define, CORTEX_A75_H_INC)) +endif +else +CORTEX_A32_H_INC := 1 +$(eval $(call add_define, CORTEX_A32_H_INC)) +endif +endif diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 8a6aa00f8..0433b61d5 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -525,3 +525,7 @@ ifeq (${PLATFORM_TEST_RAS_FFH}, 1) $(error "PLATFORM_TEST_RAS_FFH expects RAS_EXTENSION to be 1") endif endif + +ifeq (${ERRATA_ABI_SUPPORT}, 1) +include plat/arm/board/fvp/fvp_cpu_errata.mk +endif diff --git a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_bus26m.c index 0b792ab1b..c8a2d4c37 100644 --- a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_bus26m.c +++ b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_bus26m.c @@ -53,6 +53,7 @@ static unsigned int bus26m_ext_opand2; static struct mt_irqremain *refer2remain_irq; static struct mt_spm_cond_tables cond_bus26m = { + .name = "bus26m", .table_cg = { 0xFF5DD002, /* MTCMOS1 */ 0x0000003C, /* MTCMOS2 */ @@ -175,7 +176,7 @@ bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id) (IS_PLAT_SUSPEND_ID(state_id) || (state_id == MT_PLAT_PWR_STATE_SYSTEM_BUS))); } -static int update_rc_condition(const void *val) +static int update_rc_condition(int state_id, const void *val) { const struct mt_spm_cond_tables *tlb = (const struct mt_spm_cond_tables *)val; const struct mt_spm_cond_tables *tlb_check = @@ -185,7 +186,7 @@ static int update_rc_condition(const void *val) return MT_RM_STATUS_BAD; } - status.is_cond_block = mt_spm_cond_check(tlb, tlb_check, + status.is_cond_block = mt_spm_cond_check(state_id, tlb, tlb_check, (status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ? &cond_bus26m_res : NULL); status.all_pll_dump = mt_spm_dump_all_pll(tlb, tlb_check, @@ -279,7 +280,7 @@ int spm_update_rc_bus26m(int state_id, int type, const void *val) switch (type) { case PLAT_RC_UPDATE_CONDITION: - res = update_rc_condition(val); + res = update_rc_condition(state_id, val); break; case PLAT_RC_UPDATE_REMAIN_IRQS: update_rc_remain_irqs(val); diff --git a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_dram.c b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_dram.c index d1a2435f6..82b38ade4 100644 --- a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_dram.c +++ b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_dram.c @@ -37,6 +37,7 @@ #define CONSTRAINT_DRAM_RESOURCE_REQ (MT_SPM_SYSPLL | MT_SPM_INFRA | MT_SPM_26M) static struct mt_spm_cond_tables cond_dram = { + .name = "dram", .table_cg = { 0xFF5DD002, /* MTCMOS1 */ 0x0000003C, /* MTCMOS2 */ @@ -104,7 +105,7 @@ bool spm_is_valid_rc_dram(unsigned int cpu, int state_id) (state_id == MT_PLAT_PWR_STATE_SYSTEM_BUS))); } -static int update_rc_condition(const void *val) +static int update_rc_condition(int state_id, const void *val) { const struct mt_spm_cond_tables *tlb = (const struct mt_spm_cond_tables *)val; const struct mt_spm_cond_tables *tlb_check = (const struct mt_spm_cond_tables *)&cond_dram; @@ -113,7 +114,7 @@ static int update_rc_condition(const void *val) return MT_RM_STATUS_BAD; } - status.is_cond_block = mt_spm_cond_check(tlb, tlb_check, + status.is_cond_block = mt_spm_cond_check(state_id, tlb, tlb_check, (status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ? &cond_dram_res : NULL); return MT_RM_STATUS_OK; @@ -185,7 +186,7 @@ int spm_update_rc_dram(int state_id, int type, const void *val) switch (type) { case PLAT_RC_UPDATE_CONDITION: - res = update_rc_condition(val); + res = update_rc_condition(state_id, val); break; case PLAT_RC_CLKBUF_STATUS: update_rc_clkbuf_status(val); diff --git a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_syspll.c b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_syspll.c index 700f50018..5359c7c1b 100644 --- a/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_syspll.c +++ b/plat/mediatek/drivers/spm/mt8188/constraints/mt_spm_rc_syspll.c @@ -49,6 +49,7 @@ static unsigned int syspll_ext_opand2; static unsigned short ext_status_syspll; static struct mt_spm_cond_tables cond_syspll = { + .name = "syspll", .table_cg = { 0xFF5DD002, /* MTCMOS1 */ 0x0000003C, /* MTCMOS2 */ @@ -113,7 +114,7 @@ bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id) (state_id == MT_PLAT_PWR_STATE_SYSTEM_BUS))); } -static int update_rc_condition(const void *val) +static int update_rc_condition(int state_id, const void *val) { int res = MT_RM_STATUS_OK; @@ -126,7 +127,7 @@ static int update_rc_condition(const void *val) return MT_RM_STATUS_BAD; } - status.is_cond_block = mt_spm_cond_check(tlb, tlb_check, + status.is_cond_block = mt_spm_cond_check(state_id, tlb, tlb_check, (status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ? &cond_syspll_res : NULL); return res; @@ -228,7 +229,7 @@ int spm_update_rc_syspll(int state_id, int type, const void *val) switch (type) { case PLAT_RC_UPDATE_CONDITION: - res = update_rc_condition(val); + res = update_rc_condition(state_id, val); break; case PLAT_RC_CLKBUF_STATUS: update_rc_clkbuf_status(val); diff --git a/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.c b/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.c index fe6e59828..bed55c906 100644 --- a/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.c +++ b/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.c @@ -126,12 +126,14 @@ static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = { #define PLL_APLL4 MT_LP_TZ_APMIXEDSYS(0x404) #define PLL_APLL5 MT_LP_TZ_APMIXEDSYS(0x418) -unsigned int mt_spm_cond_check(const struct mt_spm_cond_tables *src, +unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, const struct mt_spm_cond_tables *dest, struct mt_spm_cond_tables *res) { unsigned int b_res = 0U; unsigned int i; + bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id); if ((src == NULL) || (dest == NULL)) { return SPM_COND_CHECK_FAIL; @@ -140,6 +142,11 @@ unsigned int mt_spm_cond_check(const struct mt_spm_cond_tables *src, for (i = 0; i < PLAT_SPM_COND_MAX; i++) { if (res != NULL) { res->table_cg[i] = (src->table_cg[i] & dest->table_cg[i]); + if (is_system_suspend && ((res->table_cg[i]) != 0U)) { + INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n", + dest->name, i, idle_cg_info[i].addr, + res->table_cg[i]); + } if ((res->table_cg[i]) != 0U) { b_res |= BIT(i); @@ -161,6 +168,10 @@ unsigned int mt_spm_cond_check(const struct mt_spm_cond_tables *src, b_res |= SPM_COND_CHECK_BLOCKED_PLL; } + if (is_system_suspend && ((b_res) != 0U)) { + INFO("suspend: %s total blocked = 0x%08x\n", dest->name, b_res); + } + return b_res; } diff --git a/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.h b/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.h index 793d5e81c..d93df57eb 100644 --- a/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.h +++ b/plat/mediatek/drivers/spm/mt8188/mt_spm_cond.h @@ -75,13 +75,15 @@ enum plat_spm_cond_pll { #define SPM_COND_CHECK_FAIL BIT(31) struct mt_spm_cond_tables { + char *name; unsigned int table_cg[PLAT_SPM_COND_MAX]; unsigned int table_pll; unsigned int table_all_pll; void *priv; }; -unsigned int mt_spm_cond_check(const struct mt_spm_cond_tables *src, +unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, const struct mt_spm_cond_tables *dest, struct mt_spm_cond_tables *res); unsigned int mt_spm_dump_all_pll(const struct mt_spm_cond_tables *src, diff --git a/plat/mediatek/drivers/spm/mt8188/mt_spm_conservation.c b/plat/mediatek/drivers/spm/mt8188/mt_spm_conservation.c index bcb2df64b..395448a9f 100644 --- a/plat/mediatek/drivers/spm/mt8188/mt_spm_conservation.c +++ b/plat/mediatek/drivers/spm/mt8188/mt_spm_conservation.c @@ -61,6 +61,14 @@ static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand, __spm_send_cpu_wakeup_event(); + INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n", + cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE), + (mmio_read_32(PCM_TIMER_VAL) / 32768)); + INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n", + pwrctrl->pcm_flags, pwrctrl->pcm_flags1, + mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS), + mmio_read_32(PWR_STATUS_2ND)); + return ret; } diff --git a/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.c b/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.c index b38a6d0a7..5eb16b35a 100644 --- a/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.c +++ b/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.c @@ -24,6 +24,7 @@ wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta) { + uint32_t bk_vtcxo_dur, spm_26m_off_pct; wake_reason_t wr = WR_UNKNOWN; if (wakesta == NULL) { @@ -46,6 +47,33 @@ wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta) } } + INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n", + wakesta->tr.comm.r12, wakesta->r12_ext, wakesta->tr.comm.r13, wakesta->tr.comm.debug_flag, + wakesta->tr.comm.debug_flag1); + INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n", + wakesta->tr.comm.raw_sta, wakesta->md32pcm_wakeup_sta, + wakesta->md32pcm_event_sta, wakesta->idle_sta, + wakesta->cg_check_sta); + INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n", + wakesta->tr.comm.req_sta0, wakesta->tr.comm.req_sta1, wakesta->tr.comm.req_sta2, + wakesta->tr.comm.req_sta3, wakesta->tr.comm.req_sta4, wakesta->isr); + INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n", + wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2); + INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n", + wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta); + INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n", + wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1, + wakesta->tr.comm.b_sw_flag0, wakesta->tr.comm.b_sw_flag1, wakesta->src_req); + INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n", + wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L), + mmio_read_32(SYS_TIMER_VALUE_H)); + + if (wakesta->tr.comm.timer_out != 0U) { + bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR); + spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->tr.comm.timer_out; + INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct); + } + return wr; } @@ -331,6 +359,18 @@ void __spm_get_wakeup_status(struct wake_status *wakesta, unsigned int ext_statu wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); /* SPM_SW_RSV_7 */ wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); /* SPM_SW_RSV_8 */ + /* record below spm info for debug */ + wakesta->src_req = mmio_read_32(SPM_SRC_REQ); + + /* get HW CG check status */ + wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA); + + wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2); + wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3); + wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4); + wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5); + wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6); + /* get ISR status */ wakesta->isr = mmio_read_32(SPM_IRQ_STA); @@ -338,6 +378,9 @@ void __spm_get_wakeup_status(struct wake_status *wakesta, unsigned int ext_statu wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0); wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1); + /* get CLK SETTLE */ + wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE); + /* check abort */ wakesta->is_abort = wakesta->tr.comm.debug_flag & DEBUG_ABORT_MASK; wakesta->is_abort |= wakesta->tr.comm.debug_flag1 & DEBUG_ABORT_MASK_1; diff --git a/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.h b/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.h index c719cafcb..5e3390f29 100644 --- a/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.h +++ b/plat/mediatek/drivers/spm/mt8188/mt_spm_internal.h @@ -628,11 +628,19 @@ struct wake_status { uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */ uint32_t wake_misc; /* SPM_SW_RSV_5 */ uint32_t idle_sta; /* SUBSYS_IDLE_STA */ + uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */ uint32_t sw_flag0; /* SPM_SW_FLAG_0 */ uint32_t sw_flag1; /* SPM_SW_FLAG_1 */ uint32_t isr; /* SPM_IRQ_STA */ + uint32_t clk_settle; /* SPM_CLK_SETTLE */ + uint32_t src_req; /* SPM_SRC_REQ */ uint32_t log_index; uint32_t is_abort; + uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */ + uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */ + uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */ + uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */ + uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */ }; struct spm_lp_scen { diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk index 7b3129c3b..8b8d76be8 100644 --- a/plat/qemu/qemu_sbsa/platform.mk +++ b/plat/qemu/qemu_sbsa/platform.mk @@ -139,3 +139,6 @@ $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) # Later QEMU versions support SME and SVE. ENABLE_SVE_FOR_NS := 2 ENABLE_SME_FOR_NS := 2 + +# QEMU 7.2+ has support for FGT and Linux needs it enabled to boot on max +ENABLE_FEAT_FGT := 2 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..671a6949d --- /dev/null +++ b/services/std_svc/errata_abi/cpu_errata_info.h @@ -0,0 +1,72 @@ +/* + * 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 <stdint.h> +#include <arch_helpers.h> + +#if __aarch64__ +#include <cortex_a35.h> +#include <cortex_a510.h> +#include <cortex_a53.h> +#include <cortex_a57.h> +#include <cortex_a55.h> +#include <cortex_a710.h> +#include <cortex_a72.h> +#include <cortex_a73.h> +#include <cortex_a75.h> +#include <cortex_a76.h> +#include <cortex_a77.h> +#include <cortex_a78.h> +#include <cortex_a78_ae.h> +#include <cortex_a78c.h> +#include <cortex_makalu.h> +#include <cortex_x1.h> +#include <cortex_x2.h> +#include <neoverse_n1.h> +#include <neoverse_n2.h> +#include <neoverse_v1.h> +#include <neoverse_v2.h> +#else +#include <cortex_a15.h> +#include <cortex_a17.h> +#include <cortex_a57.h> +#include <cortex_a9.h> +#endif + +#define MAX_ERRATA_ENTRIES 16 + +#define ERRATA_LIST_END (MAX_ERRATA_ENTRIES - 1) + +/* Default values for unused memory in the array */ +#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX, false, 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 */ + /* flag to indicate if errata query is based out of non-arm interconnect */ + bool non_arm_interconnect; +}; + +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..bf9409d06 --- /dev/null +++ b/services/std_svc/errata_abi/errata_abi_main.c @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include "cpu_errata_info.h" +#include <lib/smccc.h> +#include <lib/utils_def.h> +#include <services/errata_abi_svc.h> +#include <smccc_helpers.h> + +/* + * 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] = {2712571, 0x00, 0x12, ERRATA_A78_2712571, \ + ERRATA_NON_ARM_INTERCONNECT}, + [10] = {2742426, 0x00, 0x12, ERRATA_A78_2742426}, + [11] = {2772019, 0x00, 0x12, ERRATA_A78_2772019}, + [12] = {2779479, 0x00, 0x12, ERRATA_A78_2779479}, + [13 ... 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] = {2712574, 0x00, 0x02, ERRATA_A78_AE_2712574, \ + ERRATA_NON_ARM_INTERCONNECT}, + [5 ... 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] = {2712575, 0x01, 0x02, ERRATA_A78C_2712575, \ + ERRATA_NON_ARM_INTERCONNECT}, + [5] = {2772121, 0x00, 0x02, ERRATA_A78C_2772121}, + [6] = {2779484, 0x01, 0x02, ERRATA_A78C_2779484}, + [7 ... 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] = {2701953, 0x00, 0x11, ERRATA_V1_2701953, \ + ERRATA_NON_ARM_INTERCONNECT}, + [13] = {2743093, 0x00, 0x12, ERRATA_V1_2743093}, + [14] = {2779461, 0x00, 0x12, ERRATA_V1_2779461}, + [15 ... 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] = {2701952, 0x00, 0x21, ERRATA_A710_2701952, \ + ERRATA_NON_ARM_INTERCONNECT}, + [15] = {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] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, \ + ERRATA_NON_ARM_INTERCONNECT}, + [14] = {2743089, 0x00, 0x02, ERRATA_N2_2743089}, + [15 ... 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] = {2701952, 0x00, 0x21, ERRATA_X2_2701952, \ + ERRATA_NON_ARM_INTERCONNECT}, + [10] = {2768515, 0x00, 0x21, ERRATA_X2_2768515}, + [11 ... 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 */ + +#if NEOVERSE_V2_H_INC +{ + .cpu_partnumber = NEOVERSE_V2_MIDR, + .cpu_errata_list = { + [0] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, \ + ERRATA_NON_ARM_INTERCONNECT}, + [1 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* NEOVERSE_V2_H_INC */ + +#if CORTEX_A715_H_INC +{ + .cpu_partnumber = CORTEX_MAKALU_MIDR, + .cpu_errata_list = { + [0] = {2701951, 0x00, 0x11, ERRATA_A715_2701951, \ + ERRATA_NON_ARM_INTERCONNECT}, + [1 ... ERRATA_LIST_END] = UNDEF_ERRATA, + } +}, +#endif /* CORTEX_A715_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; + + assert(ptr != NULL); + + /* + * Pointer to the errata list of the cpu that matches + * extracted partnumber in the cpu list + */ + struct em_cpu *erratum_ptr = NULL; + + while (low_index <= high_index) { + mid_index = (low_index + high_index) / 2; + + erratum_ptr = &ptr->cpu_errata_list[mid_index]; + assert(erratum_ptr != NULL); + + if (erratum_id < erratum_ptr->em_errata_id) { + high_index = mid_index - 1; + } else if (erratum_id > erratum_ptr->em_errata_id) { + low_index = mid_index + 1; + } else if (erratum_id == erratum_ptr->em_errata_id) { + if (RXPX_RANGE(rxpx_val, erratum_ptr->em_rxpx_lo, \ + erratum_ptr->em_rxpx_hi)) { + if ((erratum_ptr->errata_enabled) && \ + (!(erratum_ptr->non_arm_interconnect))) { + 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 <lib/psci/psci.h> #include <lib/runtime_instr.h> #include <services/drtm_svc.h> +#include <services/errata_abi_svc.h> #include <services/pci_svc.h> #include <services/rmmd_svc.h> #include <services/sdei.h> @@ -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)) { |