There's a selftest that checks FPRs aren't corrupted by preemption, or
just process scheduling. However it only checks the non-volatile FPRs,
meaning corruption of the volatile FPRs could go undetected.

The check_fpu function it calls is used by several other tests, so for
now add a new routine to check all the FPRs. Increase the size of the
array of FPRs to 32, and initialise them all with random values.

Signed-off-by: Michael Ellerman <m...@ellerman.id.au>
---
 .../testing/selftests/powerpc/math/fpu_asm.S  | 41 +++++++++++++++++--
 .../selftests/powerpc/math/fpu_preempt.c      | 15 +++----
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S 
b/tools/testing/selftests/powerpc/math/fpu_asm.S
index 9dc0c158f871..051392ad3ce7 100644
--- a/tools/testing/selftests/powerpc/math/fpu_asm.S
+++ b/tools/testing/selftests/powerpc/math/fpu_asm.S
@@ -66,6 +66,40 @@ FUNC_START(check_fpu)
        li      r3,0 # Success!!!
 1:     blr
 
+
+// int check_all_fprs(double darray[32])
+FUNC_START(check_all_fprs)
+       PUSH_BASIC_STACK(8)
+       mr      r4, r3  // r4 = darray
+       li      r3, 1   // prepare for failure
+
+       stfd    f31, STACK_FRAME_LOCAL(0, 0)(sp) // backup f31
+
+       // Check regs f0-f30, using f31 as scratch
+       .set i, 0
+       .rept 31
+       lfd     f31, (8 * i)(r4)        // load expected value
+       fcmpu   cr0, i, f31             // compare
+       bne     cr0, 1f                 // bail if mismatch
+       .set i, i + 1
+       .endr
+
+       lfd     f31, STACK_FRAME_LOCAL(0, 0)(sp) // reload f31
+       stfd    f30, STACK_FRAME_LOCAL(0, 0)(sp) // backup f30
+
+       lfd     f30, (8 * 31)(r4)       // load expected value of f31
+       fcmpu   cr0, f30, f31           // compare
+       bne     cr0, 1f                 // bail if mismatch
+
+       lfd     f30, STACK_FRAME_LOCAL(0, 0)(sp) // reload f30
+
+       // Success
+       li      r3, 0
+
+1:     POP_BASIC_STACK(8)
+       blr
+FUNC_END(check_all_fprs)
+
 FUNC_START(test_fpu)
        # r3 holds pointer to where to put the result of fork
        # r4 holds pointer to the pid
@@ -104,8 +138,8 @@ FUNC_START(preempt_fpu)
        std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
        std r5,STACK_FRAME_PARAM(2)(sp) # int *running
 
-       bl load_fpu
-       nop
+       // Load FPRs with expected values
+       OP_REGS lfd, 8, 0, 31, r3
 
        sync
        # Atomic DEC
@@ -116,8 +150,7 @@ FUNC_START(preempt_fpu)
        bne- 1b
 
 2:     ld r3,STACK_FRAME_PARAM(0)(sp)
-       bl check_fpu
-       nop
+       bl check_all_fprs
        cmpdi r3,0
        bne 3f
        ld r4,STACK_FRAME_PARAM(2)(sp)
diff --git a/tools/testing/selftests/powerpc/math/fpu_preempt.c 
b/tools/testing/selftests/powerpc/math/fpu_preempt.c
index 3e5b5663d244..24b5abacccdc 100644
--- a/tools/testing/selftests/powerpc/math/fpu_preempt.c
+++ b/tools/testing/selftests/powerpc/math/fpu_preempt.c
@@ -1,13 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2015, Cyril Bur, IBM Corp.
+ * Copyright 2023, Michael Ellerman, IBM Corp.
  *
  * This test attempts to see if the FPU registers change across preemption.
- * Two things should be noted here a) The check_fpu function in asm only checks
- * the non volatile registers as it is reused from the syscall test b) There is
- * no way to be sure preemption happened so this test just uses many threads
- * and a long wait. As such, a successful test doesn't mean much but a failure
- * is bad.
+ * There is no way to be sure preemption happened so this test just uses many
+ * threads and a long wait. As such, a successful test doesn't mean much but
+ * a failure is bad.
  */
 
 #include <stdio.h>
@@ -30,9 +29,7 @@
 #define THREAD_FACTOR 8
 
 
-__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
-                    1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
-                    2.1};
+__thread double darray[32];
 
 int threads_starting;
 int running;
@@ -45,7 +42,7 @@ void *preempt_fpu_c(void *p)
        int i;
 
        srand(pthread_self());
-       for (i = 0; i < 21; i++)
+       for (i = 0; i < ARRAY_SIZE(darray); i++)
                darray[i] = rand();
 
        rc = preempt_fpu(darray, &threads_starting, &running);
-- 
2.41.0

Reply via email to