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 <mpe@ellerman.id.au> Link: https://msgid.link/20231128132748.1990179-2-mpe@ellerman.id.au
This commit is contained in:
parent
9dbd592740
commit
e5d00aaac6
2 changed files with 43 additions and 13 deletions
|
@ -66,6 +66,40 @@ FUNC_START(check_fpu)
|
||||||
li r3,0 # Success!!!
|
li r3,0 # Success!!!
|
||||||
1: blr
|
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)
|
FUNC_START(test_fpu)
|
||||||
# r3 holds pointer to where to put the result of fork
|
# r3 holds pointer to where to put the result of fork
|
||||||
# r4 holds pointer to the pid
|
# 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 r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
|
||||||
std r5,STACK_FRAME_PARAM(2)(sp) # int *running
|
std r5,STACK_FRAME_PARAM(2)(sp) # int *running
|
||||||
|
|
||||||
bl load_fpu
|
// Load FPRs with expected values
|
||||||
nop
|
OP_REGS lfd, 8, 0, 31, r3
|
||||||
|
|
||||||
sync
|
sync
|
||||||
# Atomic DEC
|
# Atomic DEC
|
||||||
|
@ -116,8 +150,7 @@ FUNC_START(preempt_fpu)
|
||||||
bne- 1b
|
bne- 1b
|
||||||
|
|
||||||
2: ld r3,STACK_FRAME_PARAM(0)(sp)
|
2: ld r3,STACK_FRAME_PARAM(0)(sp)
|
||||||
bl check_fpu
|
bl check_all_fprs
|
||||||
nop
|
|
||||||
cmpdi r3,0
|
cmpdi r3,0
|
||||||
bne 3f
|
bne 3f
|
||||||
ld r4,STACK_FRAME_PARAM(2)(sp)
|
ld r4,STACK_FRAME_PARAM(2)(sp)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* Copyright 2015, Cyril Bur, IBM Corp.
|
* Copyright 2015, Cyril Bur, IBM Corp.
|
||||||
|
* Copyright 2023, Michael Ellerman, IBM Corp.
|
||||||
*
|
*
|
||||||
* This test attempts to see if the FPU registers change across preemption.
|
* 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
|
* There is no way to be sure preemption happened so this test just uses many
|
||||||
* the non volatile registers as it is reused from the syscall test b) There is
|
* threads and a long wait. As such, a successful test doesn't mean much but
|
||||||
* no way to be sure preemption happened so this test just uses many threads
|
* a failure is bad.
|
||||||
* and a long wait. As such, a successful test doesn't mean much but a failure
|
|
||||||
* is bad.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -30,9 +29,7 @@
|
||||||
#define THREAD_FACTOR 8
|
#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,
|
__thread double darray[32];
|
||||||
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
|
|
||||||
2.1};
|
|
||||||
|
|
||||||
int threads_starting;
|
int threads_starting;
|
||||||
int running;
|
int running;
|
||||||
|
@ -45,7 +42,7 @@ void *preempt_fpu_c(void *p)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
srand(pthread_self());
|
srand(pthread_self());
|
||||||
for (i = 0; i < 21; i++)
|
for (i = 0; i < ARRAY_SIZE(darray); i++)
|
||||||
darray[i] = rand();
|
darray[i] = rand();
|
||||||
|
|
||||||
rc = preempt_fpu(darray, &threads_starting, &running);
|
rc = preempt_fpu(darray, &threads_starting, &running);
|
||||||
|
|
Loading…
Add table
Reference in a new issue