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) */
+}