File Index
Files and directories
Sign in
FILE

vstate_ptrace.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/riscv/vector/vstate_ptrace.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <stdio.h>
  3#include <stdlib.h>
  4#include <asm/ptrace.h>
  5#include <linux/elf.h>
  6#include <sys/ptrace.h>
  7#include <sys/uio.h>
  8#include <sys/wait.h>
  9#include "../../kselftest.h"
 10#include "v_helpers.h"
 11
 12int parent_set_val, child_set_val;
 13
 14static long do_ptrace(enum __ptrace_request op, pid_t pid, long type, size_t size, void *data)
 15{
 16	struct iovec v_iovec = {
 17		.iov_len = size,
 18		.iov_base = data
 19	};
 20
 21	return ptrace(op, pid, type, &v_iovec);
 22}
 23
 24static int do_child(void)
 25{
 26	int out;
 27
 28	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL)) {
 29		ksft_perror("PTRACE_TRACEME failed\n");
 30		return EXIT_FAILURE;
 31	}
 32
 33	asm volatile (".option push\n\t"
 34		".option	arch, +v\n\t"
 35		".option	norvc\n\t"
 36		"vsetivli	x0, 1, e32, m1, ta, ma\n\t"
 37		"vmv.s.x	v31, %[in]\n\t"
 38		"ebreak\n\t"
 39		"vmv.x.s	%[out], v31\n\t"
 40		".option pop\n\t"
 41		: [out] "=r" (out)
 42		: [in] "r" (child_set_val));
 43
 44	if (out != parent_set_val)
 45		return EXIT_FAILURE;
 46
 47	return EXIT_SUCCESS;
 48}
 49
 50static void do_parent(pid_t child)
 51{
 52	int status;
 53	void *data = NULL;
 54
 55	/* Attach to the child */
 56	while (waitpid(child, &status, 0)) {
 57		if (WIFEXITED(status)) {
 58			ksft_test_result(WEXITSTATUS(status) == 0, "SETREGSET vector\n");
 59			goto out;
 60		} else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) {
 61			size_t size;
 62			void *data, *v31;
 63			struct __riscv_v_regset_state *v_regset_hdr;
 64			struct user_regs_struct *gpreg;
 65
 66			size = sizeof(*v_regset_hdr);
 67			data = malloc(size);
 68			if (!data)
 69				goto out;
 70			v_regset_hdr = (struct __riscv_v_regset_state *)data;
 71
 72			if (do_ptrace(PTRACE_GETREGSET, child, NT_RISCV_VECTOR, size, data))
 73				goto out;
 74
 75			ksft_print_msg("vlenb %ld\n", v_regset_hdr->vlenb);
 76			data = realloc(data, size + v_regset_hdr->vlenb * 32);
 77			if (!data)
 78				goto out;
 79			v_regset_hdr = (struct __riscv_v_regset_state *)data;
 80			v31 = (void *)(data + size + v_regset_hdr->vlenb * 31);
 81			size += v_regset_hdr->vlenb * 32;
 82
 83			if (do_ptrace(PTRACE_GETREGSET, child, NT_RISCV_VECTOR, size, data))
 84				goto out;
 85
 86			ksft_test_result(*(int *)v31 == child_set_val, "GETREGSET vector\n");
 87
 88			*(int *)v31 = parent_set_val;
 89			if (do_ptrace(PTRACE_SETREGSET, child, NT_RISCV_VECTOR, size, data))
 90				goto out;
 91
 92			/* move the pc forward */
 93			size = sizeof(*gpreg);
 94			data = realloc(data, size);
 95			gpreg = (struct user_regs_struct *)data;
 96
 97			if (do_ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, size, data))
 98				goto out;
 99
100			gpreg->pc += 4;
101			if (do_ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, size, data))
102				goto out;
103		}
104
105		ptrace(PTRACE_CONT, child, NULL, NULL);
106	}
107
108out:
109	free(data);
110}
111
112int main(void)
113{
114	pid_t child;
115
116	ksft_set_plan(2);
117	if (!is_vector_supported() && !is_xtheadvector_supported())
118		ksft_exit_skip("Vector not supported\n");
119
120	srandom(getpid());
121	parent_set_val = rand();
122	child_set_val = rand();
123
124	child = fork();
125	if (child < 0)
126		ksft_exit_fail_msg("Fork failed %d\n", child);
127
128	if (!child)
129		return do_child();
130
131	do_parent(child);
132
133	ksft_finished();
134}
~/ Read-only file preview.