Skip to content

Commit e5d00aa

Browse files
committed
selftests/powerpc: Check all FPRs in fpu_preempt
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 <[email protected]> Link: https://msgid.link/[email protected]
1 parent 9dbd592 commit e5d00aa

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

tools/testing/selftests/powerpc/math/fpu_asm.S

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,40 @@ FUNC_START(check_fpu)
6666
li r3,0 # Success!!!
6767
1: blr
6868

69+
70+
// int check_all_fprs(double darray[32])
71+
FUNC_START(check_all_fprs)
72+
PUSH_BASIC_STACK(8)
73+
mr r4, r3 // r4 = darray
74+
li r3, 1 // prepare for failure
75+
76+
stfd f31, STACK_FRAME_LOCAL(0, 0)(sp) // backup f31
77+
78+
// Check regs f0-f30, using f31 as scratch
79+
.set i, 0
80+
.rept 31
81+
lfd f31, (8 * i)(r4) // load expected value
82+
fcmpu cr0, i, f31 // compare
83+
bne cr0, 1f // bail if mismatch
84+
.set i, i + 1
85+
.endr
86+
87+
lfd f31, STACK_FRAME_LOCAL(0, 0)(sp) // reload f31
88+
stfd f30, STACK_FRAME_LOCAL(0, 0)(sp) // backup f30
89+
90+
lfd f30, (8 * 31)(r4) // load expected value of f31
91+
fcmpu cr0, f30, f31 // compare
92+
bne cr0, 1f // bail if mismatch
93+
94+
lfd f30, STACK_FRAME_LOCAL(0, 0)(sp) // reload f30
95+
96+
// Success
97+
li r3, 0
98+
99+
1: POP_BASIC_STACK(8)
100+
blr
101+
FUNC_END(check_all_fprs)
102+
69103
FUNC_START(test_fpu)
70104
# r3 holds pointer to where to put the result of fork
71105
# r4 holds pointer to the pid
@@ -104,8 +138,8 @@ FUNC_START(preempt_fpu)
104138
std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
105139
std r5,STACK_FRAME_PARAM(2)(sp) # int *running
106140

107-
bl load_fpu
108-
nop
141+
// Load FPRs with expected values
142+
OP_REGS lfd, 8, 0, 31, r3
109143

110144
sync
111145
# Atomic DEC
@@ -116,8 +150,7 @@ FUNC_START(preempt_fpu)
116150
bne- 1b
117151

118152
2: ld r3,STACK_FRAME_PARAM(0)(sp)
119-
bl check_fpu
120-
nop
153+
bl check_all_fprs
121154
cmpdi r3,0
122155
bne 3f
123156
ld r4,STACK_FRAME_PARAM(2)(sp)

tools/testing/selftests/powerpc/math/fpu_preempt.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22
/*
33
* Copyright 2015, Cyril Bur, IBM Corp.
4+
* Copyright 2023, Michael Ellerman, IBM Corp.
45
*
56
* This test attempts to see if the FPU registers change across preemption.
6-
* Two things should be noted here a) The check_fpu function in asm only checks
7-
* the non volatile registers as it is reused from the syscall test b) There is
8-
* no way to be sure preemption happened so this test just uses many threads
9-
* and a long wait. As such, a successful test doesn't mean much but a failure
10-
* is bad.
7+
* There is no way to be sure preemption happened so this test just uses many
8+
* threads and a long wait. As such, a successful test doesn't mean much but
9+
* a failure is bad.
1110
*/
1211

1312
#include <stdio.h>
@@ -30,9 +29,7 @@
3029
#define THREAD_FACTOR 8
3130

3231

33-
__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
34-
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
35-
2.1};
32+
__thread double darray[32];
3633

3734
int threads_starting;
3835
int running;
@@ -45,7 +42,7 @@ void *preempt_fpu_c(void *p)
4542
int i;
4643

4744
srand(pthread_self());
48-
for (i = 0; i < 21; i++)
45+
for (i = 0; i < ARRAY_SIZE(darray); i++)
4946
darray[i] = rand();
5047

5148
rc = preempt_fpu(darray, &threads_starting, &running);

0 commit comments

Comments
 (0)