linux-stable/tools/testing/selftests/powerpc/math/vmx_syscall.c
Michael Ellerman 872d11bca9 selftests/powerpc: Skip vmx/vsx/tar/etc tests on older CPUs
Some of our tests use VSX or newer VMX instructions, so need to be
skipped on older CPUs to avoid SIGILL'ing.

Similarly TAR was added in v2.07, and the PMU event used in the stcx
fail test only works on Power8 or later.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200803020719.96114-1-mpe@ellerman.id.au
2020-08-03 22:12:41 +10:00

92 lines
1.7 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2015, Cyril Bur, IBM Corp.
*
* This test attempts to see if the VMX registers change across a syscall (fork).
*/
#include <altivec.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "utils.h"
vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
{13,14,15,16},{17,18,19,20},{21,22,23,24},
{25,26,27,28},{29,30,31,32},{33,34,35,36},
{37,38,39,40},{41,42,43,44},{45,46,47,48}};
extern int test_vmx(vector int *varray, pid_t *pid);
int vmx_syscall(void)
{
pid_t fork_pid;
int i;
int ret;
int child_ret;
for (i = 0; i < 1000; i++) {
/* test_vmx will fork() */
ret = test_vmx(varray, &fork_pid);
if (fork_pid == -1)
return -1;
if (fork_pid == 0)
exit(ret);
waitpid(fork_pid, &child_ret, 0);
if (ret || child_ret)
return 1;
}
return 0;
}
int test_vmx_syscall(void)
{
/*
* Setup an environment with much context switching
*/
pid_t pid2;
pid_t pid;
int ret;
int child_ret;
// vcmpequd used in vmx_asm.S is v2.07
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
pid = fork();
FAIL_IF(pid == -1);
pid2 = fork();
ret = vmx_syscall();
/* Can't FAIL_IF(pid2 == -1); because we've already forked */
if (pid2 == -1) {
/*
* Couldn't fork, ensure child_ret is set and is a fail
*/
ret = child_ret = 1;
} else {
if (pid2)
waitpid(pid2, &child_ret, 0);
else
exit(ret);
}
ret |= child_ret;
if (pid)
waitpid(pid, &child_ret, 0);
else
exit(ret);
FAIL_IF(ret || child_ret);
return 0;
}
int main(int argc, char *argv[])
{
return test_harness(test_vmx_syscall, "vmx_syscall");
}