diff --git a/Makefile b/Makefile index 31ef7699c..fe18bc0ea 100644 --- a/Makefile +++ b/Makefile @@ -456,6 +456,7 @@ $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS)) $(eval $(call assert_boolean,DEBUG)) $(eval $(call assert_boolean,DISABLE_PEDANTIC)) +$(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT)) $(eval $(call assert_boolean,ENABLE_PMF)) @@ -495,6 +496,7 @@ $(eval $(call add_define,ARM_GIC_ARCH)) $(eval $(call add_define,COLD_BOOT_SINGLE_CPU)) $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call add_define,CTX_INCLUDE_FPREGS)) +$(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_PLAT_COMPAT)) $(eval $(call add_define,ENABLE_PMF)) diff --git a/bl31/bl31.mk b/bl31/bl31.mk index fccdc8a0a..ebd0e71a9 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -50,6 +50,10 @@ ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1) BL31_SOURCES += lib/extensions/spe/spe.c endif +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += lib/extensions/amu/aarch64/amu.c +endif + BL31_LINKERFILE := bl31/bl31.ld.S # Flag used to indicate if Crash reporting via console should be included diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk index 39588ce7d..56489a3c5 100644 --- a/bl32/sp_min/sp_min.mk +++ b/bl32/sp_min/sp_min.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -22,6 +22,10 @@ ifeq (${ENABLE_PMF}, 1) BL32_SOURCES += lib/pmf/pmf_main.c endif +ifeq (${ENABLE_AMU}, 1) +BL32_SOURCES += lib/extensions/amu/aarch32/amu.c +endif + BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S # Include the platform-specific SP_MIN Makefile diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 95fa22e08..79d660d02 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -321,6 +321,11 @@ Common build options payload. Please refer to the "Booting an EL3 payload" section for more details. +- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. + This is an optional architectural feature available on v8.4 onwards. Some + v8.2 implementations also implement an AMU and this option can be used to + enable this feature on those systems as well. Default is 0. + - ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` are compiled out. For debug builds, this option defaults to 1, and calls to ``assert()`` are left in place. For release builds, this option defaults to 0 diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index c8940303c..4d2a5fc9f 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -78,6 +78,11 @@ /* CSSELR definitions */ #define LEVEL_SHIFT 1 +/* ID_PFR0 definitions */ +#define ID_PFR0_AMU_SHIFT U(20) +#define ID_PFR0_AMU_LENGTH U(4) +#define ID_PFR0_AMU_MASK U(0xf) + /* ID_PFR1 definitions */ #define ID_PFR1_VIRTEXT_SHIFT 12 #define ID_PFR1_VIRTEXT_MASK 0xf @@ -187,6 +192,7 @@ /* HCPTR definitions */ #define HCPTR_RES1 ((1 << 13) | (1<<12) | 0x3ff) #define TCPAC_BIT (1 << 31) +#define TAM_BIT (1 << 30) #define TTA_BIT (1 << 20) #define TCP11_BIT (1 << 10) #define TCP10_BIT (1 << 10) @@ -407,6 +413,7 @@ #define DCISW p15, 0, c7, c6, 2 #define CTR p15, 0, c0, c0, 1 #define CNTFRQ p15, 0, c14, c0, 0 +#define ID_PFR0 p15, 0, c0, c1, 0 #define ID_PFR1 p15, 0, c0, c1, 1 #define MAIR0 p15, 0, c10, c2, 0 #define MAIR1 p15, 0, c10, c2, 1 @@ -525,4 +532,28 @@ #define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR p15, 0, c13, c2, 0 +#define AMCFGR p15, 0, c13, c2, 1 +#define AMCGCR p15, 0, c13, c2, 2 +#define AMUSERENR p15, 0, c13, c2, 3 +#define AMCNTENCLR0 p15, 0, c13, c2, 4 +#define AMCNTENSET0 p15, 0, c13, c2, 5 +#define AMCNTENCLR1 p15, 0, c13, c3, 0 +#define AMCNTENSET1 p15, 0, c13, c1, 1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00 p15, 0, c0 +#define AMEVCNTR01 p15, 1, c0 +#define AMEVCNTR02 p15, 2, c0 +#define AMEVCNTR03 p15, 3, c0 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00 p15, 0, c13, c6, 0 +#define AMEVTYPER01 p15, 0, c13, c6, 1 +#define AMEVTYPER02 p15, 0, c13, c6, 2 +#define AMEVTYPER03 p15, 0, c13, c6, 3 + #endif /* __ARCH_H__ */ diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h index 42309d550..0230195a0 100644 --- a/include/lib/aarch32/arch_helpers.h +++ b/include/lib/aarch32/arch_helpers.h @@ -227,6 +227,7 @@ DEFINE_SYSREG_RW_FUNCS(cpsr) ******************************************************************************/ DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR) DEFINE_COPROCR_READ_FUNC(midr, MIDR) +DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0) DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1) DEFINE_COPROCR_READ_FUNC(isr, ISR) DEFINE_COPROCR_READ_FUNC(clidr, CLIDR) @@ -281,6 +282,11 @@ DEFINE_COPROCR_RW_FUNCS(prrr, PRRR) DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR) DEFINE_COPROCR_RW_FUNCS(dacr, DACR) +DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0) +DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1) +DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0) +DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1) + /* * TLBI operation prototypes */ diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 4b31f1689..65e9fc1be 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -110,6 +110,9 @@ #define ID_AA64PFR0_EL1_SHIFT U(4) #define ID_AA64PFR0_EL2_SHIFT U(8) #define ID_AA64PFR0_EL3_SHIFT U(12) +#define ID_AA64PFR0_AMU_SHIFT U(44) +#define ID_AA64PFR0_AMU_LENGTH U(4) +#define ID_AA64PFR0_AMU_MASK U(0xf) #define ID_AA64PFR0_ELX_MASK U(0xf) /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ @@ -295,6 +298,7 @@ /* CPTR_EL3 definitions */ #define TCPAC_BIT (U(1) << 31) +#define TAM_BIT (U(1) << 30) #define TTA_BIT (U(1) << 20) #define TFP_BIT (U(1) << 10) #define CPTR_EL3_RESET_VAL U(0x0) @@ -302,6 +306,7 @@ /* CPTR_EL2 definitions */ #define CPTR_EL2_RES1 ((U(1) << 13) | (U(1) << 12) | (U(0x3ff))) #define CPTR_EL2_TCPAC_BIT (U(1) << 31) +#define CPTR_EL2_TAM_BIT (U(1) << 30) #define CPTR_EL2_TTA_BIT (U(1) << 20) #define CPTR_EL2_TFP_BIT (U(1) << 10) #define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 @@ -610,4 +615,28 @@ ******************************************************************************/ #define PMBLIMITR_EL1 S3_0_C9_C10_0 +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR_EL0 S3_3_C13_C2_0 +#define AMCFGR_EL0 S3_3_C13_C2_1 +#define AMCGCR_EL0 S3_3_C13_C2_2 +#define AMUSERENR_EL0 S3_3_C13_C2_3 +#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 +#define AMCNTENSET0_EL0 S3_3_C13_C2_5 +#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 +#define AMCNTENSET1_EL0 S3_3_C13_C3_1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00_EL0 S3_3_C13_C4_0 +#define AMEVCNTR01_EL0 S3_3_C13_C4_1 +#define AMEVCNTR02_EL0 S3_3_C13_C4_2 +#define AMEVCNTR03_EL0 S3_3_C13_C4_3 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00_EL0 S3_3_C13_C6_0 +#define AMEVTYPER01_EL0 S3_3_C13_C6_1 +#define AMEVTYPER02_EL0 S3_3_C13_C6_2 +#define AMEVTYPER03_EL0 S3_3_C13_C6_3 + #endif /* __ARCH_H__ */ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 46d9a1c0c..b6be16759 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -322,6 +322,11 @@ DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) +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_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) #define IS_IN_EL(x) \ diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h index 1ffe20bb3..d68c95721 100644 --- a/include/lib/cpus/aarch64/cortex_a75.h +++ b/include/lib/cpus/aarch64/cortex_a75.h @@ -19,4 +19,38 @@ /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */ #define CORTEX_A75_CORE_PWRDN_EN_MASK 0x1 +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR_EL0 S3_3_C15_C9_7 +#define CPUAMCNTENSET_EL0 S3_3_C15_C9_6 +#define CPUAMCFGR_EL0 S3_3_C15_C10_6 +#define CPUAMUSERENR_EL0 S3_3_C15_C10_7 + +/* Activity Monitor Event Counter Registers */ +#define CPUAMEVCNTR0_EL0 S3_3_C15_C9_0 +#define CPUAMEVCNTR1_EL0 S3_3_C15_C9_1 +#define CPUAMEVCNTR2_EL0 S3_3_C15_C9_2 +#define CPUAMEVCNTR3_EL0 S3_3_C15_C9_3 +#define CPUAMEVCNTR4_EL0 S3_3_C15_C9_4 + +/* Activity Monitor Event Type Registers */ +#define CPUAMEVTYPER0_EL0 S3_3_C15_C10_0 +#define CPUAMEVTYPER1_EL0 S3_3_C15_C10_1 +#define CPUAMEVTYPER2_EL0 S3_3_C15_C10_2 +#define CPUAMEVTYPER3_EL0 S3_3_C15_C10_3 +#define CPUAMEVTYPER4_EL0 S3_3_C15_C10_4 + +#define CORTEX_A75_ACTLR_AMEN_BIT (U(1) << 4) + +/* + * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are + * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are + * programmable by programming the appropriate Event count bits in + * CPUAMEVTYPER register and are disabled by default. Platforms may + * enable this with suitable programming. + */ +#define CORTEX_A75_AMU_GROUP0_MASK 0x7 +#define CORTEX_A75_AMU_GROUP1_MASK (0 << 3) + #endif /* __CORTEX_A75_H__ */ diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h new file mode 100644 index 000000000..bbefe8ff6 --- /dev/null +++ b/include/lib/extensions/amu.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __AMU_H__ +#define __AMU_H__ + +/* Enable all group 0 counters */ +#define AMU_GROUP0_COUNTERS_MASK 0xf + +void amu_enable(int el2_unused); + +#endif /* __AMU_H__ */ diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S index 1f4500cbc..4cab9e4fc 100644 --- a/lib/cpus/aarch64/cortex_a75.S +++ b/lib/cpus/aarch64/cortex_a75.S @@ -11,6 +11,33 @@ #include #include +func cortex_a75_reset_func +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el3, x0 + isb + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el2, x0 + isb + + /* Enable group0 counters */ + mov x0, #CORTEX_A75_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 + isb + + /* Enable group1 counters */ + mov x0, #CORTEX_A75_AMU_GROUP1_MASK + msr CPUAMCNTENSET_EL0, x0 + isb +#endif + ret +endfunc cortex_a75_reset_func + /* --------------------------------------------- * HW will do the cache maintenance while powering down * --------------------------------------------- @@ -47,5 +74,5 @@ func cortex_a75_cpu_reg_dump endfunc cortex_a75_cpu_reg_dump declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \ - CPU_NO_RESET_FUNC, \ + cortex_a75_reset_func, \ cortex_a75_core_pwr_dwn diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c index a8672d6ca..76e440e3d 100644 --- a/lib/el3_runtime/aarch32/context_mgmt.c +++ b/lib/el3_runtime/aarch32/context_mgmt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include @@ -132,6 +133,9 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t static void enable_extensions_nonsecure(int el2_unused) { #if IMAGE_BL32 +#if ENABLE_AMU + amu_enable(el2_unused); +#endif #endif } diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 8f1523f0d..b892729ef 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include @@ -220,6 +221,10 @@ static void enable_extensions_nonsecure(int el2_unused) #if ENABLE_SPE_FOR_LOWER_ELS spe_enable(el2_unused); #endif + +#if ENABLE_AMU + amu_enable(el2_unused); +#endif #endif } diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c new file mode 100644 index 000000000..d450bd692 --- /dev/null +++ b/lib/extensions/amu/aarch32/amu.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void amu_enable(int el2_unused) +{ + uint64_t features; + + features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; + if ((features & ID_PFR0_AMU_MASK) == 1) { + if (el2_unused) { + uint64_t v; + + /* + * Non-secure access from EL0 or EL1 to the Activity Monitor + * registers do not trap to EL2. + */ + v = read_hcptr(); + v &= ~TAM_BIT; + write_hcptr(v); + } + + /* Enable group 0 counters */ + write_amcntenset0(AMU_GROUP0_COUNTERS_MASK); + } +} diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c new file mode 100644 index 000000000..007b3494f --- /dev/null +++ b/lib/extensions/amu/aarch64/amu.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void amu_enable(int el2_unused) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT; + if ((features & ID_AA64PFR0_AMU_MASK) == 1) { + uint64_t v; + + if (el2_unused) { + /* + * CPTR_EL2.TAM: Set to zero so any accesses to + * the Activity Monitor registers do not trap to EL2. + */ + v = read_cptr_el2(); + v &= ~CPTR_EL2_TAM_BIT; + write_cptr_el2(v); + } + + /* + * CPTR_EL3.TAM: Set to zero so that any accesses to + * the Activity Monitor registers do not trap to EL3. + */ + v = read_cptr_el3(); + v &= ~TAM_BIT; + write_cptr_el3(v); + + /* Enable group 0 counters */ + write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK); + } +} diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index b7ce051b4..9f7abed1e 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -156,3 +156,5 @@ ENABLE_SPE_FOR_LOWER_ELS := 1 ifeq (${ARCH},aarch32) override ENABLE_SPE_FOR_LOWER_ELS := 0 endif + +ENABLE_AMU := 0 diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 1b502967a..7edbd3dfa 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -147,6 +147,9 @@ BL31_SOURCES += drivers/arm/smmu/smmu_v3.c \ # Disable the PSCI platform compatibility layer ENABLE_PLAT_COMPAT := 0 +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + ifneq (${ENABLE_STACK_PROTECTOR},0) PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c endif