aboutsummaryrefslogtreecommitdiff
path: root/lib/extensions/amu/aarch32/amu.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/extensions/amu/aarch32/amu.c')
-rw-r--r--lib/extensions/amu/aarch32/amu.c53
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;
}