Validate successful and trapped executions of GCSPUSHM, GCSPOPM.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/tcg/aarch64/gcspushm.c | 77 +++++++++++++++++++++++++++++++
tests/tcg/aarch64/Makefile.target | 2 +-
2 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/aarch64/gcspushm.c
diff --git a/tests/tcg/aarch64/gcspushm.c b/tests/tcg/aarch64/gcspushm.c
new file mode 100644
index 0000000000..0c7cc09065
--- /dev/null
+++ b/tests/tcg/aarch64/gcspushm.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gcs.h"
+
+
+#define GCSPUSHM "sys #3, c7, c7, #0, %[push]"
+#define GCSPOPM "sysl %[pop], #3, c7, c7, #1"
+
+static volatile uint64_t test_pc;
+
+static void test_sigsegv(int sig, siginfo_t *info, void *vuc)
+{
+ ucontext_t *uc = vuc;
+
+ assert(uc->uc_mcontext.pc == test_pc);
+ assert(info->si_code == SEGV_CPERR);
+ /* TODO: Dig for ESR and verify syndrome. */
+ uc->uc_mcontext.pc += 4;
+}
+
+static void test_sigill(int sig, siginfo_t *info, void *vuc)
+{
+ ucontext_t *uc = vuc;
+
+ assert(uc->uc_mcontext.pc == test_pc);
+ assert(info->si_code == ILL_ILLOPC);
+ uc->uc_mcontext.pc += 4;
+}
+
+int main()
+{
+ struct sigaction sa = { .sa_flags = SA_SIGINFO };
+ uint64_t tmp, old, new;
+
+ enable_gcs(PR_SHADOW_STACK_PUSH);
+
+ /* Valid value -- low 2 bits clear */
+ old = 0xdeadbeeffeedcaec;
+ asm volatile(GCSPUSHM "\n\t" GCSPOPM
+ : [pop] "=r" (new)
+ : [push] "r" (old));
+ assert(old == new);
+
+ sa.sa_sigaction = test_sigsegv;
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ perror("sigaction");
+ exit(1);
+ }
+
+ /* Invalid value -- SIGSEGV via EC_GCS */
+ asm volatile("adr %[tmp], 0f\n\t"
+ "str %[tmp], %[test]\n\t"
+ GCSPUSHM "\n"
+ "0:" GCSPOPM
+ : [tmp] "=&r" (tmp),
+ [test] "=m" (test_pc),
+ [pop] "=r" (new)
+ : [push] "r" (1));
+
+ enable_gcs(0);
+
+ sa.sa_sigaction = test_sigill;
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
+ perror("sigaction");
+ exit(1);
+ }
+
+ /* Pushm is disabled -- SIGILL via EC_SYSTEMREGISTERTRAP */
+ asm volatile("adr %[tmp], 0f\n\t"
+ "str %[tmp], %[test]\n"
+ "0:\t" GCSPUSHM
+ : [tmp] "=&r" (tmp),
+ [test] "=m" (test_pc)
+ : [push] "r" (1));
+
+ exit(0);
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index 0347a36e8d..c6f401c317 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -76,7 +76,7 @@ $(SME_TESTS): CFLAGS += $(CROSS_AS_HAS_ARMV9_SME)
endif
# GCS Tests
-GCS_TESTS += gcsstr
+GCS_TESTS += gcsstr gcspushm
AARCH64_TESTS += $(GCS_TESTS)
$(GCS_TESTS): gcs.h
--
2.43.0