diff --git a/Makefile b/Makefile index 18c487342..cb7eb08cf 100644 --- a/Makefile +++ b/Makefile @@ -550,6 +550,7 @@ $(eval $(call assert_boolean,DYN_DISABLE_AUTH)) $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING)) $(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) +$(eval $(call assert_boolean,ENABLE_MPAM_FOR_LOWER_ELS)) $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) @@ -601,6 +602,7 @@ $(eval $(call add_define,CTX_INCLUDE_FPREGS)) $(eval $(call add_define,EL3_EXCEPTION_HANDLING)) $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) +$(eval $(call add_define,ENABLE_MPAM_FOR_LOWER_ELS)) $(eval $(call add_define,ENABLE_PLAT_COMPAT)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) diff --git a/bl31/bl31.mk b/bl31/bl31.mk index bff965386..c99b637de 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -63,6 +63,10 @@ ifeq (${ENABLE_SVE_FOR_NS},1) BL31_SOURCES += lib/extensions/sve/sve.c endif +ifeq (${ENABLE_MPAM_FOR_LOWER_ELS},1) +BL31_SOURCES += lib/extensions/mpam/mpam.c +endif + ifeq (${WORKAROUND_CVE_2017_5715},1) BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ lib/cpus/aarch64/wa_cve_2017_5715_mmu.S diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 2b90bece8..2ef7c61d3 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -350,6 +350,17 @@ Common build options that is only required for the assertion and does not fit in the assertion itself. +- ``ENABLE_MPAM_FOR_LOWER_ELS``: Boolean option to enable lower ELs to use MPAM + feature. MPAM is an optional Armv8.4 extension that enables various memory + system components and resources to define partitions; software running at + various ELs can assign themselves to desired partition to control their + performance aspects. + + When this option is set to ``1``, EL3 allows lower ELs to access their own + MPAM registers without trapping into EL3. This option doesn't make use of + partitioning in EL3, however. Platform initialisation code should configure + and use partitions in EL3 as required. This option defaults to ``0``. + - ``ENABLE_PMF``: Boolean option to enable support for optional Performance Measurement Framework(PMF). Default is 0. diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index c9619f6c6..cccb286c5 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -117,6 +117,8 @@ #define ID_AA64PFR0_SVE_SHIFT U(32) #define ID_AA64PFR0_SVE_MASK ULL(0xf) #define ID_AA64PFR0_SVE_LENGTH U(4) +#define ID_AA64PFR0_MPAM_SHIFT U(40) +#define ID_AA64PFR0_MPAM_MASK ULL(0xf) #define ID_AA64PFR0_CSV2_SHIFT U(56) #define ID_AA64PFR0_CSV2_MASK ULL(0xf) #define ID_AA64PFR0_CSV2_LENGTH U(4) @@ -657,6 +659,14 @@ ******************************************************************************/ #define PMBLIMITR_EL1 S3_0_C9_C10_0 +/******************************************************************************* + * Definitions for system register interface to MPAM + ******************************************************************************/ +#define MPAMIDR_EL1 S3_0_C10_C4_4 +#define MPAM2_EL2 S3_4_C10_C5_0 +#define MPAMHCR_EL2 S3_4_C10_C4_0 +#define MPAM3_EL3 S3_6_C10_C5_0 + /******************************************************************************* * Definitions for system register interface to AMU for ARMv8.4 onwards ******************************************************************************/ @@ -722,6 +732,11 @@ #define AMCGCR_EL0_CG1NC_LENGTH U(8) #define AMCGCR_EL0_CG1NC_MASK U(0xff) +/* MPAM register definitions */ +#define MPAM3_EL3_MPAMEN_BIT (ULL(1) << 63) + +#define MPAMIDR_HAS_HCR_BIT (ULL(1) << 17) + /******************************************************************************* * RAS system registers *******************************************************************************/ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 58ec943a2..8e82dbdc7 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -328,6 +328,11 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) +DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2) + DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3) diff --git a/include/lib/extensions/mpam.h b/include/lib/extensions/mpam.h new file mode 100644 index 000000000..571b96b65 --- /dev/null +++ b/include/lib/extensions/mpam.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPAM_H +#define MPAM_H + +#include + +bool mpam_supported(void); +void mpam_enable(int el2_unused); + +#endif /* MPAM_H */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index f389368d4..2812bdaab 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -244,6 +245,10 @@ static void enable_extensions_nonsecure(int el2_unused) #if ENABLE_SVE_FOR_NS sve_enable(el2_unused); #endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + mpam_enable(el2_unused); +#endif #endif } diff --git a/lib/extensions/mpam/mpam.c b/lib/extensions/mpam/mpam.c new file mode 100644 index 000000000..e628827bf --- /dev/null +++ b/lib/extensions/mpam/mpam.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +bool mpam_supported(void) +{ + uint64_t features = read_id_aa64dfr0_el1() >> ID_AA64PFR0_MPAM_SHIFT; + + return ((features & ID_AA64PFR0_MPAM_MASK) != 0U); +} + +void mpam_enable(int el2_unused) +{ + if (!mpam_supported()) + return; + + /* + * Enable MPAM, and disable trapping to EL3 when lower ELs access their + * own MPAM registers. + */ + write_mpam3_el3(MPAM3_EL3_MPAMEN_BIT); + + /* + * If EL2 is implemented but unused, disable trapping to EL2 when lower + * ELs access their own MPAM registers. + */ + if (el2_unused != 0) { + write_mpam2_el2(0); + + if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) + write_mpamhcr_el2(0); + } +} diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index e4b5bdc92..49f403d2e 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -62,6 +62,9 @@ DEFAULT_PLAT := fvp # development platforms. DYN_DISABLE_AUTH := 0 +# Build option to enable MPAM for lower ELs +ENABLE_MPAM_FOR_LOWER_ELS := 0 + # Flag to enable Performance Measurement Framework ENABLE_PMF := 0