diff options
Diffstat (limited to 'lib/extensions/amu/aarch32/amu.c')
-rw-r--r-- | lib/extensions/amu/aarch32/amu.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c index 0f75f0791..ed56dddc9 100644 --- a/lib/extensions/amu/aarch32/amu.c +++ b/lib/extensions/amu/aarch32/amu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,13 +18,17 @@ static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; -/* Check if AMUv1 for Armv8.4 or 8.6 is implemented */ -bool amu_supported(void) +/* + * Get AMU version value from pfr0. + * Return values + * ID_PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4) + * ID_PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6) + * ID_PFR0_AMU_NOT_SUPPORTED: not supported + */ +unsigned int amu_get_version(void) { - uint32_t features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; - - features &= ID_PFR0_AMU_MASK; - return ((features == 1U) || (features == 2U)); + return (unsigned int)(read_id_pfr0() >> ID_PFR0_AMU_SHIFT) & + ID_PFR0_AMU_MASK; } #if AMU_GROUP1_NR_COUNTERS @@ -43,7 +47,7 @@ bool amu_group1_supported(void) */ void amu_enable(bool el2_unused) { - if (!amu_supported()) { + if (amu_get_version() == ID_PFR0_AMU_NOT_SUPPORTED) { return; } @@ -87,12 +91,31 @@ void amu_enable(bool el2_unused) /* Enable group 1 counters */ write_amcntenset1(AMU_GROUP1_COUNTERS_MASK); #endif + + /* Initialize FEAT_AMUv1p1 features if present. */ + if (amu_get_version() < ID_PFR0_AMU_V1P1) { + return; + } + +#if AMU_RESTRICT_COUNTERS + /* + * FEAT_AMUv1p1 adds a register field to restrict access to group 1 + * counters at all but the highest implemented EL. This is controlled + * with the AMU_RESTRICT_COUNTERS compile time flag, when set, system + * register reads at lower ELs return zero. Reads from the memory + * mapped view are unaffected. + */ + VERBOSE("AMU group 1 counter access restricted.\n"); + write_amcr(read_amcr() | AMCR_CG1RZ_BIT); +#else + write_amcr(read_amcr() & ~AMCR_CG1RZ_BIT); +#endif } /* Read the group 0 counter identified by the given `idx`. */ uint64_t amu_group0_cnt_read(unsigned int idx) { - assert(amu_supported()); + assert(amu_get_version() != ID_PFR0_AMU_NOT_SUPPORTED); assert(idx < AMU_GROUP0_NR_COUNTERS); return amu_group0_cnt_read_internal(idx); @@ -101,7 +124,7 @@ uint64_t amu_group0_cnt_read(unsigned int idx) /* Write the group 0 counter identified by the given `idx` with `val` */ void amu_group0_cnt_write(unsigned int idx, uint64_t val) { - assert(amu_supported()); + assert(amu_get_version() != ID_PFR0_AMU_NOT_SUPPORTED); assert(idx < AMU_GROUP0_NR_COUNTERS); amu_group0_cnt_write_internal(idx, val); @@ -112,7 +135,7 @@ void amu_group0_cnt_write(unsigned int idx, uint64_t val) /* Read the group 1 counter identified by the given `idx` */ uint64_t amu_group1_cnt_read(unsigned int idx) { - assert(amu_supported()); + assert(amu_get_version() != ID_PFR0_AMU_NOT_SUPPORTED); assert(amu_group1_supported()); assert(idx < AMU_GROUP1_NR_COUNTERS); @@ -122,7 +145,7 @@ uint64_t amu_group1_cnt_read(unsigned int idx) /* Write the group 1 counter identified by the given `idx` with `val` */ void amu_group1_cnt_write(unsigned int idx, uint64_t val) { - assert(amu_supported()); + assert(amu_get_version() != ID_PFR0_AMU_NOT_SUPPORTED); assert(amu_group1_supported()); assert(idx < AMU_GROUP1_NR_COUNTERS); @@ -136,7 +159,7 @@ void amu_group1_cnt_write(unsigned int idx, uint64_t val) */ void amu_group1_set_evtype(unsigned int idx, unsigned int val) { - assert(amu_supported()); + assert(amu_get_version() != ID_PFR0_AMU_NOT_SUPPORTED); assert(amu_group1_supported()); assert(idx < AMU_GROUP1_NR_COUNTERS); @@ -150,7 +173,7 @@ static void *amu_context_save(const void *arg) struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; unsigned int i; - if (!amu_supported()) { + if (amu_get_version() == ID_PFR0_AMU_NOT_SUPPORTED) { return (void *)-1; } @@ -197,7 +220,7 @@ static void *amu_context_restore(const void *arg) struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; unsigned int i; - if (!amu_supported()) { + if (amu_get_version() == ID_PFR0_AMU_NOT_SUPPORTED) { return (void *)-1; } |