feat(WFxT): add a test for WFxT instructions
This patch adds the test to verify the WFET and WFIT instructions
introduced by FEAT_WFxT.
WFET and WFIT instructions assist in generating local-timeout event
and thereby act as wakeup event for the PE, when the virtual count
in CNTVCT_EL0 (counter-timer virtual count) register equals or exceed
the timeout value passed with these instructions.
Accordingly, this testcase verifies whether the time lapsed matches the
value supplied with WFET and WFIT instructions.
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
Change-Id: I9aea5da869db8520e305e49989cb71f166a582eb
diff --git a/tftf/tests/extensions/wfxt/test_wfxt.c b/tftf/tests/extensions/wfxt/test_wfxt.c
new file mode 100644
index 0000000..bb3e486
--- /dev/null
+++ b/tftf/tests/extensions/wfxt/test_wfxt.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+typedef enum {
+ EXEC_WFIT = 0,
+ EXEC_WFET
+} exec_wfxt;
+
+#ifdef __aarch64__
+static test_result_t test_wfxt_inst(exec_wfxt val, uint64_t ms)
+{
+ __asm__ volatile(".arch armv8.7-a");
+ uint64_t timer_cnt1, timer_cnt2, feed_cnt;
+ uint64_t timer_freq = read_cntfrq_el0();
+ uint64_t ms_to_counts = ((ms * timer_freq) / 1000U);
+
+ timer_cnt1 = virtualcounter_read();
+ feed_cnt = timer_cnt1 + ms_to_counts;
+
+ if (val == EXEC_WFIT) {
+ wfit(feed_cnt);
+ } else {
+ wfet(feed_cnt);
+ }
+
+ timer_cnt2 = virtualcounter_read();
+
+ /* Lapsed time should be at least equal to sleep time */
+ if ((timer_cnt2 - timer_cnt1) >= ms_to_counts) {
+ return TEST_RESULT_SUCCESS;
+ } else {
+ /* unlikely ends up here */
+ uint64_t lapsed_ms = ((timer_cnt2 - timer_cnt1) * 1000) / timer_freq;
+
+ ERROR("Time elapsed: actual(%llu)ms vs requested(%llu)ms \n",
+ lapsed_ms, ms);
+ return TEST_RESULT_FAIL;
+ }
+}
+#endif /* __aarch64__ */
+
+test_result_t test_wfet_instruction(void)
+{
+ SKIP_TEST_IF_AARCH32();
+
+#ifdef __aarch64__
+ SKIP_TEST_IF_WFXT_NOT_SUPPORTED();
+
+ /*
+ * first invocation of wfe returns immediately clearing the event
+ * register
+ */
+ sevl();
+ wfe();
+
+ return test_wfxt_inst(EXEC_WFET, 10);
+#endif /* __aarch64__ */
+}
+
+test_result_t test_wfit_instruction(void)
+{
+ test_result_t ret;
+
+ SKIP_TEST_IF_AARCH32();
+
+#ifdef __aarch64__
+ SKIP_TEST_IF_WFXT_NOT_SUPPORTED();
+
+ /* disable irqs to run wfi till timeout */
+ disable_irq();
+
+ ret = test_wfxt_inst(EXEC_WFIT, 10);
+
+ /* enable irq back */
+ enable_irq();
+#endif /* __aarch64__ */
+
+ return ret;
+}
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 0719486..061ab7e 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -19,6 +19,7 @@
extensions/sys_reg_trace/test_sys_reg_trace.c \
extensions/trbe/test_trbe.c \
extensions/trf/test_trf.c \
+ extensions/wfxt/test_wfxt.c \
runtime_services/arm_arch_svc/smccc_arch_soc_id.c \
runtime_services/arm_arch_svc/smccc_arch_workaround_1.c \
runtime_services/arm_arch_svc/smccc_arch_workaround_2.c \
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index ba85866..bc84659 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -27,6 +27,8 @@
<testcase name="SME support" function="test_sme_support" />
<testcase name="SPE support" function="test_spe_support" />
<testcase name="AFP support" function="test_afp_support" />
+ <testcase name="Test wfit instruction" function="test_wfit_instruction" />
+ <testcase name="Test wfet instruction" function="test_wfet_instruction" />
</testsuite>
<testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">