selftests/powerpc: Fix prefixes in alignment_handler signal handler
authorJordan Niethe <jniethe5@gmail.com>
Mon, 24 Aug 2020 13:12:31 +0000 (23:12 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 8 Sep 2020 12:24:20 +0000 (22:24 +1000)
The signal handler in the alignment handler self test has the ability
to jump over the instruction that triggered the signal. It does this
by incrementing the PT_NIP in the user context by 4. If it were a
prefixed instruction this will mean that the suffix is then executed
which is incorrect. Instead check if the major opcode indicates a
prefixed instruction (e.g. it is 1) and if so increment PT_NIP by 8.

If ISA v3.1 is not available treat it as a word instruction even if
the major opcode is 1.

Fixes: 620a6473df36 ("selftests/powerpc: Add prefixed loads/stores to alignment_handler test")
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
[mpe: Fix 32-bit build, rename haveprefixes to prefixes_enabled]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200824131231.14008-1-jniethe5@gmail.com
tools/testing/selftests/powerpc/alignment/alignment_handler.c

index e4063eb..2a0503b 100644 (file)
@@ -62,6 +62,7 @@ int bufsize;
 int debug;
 int testing;
 volatile int gotsig;
+bool prefixes_enabled;
 char *cipath = "/dev/fb0";
 long cioffset;
 
@@ -75,7 +76,12 @@ void sighandler(int sig, siginfo_t *info, void *ctx)
        }
        gotsig = sig;
 #ifdef __powerpc64__
-       ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
+       if (prefixes_enabled) {
+               u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP];
+               ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4);
+       } else {
+               ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
+       }
 #else
        ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
 #endif
@@ -646,6 +652,8 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+       prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1);
+
        rc |= test_harness(test_alignment_handler_vsx_206,
                           "test_alignment_handler_vsx_206");
        rc |= test_harness(test_alignment_handler_vsx_207,