Add a test case that attempts to set invalid vtype value using ptrace and verifies that the 'vill' bit is set as required by the RISC-V Vector specification v1.0, Section 3.4.1.
Signed-off-by: Sergey Matyukevich geomatsi@gmail.com --- .../testing/selftests/riscv/vector/v_ptrace.c | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+)
diff --git a/tools/testing/selftests/riscv/vector/v_ptrace.c b/tools/testing/selftests/riscv/vector/v_ptrace.c index 6a8d56a5c4f4..ccda8a4dc49b 100644 --- a/tools/testing/selftests/riscv/vector/v_ptrace.c +++ b/tools/testing/selftests/riscv/vector/v_ptrace.c @@ -84,4 +84,116 @@ TEST(ptrace_rvv_not_enabled) } }
+TEST(ptrace_rvv_invalid_vtype) +{ + static volatile unsigned long vtype; + unsigned long vlenb; + unsigned long reg; + pid_t pid; + + if (!is_vector_supported()) + SKIP(return, "Vector not supported"); + + asm volatile("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb)); + + if (vlenb > 16) + SKIP(return, "This test does not support VLEN > 128"); + + chld_lock = 1; + + pid = fork(); + + ASSERT_LE(0, pid) + TH_LOG("fork: %m"); + + if (pid == 0) { + while (chld_lock == 1) + asm volatile("" : : "g"(chld_lock) : "memory"); + + asm(".option arch, +v\n"); + asm(".option arch, +c\n"); + asm volatile("vsetvli x0, x0, e8, m8, tu, mu\n"); + + while (1) { + asm volatile ("c.ebreak"); + asm volatile("csrr %[vtype], vtype" : [vtype] "=r"(vtype) : :); + asm volatile ("c.ebreak"); + } + } else { + struct __riscv_v_regset_state *regset_data; + struct user_regs_struct regs; + size_t regset_size; + struct iovec iov; + int status; + + /* attach */ + + ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL)); + ASSERT_EQ(pid, waitpid(pid, &status, 0)); + ASSERT_TRUE(WIFSTOPPED(status)); + + /* unlock */ + + ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0)); + + /* resume and wait for the 1st c.ebreak */ + + ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL)); + ASSERT_EQ(pid, waitpid(pid, &status, 0)); + ASSERT_TRUE(WIFSTOPPED(status)); + + /* read tracee vector csr regs using ptrace GETREGSET */ + + regset_size = sizeof(*regset_data) + vlenb * 32; + regset_data = calloc(1, regset_size); + + iov.iov_base = regset_data; + iov.iov_len = regset_size; + + ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov)); + + /* set invalid vtype 0x1d = (5 | 3 << 3): + * - LMUL: 1/8 + * - SEW: 64 + * - invalid configuration for VLENB <= 128 + */ + regset_data->vtype = 0x1d; + ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_RISCV_VECTOR, &iov)); + + /* skip 1st c.ebreak, then resume and wait for the 2nd c.ebreak */ + + iov.iov_base = ®s; + iov.iov_len = sizeof(regs); + + ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov)); + regs.pc += 2; + ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov)); + + ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL)); + ASSERT_EQ(pid, waitpid(pid, &status, 0)); + ASSERT_TRUE(WIFSTOPPED(status)); + + /* read tracee vtype using ptrace GETREGSET */ + + iov.iov_base = regset_data; + iov.iov_len = regset_size; + ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov)); + + /* read tracee vtype ptrace PEEKDATA */ + + errno = 0; + reg = ptrace(PTRACE_PEEKDATA, pid, &vtype, NULL); + ASSERT_FALSE((errno != 0) && (reg == -1)); + + /* verify that V state is illegal */ + + EXPECT_EQ(reg, regset_data->vtype); + EXPECT_EQ(1UL, (regset_data->vtype >> (__riscv_xlen - 1))); + + /* cleanup */ + + ASSERT_EQ(0, kill(pid, SIGKILL)); + } +} + TEST_HARNESS_MAIN