Enable v8.6 AMU enhancements (FEAT_AMUv1p1)
ARMv8.6 adds virtual offset registers to support virtualization of the
event counters in EL1 and EL0. This patch enables support for this
feature in EL3 firmware.
Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I7ee1f3d9f554930bf5ef6f3d492e932e6d95b217
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index 0f75f07..ed56ddd 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 @@
*/
void amu_enable(bool el2_unused)
{
- if (!amu_supported()) {
+ if (amu_get_version() == ID_PFR0_AMU_NOT_SUPPORTED) {
return;
}
@@ -87,12 +91,31 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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_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 @@
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 @@
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;
}
diff --git a/lib/extensions/amu/aarch32/amu_helpers.S b/lib/extensions/amu/aarch32/amu_helpers.S
index effb8e5..d387341 100644
--- a/lib/extensions/amu/aarch32/amu_helpers.S
+++ b/lib/extensions/amu/aarch32/amu_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -75,13 +75,13 @@
1:
stcopr16 r2, r3, AMEVCNTR00 /* index 0 */
- bx lr
+ bx lr
stcopr16 r2, r3, AMEVCNTR01 /* index 1 */
- bx lr
+ bx lr
stcopr16 r2, r3, AMEVCNTR02 /* index 2 */
- bx lr
+ bx lr
stcopr16 r2, r3, AMEVCNTR03 /* index 3 */
- bx lr
+ bx lr
endfunc amu_group0_cnt_write_internal
/*
@@ -169,37 +169,37 @@
bx r1
1:
- stcopr16 r2, r3, AMEVCNTR10 /* index 0 */
+ stcopr16 r2, r3, AMEVCNTR10 /* index 0 */
bx lr
- stcopr16 r2, r3, AMEVCNTR11 /* index 1 */
+ stcopr16 r2, r3, AMEVCNTR11 /* index 1 */
bx lr
- stcopr16 r2, r3, AMEVCNTR12 /* index 2 */
+ stcopr16 r2, r3, AMEVCNTR12 /* index 2 */
bx lr
- stcopr16 r2, r3, AMEVCNTR13 /* index 3 */
+ stcopr16 r2, r3, AMEVCNTR13 /* index 3 */
bx lr
- stcopr16 r2, r3, AMEVCNTR14 /* index 4 */
+ stcopr16 r2, r3, AMEVCNTR14 /* index 4 */
bx lr
- stcopr16 r2, r3, AMEVCNTR15 /* index 5 */
+ stcopr16 r2, r3, AMEVCNTR15 /* index 5 */
bx lr
- stcopr16 r2, r3, AMEVCNTR16 /* index 6 */
+ stcopr16 r2, r3, AMEVCNTR16 /* index 6 */
bx lr
- stcopr16 r2, r3, AMEVCNTR17 /* index 7 */
+ stcopr16 r2, r3, AMEVCNTR17 /* index 7 */
bx lr
- stcopr16 r2, r3, AMEVCNTR18 /* index 8 */
+ stcopr16 r2, r3, AMEVCNTR18 /* index 8 */
bx lr
- stcopr16 r2, r3, AMEVCNTR19 /* index 9 */
+ stcopr16 r2, r3, AMEVCNTR19 /* index 9 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1A /* index 10 */
+ stcopr16 r2, r3, AMEVCNTR1A /* index 10 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1B /* index 11 */
+ stcopr16 r2, r3, AMEVCNTR1B /* index 11 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1C /* index 12 */
+ stcopr16 r2, r3, AMEVCNTR1C /* index 12 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1D /* index 13 */
+ stcopr16 r2, r3, AMEVCNTR1D /* index 13 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1E /* index 14 */
+ stcopr16 r2, r3, AMEVCNTR1E /* index 14 */
bx lr
- stcopr16 r2, r3, AMEVCNTR1F /* index 15 */
+ stcopr16 r2, r3, AMEVCNTR1F /* index 15 */
bx lr
endfunc amu_group1_cnt_write_internal
@@ -234,36 +234,36 @@
bx r2
1:
- stcopr r1, AMEVTYPER10 /* index 0 */
+ stcopr r1, AMEVTYPER10 /* index 0 */
bx lr
- stcopr r1, AMEVTYPER11 /* index 1 */
+ stcopr r1, AMEVTYPER11 /* index 1 */
bx lr
- stcopr r1, AMEVTYPER12 /* index 2 */
+ stcopr r1, AMEVTYPER12 /* index 2 */
bx lr
- stcopr r1, AMEVTYPER13 /* index 3 */
+ stcopr r1, AMEVTYPER13 /* index 3 */
bx lr
- stcopr r1, AMEVTYPER14 /* index 4 */
+ stcopr r1, AMEVTYPER14 /* index 4 */
bx lr
- stcopr r1, AMEVTYPER15 /* index 5 */
+ stcopr r1, AMEVTYPER15 /* index 5 */
bx lr
- stcopr r1, AMEVTYPER16 /* index 6 */
+ stcopr r1, AMEVTYPER16 /* index 6 */
bx lr
- stcopr r1, AMEVTYPER17 /* index 7 */
+ stcopr r1, AMEVTYPER17 /* index 7 */
bx lr
- stcopr r1, AMEVTYPER18 /* index 8 */
+ stcopr r1, AMEVTYPER18 /* index 8 */
bx lr
- stcopr r1, AMEVTYPER19 /* index 9 */
+ stcopr r1, AMEVTYPER19 /* index 9 */
bx lr
- stcopr r1, AMEVTYPER1A /* index 10 */
+ stcopr r1, AMEVTYPER1A /* index 10 */
bx lr
- stcopr r1, AMEVTYPER1B /* index 11 */
+ stcopr r1, AMEVTYPER1B /* index 11 */
bx lr
- stcopr r1, AMEVTYPER1C /* index 12 */
+ stcopr r1, AMEVTYPER1C /* index 12 */
bx lr
- stcopr r1, AMEVTYPER1D /* index 13 */
+ stcopr r1, AMEVTYPER1D /* index 13 */
bx lr
- stcopr r1, AMEVTYPER1E /* index 14 */
+ stcopr r1, AMEVTYPER1E /* index 14 */
bx lr
- stcopr r1, AMEVTYPER1F /* index 15 */
+ stcopr r1, AMEVTYPER1F /* index 15 */
bx lr
endfunc amu_group1_set_evtype_internal