feat(amu): test AMU counter restriction (RAZ)
When using AMU counters, there is risk of exposing information to
lower exception levels. In order to prevent this, counters are
restricted, so they are read as zero (RAZ) at a lower EL. This
test verifies that counters are read as zero after forcing counting
through instructions that trigger MPMM "gear shifting" (e.g.: by
executing SVE instructions).
Note: This test applies to TC2 only, as it is the only platform that
supports MPMM currently.
Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Change-Id: Ic32ba19fa489cf479947d4467ddb84e6abd1b454
diff --git a/tftf/tests/extensions/amu/test_amu.c b/tftf/tests/extensions/amu/test_amu.c
index 8d5c92b..21305a7 100644
--- a/tftf/tests/extensions/amu/test_amu.c
+++ b/tftf/tests/extensions/amu/test_amu.c
@@ -16,7 +16,8 @@
#include <tftf_lib.h>
#include <timer.h>
-#define SUSPEND_TIME_1_SEC 1000
+#define SUSPEND_TIME_1_SEC 1000
+#define MAX_MPMM_TEST_ITERATIONS 100000U
static volatile int wakeup_irq_received[PLATFORM_CORE_COUNT];
@@ -242,3 +243,53 @@
return TEST_RESULT_SUCCESS;
}
+
+/*
+ * Check that group 1 counters read as 0 at ELs lower than EL3 when
+ * AMCR.CG1RZ is set.
+ */
+test_result_t test_amu_group1_raz(void)
+{
+/* Test on TC2 only, as MPMM not implemented in other platforms yet */
+#if PLAT_tc && (TARGET_PLATFORM == 2)
+ uint64_t counters_initial[AMU_GROUP1_NR_COUNTERS] = {0};
+ uint64_t counters_final[AMU_GROUP1_NR_COUNTERS] = {0};
+
+ for (unsigned int i = 0; i < amu_group1_num_counters(); i++) {
+ INFO("AMUEVTYPER1%x: 0x%llx\n", i, amu_group1_evtype_read(i));
+ counters_initial[i] = amu_group1_cnt_read(i);
+ }
+
+ for (int i = 0; i < MAX_MPMM_TEST_ITERATIONS; i++) {
+ // Instruction with activity count 1
+ __asm__ volatile("fmov d0,xzr");
+ __asm__ volatile("fmov d1,xzr");
+ __asm__ volatile("fmul d2,d0,d1");
+ __asm__ volatile("fmov d2,xzr");
+
+ __asm__ volatile("fmov d0,xzr");
+ __asm__ volatile("fmov d1,xzr");
+ __asm__ volatile("fmov d2,xzr");
+ __asm__ volatile("fmadd d3,d2,d1,d0");
+
+ // Instruction with activity count 2
+ __asm__ volatile("ptrue p0.s, ALL");
+ __asm__ volatile("index z10.s, #10,13");
+ __asm__ volatile("index z11.s, #12,7");
+ __asm__ volatile("ucvtf v10.4s, v10.4s");
+ __asm__ volatile("ucvtf v11.4s, v11.4s");
+ __asm__ volatile("fadd v0.4s, v10.4s, v11.4s");
+ }
+
+ for (unsigned int i = 0; i < amu_group1_num_counters(); i++) {
+ counters_final[i] = amu_group1_cnt_read(i);
+ if (counters_final[i] == counters_initial[i]) {
+ return TEST_RESULT_FAIL;
+ }
+ }
+
+ return TEST_RESULT_SUCCESS;
+#else
+ return TEST_RESULT_SKIPPED;
+#endif /* PLAT_tc && (TARGET_PLATFORM == 2) */
+}
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 3b93344..bd6abdd 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -11,6 +11,7 @@
<testsuite name="CPU extensions" description="Various CPU extensions tests">
<testcase name="AMUv1 valid counter values" function="test_amu_valid_ctr" />
<testcase name="AMUv1 suspend/resume" function="test_amu_suspend_resume" />
+ <testcase name="AMUv1 group 1 RAZ" function="test_amu_group1_raz" />
<testcase name="SVE support" function="test_sve_support" />
<testcase name="Access Pointer Authentication Registers" function="test_pauth_reg_access" />
<testcase name="Use Pointer Authentication Instructions" function="test_pauth_instructions" />