linux/tools/testing/selftests/riscv/vector/vstate_prctl.c
Charlie Jenkins c384c5d4a2
selftests: riscv: Support xtheadvector in vector tests
Extend existing vector tests to be compatible with the xtheadvector
instructions.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Yangyu Chen <cyy@cyyself.name>
Link: https://lore.kernel.org/r/20241113-xtheadvector-v11-13-236c22791ef9@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2025-01-18 12:33:38 -08:00

246 lines
5.9 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
#include <sys/prctl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include "../../kselftest_harness.h"
#include "v_helpers.h"
#define NEXT_PROGRAM "./vstate_exec_nolibc"
int test_and_compare_child(long provided, long expected, int inherit, int xtheadvector)
{
int rc;
rc = prctl(PR_RISCV_V_SET_CONTROL, provided);
if (rc != 0) {
printf("prctl with provided arg %lx failed with code %d\n",
provided, rc);
return -1;
}
rc = launch_test(NEXT_PROGRAM, inherit, xtheadvector);
if (rc != expected) {
printf("Test failed, check %d != %ld\n", rc, expected);
return -2;
}
return 0;
}
#define PR_RISCV_V_VSTATE_CTRL_CUR_SHIFT 0
#define PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT 2
TEST(get_control_no_v)
{
long rc;
if (is_vector_supported() || is_xtheadvector_supported())
SKIP(return, "Test expects vector to be not supported");
rc = prctl(PR_RISCV_V_GET_CONTROL);
EXPECT_EQ(-1, rc)
TH_LOG("GET_CONTROL should fail on kernel/hw without ZVE32X");
EXPECT_EQ(EINVAL, errno)
TH_LOG("GET_CONTROL should fail on kernel/hw without ZVE32X");
}
TEST(set_control_no_v)
{
long rc;
if (is_vector_supported() || is_xtheadvector_supported())
SKIP(return, "Test expects vector to be not supported");
rc = prctl(PR_RISCV_V_SET_CONTROL, PR_RISCV_V_VSTATE_CTRL_ON);
EXPECT_EQ(-1, rc)
TH_LOG("SET_CONTROL should fail on kernel/hw without ZVE32X");
EXPECT_EQ(EINVAL, errno)
TH_LOG("SET_CONTROL should fail on kernel/hw without ZVE32X");
}
TEST(vstate_on_current)
{
long flag;
long rc;
if (!is_vector_supported() && !is_xtheadvector_supported())
SKIP(return, "Vector not supported");
flag = PR_RISCV_V_VSTATE_CTRL_ON;
rc = prctl(PR_RISCV_V_SET_CONTROL, flag);
EXPECT_EQ(0, rc) TH_LOG("Enabling V for current should always succeed");
}
TEST(vstate_off_eperm)
{
long flag;
long rc;
if (!is_vector_supported() && !is_xtheadvector_supported())
SKIP(return, "Vector not supported");
flag = PR_RISCV_V_VSTATE_CTRL_OFF;
rc = prctl(PR_RISCV_V_SET_CONTROL, flag);
EXPECT_EQ(EPERM, errno)
TH_LOG("Disabling V in current thread with V enabled must fail with EPERM(%d)", errno);
EXPECT_EQ(-1, rc)
TH_LOG("Disabling V in current thread with V enabled must fail with EPERM(%d)", errno);
}
TEST(vstate_on_no_nesting)
{
long flag;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn on next's vector explicitly and test */
flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
EXPECT_EQ(0, test_and_compare_child(flag, PR_RISCV_V_VSTATE_CTRL_ON, 0, xtheadvector));
}
TEST(vstate_off_nesting)
{
long flag;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn off next's vector explicitly and test */
flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
EXPECT_EQ(0, test_and_compare_child(flag, PR_RISCV_V_VSTATE_CTRL_OFF, 1, xtheadvector));
}
TEST(vstate_on_inherit_no_nesting)
{
long flag, expected;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn on next's vector explicitly and test no inherit */
flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
expected = flag | PR_RISCV_V_VSTATE_CTRL_ON;
EXPECT_EQ(0, test_and_compare_child(flag, expected, 0, xtheadvector));
}
TEST(vstate_on_inherit)
{
long flag, expected;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn on next's vector explicitly and test inherit */
flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
expected = flag | PR_RISCV_V_VSTATE_CTRL_ON;
EXPECT_EQ(0, test_and_compare_child(flag, expected, 1, xtheadvector));
}
TEST(vstate_off_inherit_no_nesting)
{
long flag, expected;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn off next's vector explicitly and test no inherit */
flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
expected = flag | PR_RISCV_V_VSTATE_CTRL_OFF;
EXPECT_EQ(0, test_and_compare_child(flag, expected, 0, xtheadvector));
}
TEST(vstate_off_inherit)
{
long flag, expected;
int xtheadvector = 0;
if (!is_vector_supported()) {
if (is_xtheadvector_supported())
xtheadvector = 1;
else
SKIP(return, "Vector not supported");
}
/* Turn off next's vector explicitly and test inherit */
flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
expected = flag | PR_RISCV_V_VSTATE_CTRL_OFF;
EXPECT_EQ(0, test_and_compare_child(flag, expected, 1, xtheadvector));
}
/* arguments should fail with EINVAL */
TEST(inval_set_control_1)
{
int rc;
if (!is_vector_supported() && !is_xtheadvector_supported())
SKIP(return, "Vector not supported");
rc = prctl(PR_RISCV_V_SET_CONTROL, 0xff0);
EXPECT_EQ(-1, rc);
EXPECT_EQ(EINVAL, errno);
}
/* arguments should fail with EINVAL */
TEST(inval_set_control_2)
{
int rc;
if (!is_vector_supported() && !is_xtheadvector_supported())
SKIP(return, "Vector not supported");
rc = prctl(PR_RISCV_V_SET_CONTROL, 0x3);
EXPECT_EQ(-1, rc);
EXPECT_EQ(EINVAL, errno);
}
/* arguments should fail with EINVAL */
TEST(inval_set_control_3)
{
int rc;
if (!is_vector_supported() && !is_xtheadvector_supported())
SKIP(return, "Vector not supported");
rc = prctl(PR_RISCV_V_SET_CONTROL, 0xc);
EXPECT_EQ(-1, rc);
EXPECT_EQ(EINVAL, errno);
}
TEST_HARNESS_MAIN