Commit e5d00aaa authored by Michael Ellerman's avatar Michael Ellerman
Browse files

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: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20231128132748.1990179-2-mpe@ellerman.id.au
parent 9dbd5927
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -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)
+6 −9
Original line number Diff line number Diff line
// 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);