test(rme): check various SIMD state preserved across NS/RL switch
Thie test case verifies whether various SIMD related registers like
Q[0-31], FPCR, FPSR, Z[0-31], P[0-15], FFR are preserved by RMM during
world switch between NS world and Realm world.
Randomly verify FPU registers or SVE registers if the system supports
SVE. Within SVE, randomly configure SVE vector length.
This testcase runs on below configs:
* with SVE
* without SVE
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I3fc755f75bdcdc8c24af0440d8a5f094beafca73
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index b73cc3b..1351415 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -20,6 +20,7 @@
bool test_realm_sve_probe_vl(void);
bool test_realm_sve_ops(void);
bool test_realm_sve_fill_regs(void);
+bool test_realm_sve_cmp_regs(void);
bool test_realm_sve_undef_abort(void);
#endif /* REALM_TESTS_H */
diff --git a/realm/realm.mk b/realm/realm.mk
index 23ebc0c..debbda2 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -34,7 +34,7 @@
realm_psci.c \
realm_rsi.c \
realm_shared_data.c \
- realm_sve.c \
+ realm_simd.c \
)
REALM_SOURCES += lib/${ARCH}/cache_helpers.S \
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 4eea234..43cbf2d 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -123,6 +123,9 @@
case REALM_SVE_FILL_REGS:
test_succeed = test_realm_sve_fill_regs();
break;
+ case REALM_SVE_CMP_REGS:
+ test_succeed = test_realm_sve_cmp_regs();
+ break;
case REALM_SVE_UNDEF_ABORT:
test_succeed = test_realm_sve_undef_abort();
break;
diff --git a/realm/realm_sve.c b/realm/realm_simd.c
similarity index 69%
rename from realm/realm_sve.c
rename to realm/realm_simd.c
index 098cf4c..273696b 100644
--- a/realm/realm_sve.c
+++ b/realm/realm_simd.c
@@ -10,6 +10,7 @@
#include <debug.h>
#include <stdlib.h>
#include <sync.h>
+#include <lib/extensions/fpu.h>
#include <lib/extensions/sve.h>
#include <host_realm_sve.h>
@@ -22,6 +23,16 @@
static int rl_sve_op_2[RL_SVE_OP_ARRAYSIZE];
static sve_z_regs_t rl_sve_z_regs_write;
+static sve_z_regs_t rl_sve_z_regs_read;
+
+static sve_p_regs_t rl_sve_p_regs_write;
+static sve_p_regs_t rl_sve_p_regs_read;
+
+static sve_ffr_regs_t rl_sve_ffr_regs_write;
+static sve_ffr_regs_t rl_sve_ffr_regs_read;
+
+static fpu_cs_regs_t rl_fpu_cs_regs_write;
+static fpu_cs_regs_t rl_fpu_cs_regs_read;
static int volatile realm_got_undef_abort;
@@ -118,20 +129,65 @@
/* Fill SVE Z registers with known pattern */
bool test_realm_sve_fill_regs(void)
{
- uint32_t vl;
-
assert(is_armv8_2_sve_present());
/* Config Realm with max SVE length */
sve_config_vq(SVE_VQ_ARCH_MAX);
- vl = sve_rdvl_1();
- memset((void *)&rl_sve_z_regs_write, 0xcd, vl * SVE_NUM_VECTORS);
- sve_z_regs_write(&rl_sve_z_regs_write);
+ sve_z_regs_write_rand(&rl_sve_z_regs_write);
+ sve_p_regs_write_rand(&rl_sve_p_regs_write);
+ sve_ffr_regs_write_rand(&rl_sve_ffr_regs_write);
+
+ /* fpcr, fpsr common registers */
+ fpu_cs_regs_write_rand(&rl_fpu_cs_regs_write);
return true;
}
+/* Compare SVE Z registers with last filled in values */
+bool test_realm_sve_cmp_regs(void)
+{
+ bool rc = true;
+ uint64_t bit_map;
+
+ assert(is_armv8_2_sve_present());
+
+ memset(&rl_sve_z_regs_read, 0, sizeof(rl_sve_z_regs_read));
+ memset(&rl_sve_p_regs_read, 0, sizeof(rl_sve_p_regs_read));
+ memset(&rl_sve_ffr_regs_read, 0, sizeof(rl_sve_ffr_regs_read));
+
+ /* Read all SVE registers */
+ sve_z_regs_read(&rl_sve_z_regs_read);
+ sve_p_regs_read(&rl_sve_p_regs_read);
+ sve_ffr_regs_read(&rl_sve_ffr_regs_read);
+
+ /* Compare the read values with last written values */
+ bit_map = sve_z_regs_compare(&rl_sve_z_regs_write, &rl_sve_z_regs_read);
+ if (bit_map) {
+ rc = false;
+ }
+
+ bit_map = sve_p_regs_compare(&rl_sve_p_regs_write, &rl_sve_p_regs_read);
+ if (bit_map) {
+ rc = false;
+ }
+
+ bit_map = sve_ffr_regs_compare(&rl_sve_ffr_regs_write,
+ &rl_sve_ffr_regs_read);
+ if (bit_map) {
+ rc = false;
+ }
+
+ /* fpcr, fpsr common registers */
+ fpu_cs_regs_read(&rl_fpu_cs_regs_read);
+ if (fpu_cs_regs_compare(&rl_fpu_cs_regs_write, &rl_fpu_cs_regs_read)) {
+ ERROR("Realm: FPCR/FPSR mismatch\n");
+ rc = false;
+ }
+
+ return rc;
+}
+
static bool realm_sync_exception_handler(void)
{
uint64_t esr_el1 = read_esr_el1();