Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests/powerpc: Check all FPRs in fpu_syscall test

There is a selftest that checks if FPRs are corrupted across a fork, aka
clone. It was added as part of the series that optimised the clone path
to save the parent's FP state without "giving up" (turning off FP).

See commit 8792468da5e1 ("powerpc: Add the ability to save FPU without
giving it up").

The test encodes the assumption that FPRs 0-13 are volatile across the
syscall, by only checking the volatile FPRs are not changed by the fork.
There was also a comment in the fpu_preempt test alluding to that:

The check_fpu function in asm only checks the non volatile registers
as it is reused from the syscall test

It is true that the function call ABI treats f0-f13 as volatile,
however the syscall ABI has since been documented as *not* treating those
registers as volatile. See commit 7b8845a2a2ec ("powerpc/64: Document
the syscall ABI").

So change the test to check all FPRs are not corrupted by the syscall.
Note that this currently fails, because save_fpu() etc. do not restore
f0/vsr0.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20231128132748.1990179-5-mpe@ellerman.id.au

+9 -6
+4 -3
tools/testing/selftests/powerpc/math/fpu_asm.S
··· 109 109 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray 110 110 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid 111 111 112 - bl load_fpu 113 - nop 112 + // Load FPRs with expected values 113 + OP_REGS lfd, 8, 0, 31, r3 114 + 114 115 li r0,__NR_fork 115 116 sc 116 117 ··· 120 119 std r3,0(r9) 121 120 122 121 ld r3,STACK_FRAME_PARAM(0)(sp) 123 - bl check_fpu 122 + bl check_all_fprs 124 123 nop 125 124 126 125 POP_FPU(256)
+5 -3
tools/testing/selftests/powerpc/math/fpu_syscall.c
··· 14 14 #include <stdlib.h> 15 15 16 16 #include "utils.h" 17 + #include "fpu.h" 17 18 18 19 extern int test_fpu(double *darray, pid_t *pid); 19 20 20 - double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 21 - 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 22 - 2.1}; 21 + double darray[32]; 23 22 24 23 int syscall_fpu(void) 25 24 { ··· 26 27 int i; 27 28 int ret; 28 29 int child_ret; 30 + 31 + randomise_darray(darray, ARRAY_SIZE(darray)); 32 + 29 33 for (i = 0; i < 1000; i++) { 30 34 /* test_fpu will fork() */ 31 35 ret = test_fpu(darray, &fork_pid);