summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/powerpc/security
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2020-08-19 04:57:21 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2020-09-08 15:23:57 +0300
commitd89002397cfb2b65267d6688fe671ee1cf7c5f0d (patch)
treefa3e99d14245c84ac73a46f8c05d739c69aeff74 /tools/testing/selftests/powerpc/security
parent17c98a541dc9bb1162877af41cddbdca043f9a59 (diff)
downloadlinux-d89002397cfb2b65267d6688fe671ee1cf7c5f0d.tar.xz
selftests/powerpc: Move set_dscr() into rfi_flush.c
This version of set_dscr() was added for the RFI flush test, and is fairly specific to it. It also clashes with the version of set_dscr() in dscr/dscr.h. So move it into the RFI flush test where it's used. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200819015727.1977134-3-mpe@ellerman.id.au
Diffstat (limited to 'tools/testing/selftests/powerpc/security')
-rw-r--r--tools/testing/selftests/powerpc/security/rfi_flush.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c
index 0a7d0afb26b8..fd37ff9b1c45 100644
--- a/tools/testing/selftests/powerpc/security/rfi_flush.c
+++ b/tools/testing/selftests/powerpc/security/rfi_flush.c
@@ -10,6 +10,7 @@
#include <stdint.h>
#include <malloc.h>
#include <unistd.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -41,6 +42,40 @@ static void syscall_loop(char *p, unsigned long iterations,
}
}
+static void sigill_handler(int signr, siginfo_t *info, void *unused)
+{
+ static int warned = 0;
+ ucontext_t *ctx = (ucontext_t *)unused;
+ unsigned long *pc = &UCONTEXT_NIA(ctx);
+
+ /* mtspr 3,RS to check for move to DSCR below */
+ if ((*((unsigned int *)*pc) & 0xfc1fffff) == 0x7c0303a6) {
+ if (!warned++)
+ printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n");
+ *pc += 4;
+ } else {
+ printf("SIGILL at %p\n", pc);
+ abort();
+ }
+}
+
+static void set_dscr(unsigned long val)
+{
+ static int init = 0;
+ struct sigaction sa;
+
+ if (!init) {
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = sigill_handler;
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGILL, &sa, NULL))
+ perror("sigill_handler");
+ init = 1;
+ }
+
+ asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
+}
+
int rfi_flush_test(void)
{
char *p;