public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases
@ 2025-12-14 16:35 Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension Sergey Matyukevich
                   ` (10 more replies)
  0 siblings, 11 replies; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

This patch series suggests fixes for several corner cases in the RISC-V
vector ptrace implementation:

- init vector context with proper vlenb, to avoid reading zero vlenb
  by an early attached debugger

- follow gdbserver expectations and return ENODATA instead of EINVAL
  if vector extension is supported but not yet activated for the
  traced process

- validate input vector csr registers in ptrace, to maintain an accurate
  view of the tracee's vector context across multiple halt/resume
  debug cycles

For detailed description see the appropriate commit messages. A new test
suite validate_v_ptrace is added to the tools/testing/selftests/riscv/vector
to verify some of the vector ptrace functionality and corner cases.

So far tested on the following platforms:
- test in QEMU rv32/rv64
- test on c908 (BananaPi CanMV K230D Zero)
- test on c906 (MangoPi MQ Pro)

Previous versions:
- v4: https://lore.kernel.org/linux-riscv/20251108194207.1257866-1-geomatsi@gmail.com/T/#u
- v3: https://lore.kernel.org/linux-riscv/20251025210655.43099-1-geomatsi@gmail.com/T/#u
- v2: https://lore.kernel.org/linux-riscv/20250821173957.563472-1-geomatsi@gmail.com/T/#u
- v1: https://lore.kernel.org/linux-riscv/20251007115840.2320557-1-geomatsi@gmail.com/T/#u

Changes in v5:
- add support and minimal set of tests for XTheadVector

Changes in v4:
The form 'vsetvli x0, x0, ...' can only be used if VLMAX remains
unchanged, see spec 6.2. This condition was not met by the initial
values in the selftests w.r.t. the initial zeroed context. QEMU accepted
such values, but actual hardware (c908, BananaPi CanMV Zero board) did
not, setting vill. So fix the selftests after testing on hardware:
- replace 'vsetvli x0, x0, ...' by 'vsetvli rd, x0, ...' 
- fixed instruction returns VLMAX, so use it in checks as well
- replace fixed vlenb == 16 in the syscall test

Changes in v3:
Address the review comments by Andy Chiu and rework the approach:
- drop forced vector context save entirely
- perform strict validation of vector csr regs in ptrace

Changes in v2:
- add thread_info flag to allow to force vector context save
- force vector context save after vector ptrace to ensure valid vector
  context in the next ptrace operations
- force vector context save on the first context switch after vector
  context init to get proper vlenb

---

Ilya Mamay (1):
  riscv: ptrace: return ENODATA for inactive vector extension

Sergey Matyukevich (8):
  riscv: vector: init vector context with proper vlenb
  riscv: csr: define vtype register elements
  riscv: ptrace: validate input vector csr registers
  selftests: riscv: test ptrace vector interface
  selftests: riscv: verify initial vector state with ptrace
  selftests: riscv: verify syscalls discard vector context
  selftests: riscv: verify ptrace rejects invalid vector csr inputs
  selftests: riscv: verify ptrace accepts valid vector csr values

 arch/riscv/include/asm/csr.h                  |  17 +
 arch/riscv/kernel/ptrace.c                    |  98 +-
 arch/riscv/kernel/vector.c                    |  12 +-
 .../testing/selftests/riscv/vector/.gitignore |   2 +
 tools/testing/selftests/riscv/vector/Makefile |  10 +-
 .../selftests/riscv/vector/v_helpers.c        |  23 +
 .../selftests/riscv/vector/v_helpers.h        |   2 +
 .../riscv/vector/validate_v_ptrace.c          | 919 ++++++++++++++++++
 8 files changed, 1075 insertions(+), 8 deletions(-)
 create mode 100644 tools/testing/selftests/riscv/vector/validate_v_ptrace.c


base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
-- 
2.52.0


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-07  6:48   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb Sergey Matyukevich
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich, Ilya Mamay

From: Ilya Mamay <mmamayka01@gmail.com>

Currently, ptrace returns EINVAL when the vector extension is supported
but not yet activated for the traced process. This error code is not
always appropriate since the ptrace arguments may be valid.

Debug tools like gdbserver expect ENODATA when the requested register
set is not active, e.g. see [1]. This expectation seems to be more
appropriate, so modify the vector ptrace implementation to return:
- EINVAL when V extension is not supported
- ENODATA when V extension is supported but not active

[1] https://github.com/bminor/binutils-gdb/blob/637f25e88675fa47e47f9cc5e2cf37384836b8a2/gdbserver/linux-low.cc#L5020

Signed-off-by: Ilya Mamay <mmamayka01@gmail.com>
Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 arch/riscv/kernel/ptrace.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index e6272d74572f..9d203fb84f5e 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -95,9 +95,12 @@ static int riscv_vr_get(struct task_struct *target,
 	struct __riscv_v_ext_state *vstate = &target->thread.vstate;
 	struct __riscv_v_regset_state ptrace_vstate;
 
-	if (!riscv_v_vstate_query(task_pt_regs(target)))
+	if (!(has_vector() || has_xtheadvector()))
 		return -EINVAL;
 
+	if (!riscv_v_vstate_query(task_pt_regs(target)))
+		return -ENODATA;
+
 	/*
 	 * Ensure the vector registers have been saved to the memory before
 	 * copying them to membuf.
@@ -130,9 +133,12 @@ static int riscv_vr_set(struct task_struct *target,
 	struct __riscv_v_ext_state *vstate = &target->thread.vstate;
 	struct __riscv_v_regset_state ptrace_vstate;
 
-	if (!riscv_v_vstate_query(task_pt_regs(target)))
+	if (!(has_vector() || has_xtheadvector()))
 		return -EINVAL;
 
+	if (!riscv_v_vstate_query(task_pt_regs(target)))
+		return -ENODATA;
+
 	/* Copy rest of the vstate except datap */
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
 				 sizeof(struct __riscv_v_regset_state));
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-07  6:49   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 3/9] riscv: csr: define vtype register elements Sergey Matyukevich
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

The vstate in thread_struct is zeroed when the vector context is
initialized. That includes read-only register vlenb, which holds
the vector register length in bytes. Zeroed state persists until
mstatus.VS becomes 'dirty' and a context switch saves the actual
hardware values.

This can expose the zero vlenb value to the user-space in early
debug scenarios, e.g. when ptrace attaches to a traced process
early, before any vector instruction except the first one was
executed.

Fix this by specifying proper vlenb on vector context init.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 arch/riscv/kernel/vector.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
index 3ed071dab9d8..b112166d51e9 100644
--- a/arch/riscv/kernel/vector.c
+++ b/arch/riscv/kernel/vector.c
@@ -111,8 +111,8 @@ bool insn_is_vector(u32 insn_buf)
 	return false;
 }
 
-static int riscv_v_thread_zalloc(struct kmem_cache *cache,
-				 struct __riscv_v_ext_state *ctx)
+static int riscv_v_thread_ctx_alloc(struct kmem_cache *cache,
+				    struct __riscv_v_ext_state *ctx)
 {
 	void *datap;
 
@@ -122,13 +122,15 @@ static int riscv_v_thread_zalloc(struct kmem_cache *cache,
 
 	ctx->datap = datap;
 	memset(ctx, 0, offsetof(struct __riscv_v_ext_state, datap));
+	ctx->vlenb = riscv_v_vsize / 32;
+
 	return 0;
 }
 
 void riscv_v_thread_alloc(struct task_struct *tsk)
 {
 #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
-	riscv_v_thread_zalloc(riscv_v_kernel_cachep, &tsk->thread.kernel_vstate);
+	riscv_v_thread_ctx_alloc(riscv_v_kernel_cachep, &tsk->thread.kernel_vstate);
 #endif
 }
 
@@ -214,12 +216,14 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
 	 * context where VS has been off. So, try to allocate the user's V
 	 * context and resume execution.
 	 */
-	if (riscv_v_thread_zalloc(riscv_v_user_cachep, &current->thread.vstate)) {
+	if (riscv_v_thread_ctx_alloc(riscv_v_user_cachep, &current->thread.vstate)) {
 		force_sig(SIGBUS);
 		return true;
 	}
+
 	riscv_v_vstate_on(regs);
 	riscv_v_vstate_set_restore(current, regs);
+
 	return true;
 }
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 3/9] riscv: csr: define vtype register elements
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-21 21:04   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers Sergey Matyukevich
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Define masks and shifts for vtype CSR according to the vector specs:
- v0.7.1 used in early T-Head cores, known as xtheadvector in the kernel
- v1.0

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 arch/riscv/include/asm/csr.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 4a37a98398ad..38f16538b35c 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -444,6 +444,23 @@
 #define CSR_VTYPE		0xc21
 #define CSR_VLENB		0xc22
 
+#define VTYPE_VLMUL		_AC(7, UL)
+#define VTYPE_VLMUL_FRAC	_AC(4, UL)
+#define VTYPE_VSEW_SHIFT	3
+#define VTYPE_VSEW		(_AC(7, UL) << VTYPE_VSEW_SHIFT)
+#define VTYPE_VTA_SHIFT		6
+#define VTYPE_VTA		(_AC(1, UL) << VTYPE_VTA_SHIFT)
+#define VTYPE_VMA_SHIFT		7
+#define VTYPE_VMA		(_AC(1, UL) << VTYPE_VMA_SHIFT)
+#define VTYPE_VILL_SHIFT	(__riscv_xlen - 1)
+#define VTYPE_VILL		(_AC(1, UL) << VTYPE_VILL_SHIFT)
+
+#define VTYPE_VLMUL_THEAD	_AC(3, UL)
+#define VTYPE_VSEW_THEAD_SHIFT  2
+#define VTYPE_VSEW_THEAD	(_AC(7, UL) << VTYPE_VSEW_THEAD_SHIFT)
+#define VTYPE_VEDIV_THEAD_SHIFT	5
+#define VTYPE_VEDIV_THEAD	(_AC(3, UL) << VTYPE_VEDIV_THEAD_SHIFT)
+
 /* Scalar Crypto Extension - Entropy */
 #define CSR_SEED		0x015
 #define SEED_OPST_MASK		_AC(0xC0000000, UL)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (2 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 3/9] riscv: csr: define vtype register elements Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-21 21:07   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 5/9] selftests: riscv: test ptrace vector interface Sergey Matyukevich
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add strict validation for vector csr registers when setting them via
ptrace:
- reject attempts to set reserved bits or invalid field combinations
- enforce strict VL checks against calculated VLMAX values

Vector specs 0.7.1 and 1.0 allow normal applications to set candidate
VL values and read back the hardware-adjusted results, see section 6
for details. Disallow such flexibility in vector ptrace operations
and strictly enforce valid VL input.

The traced process may not update its saved vector context if no vector
instructions execute between breakpoints. So the purpose of the strict
ptrace approach is to make sure that debuggers maintain an accurate view
of the tracee's vector context across multiple halt/resume debug cycles.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 arch/riscv/kernel/ptrace.c | 88 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 9d203fb84f5e..5d18fe241697 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -124,6 +124,92 @@ static int riscv_vr_get(struct task_struct *target,
 	return membuf_write(&to, vstate->datap, riscv_v_vsize);
 }
 
+static int invalid_ptrace_v_csr(struct __riscv_v_ext_state *vstate,
+				struct __riscv_v_regset_state *ptrace)
+{
+	unsigned long vsew, vlmul, vfrac, vl;
+	unsigned long elen, vlen;
+	unsigned long sew, lmul;
+	unsigned long reserved;
+
+	vlen = vstate->vlenb * 8;
+	if (vstate->vlenb != ptrace->vlenb)
+		return 1;
+
+	/* do not allow to set vcsr/vxrm/vxsat reserved bits */
+	reserved = ~(CSR_VXSAT_MASK | (CSR_VXRM_MASK << CSR_VXRM_SHIFT));
+	if (ptrace->vcsr & reserved)
+		return 1;
+
+	if (has_vector()) {
+		/* do not allow to set vtype reserved bits and vill bit */
+		reserved = ~(VTYPE_VSEW | VTYPE_VLMUL | VTYPE_VMA | VTYPE_VTA);
+		if (ptrace->vtype & reserved)
+			return 1;
+
+		elen = riscv_has_extension_unlikely(RISCV_ISA_EXT_ZVE64X) ? 64 : 32;
+		vsew = (ptrace->vtype & VTYPE_VSEW) >> VTYPE_VSEW_SHIFT;
+		sew = 8 << vsew;
+
+		if (sew > elen)
+			return 1;
+
+		vfrac = (ptrace->vtype & VTYPE_VLMUL_FRAC);
+		vlmul = (ptrace->vtype & VTYPE_VLMUL);
+
+		/* RVV 1.0 spec 3.4.2: VLMUL(0x4) reserved */
+		if (vlmul == 4)
+			return 1;
+
+		/* RVV 1.0 spec 3.4.2: (LMUL < SEW_min / ELEN) reserved */
+		if (vlmul == 5 && elen == 32)
+			return 1;
+
+		/* for zero vl verify that at least one element is possible */
+		vl = ptrace->vl ? ptrace->vl : 1;
+
+		if (vfrac) {
+			/* integer 1/LMUL: VL =< VLMAX = VLEN / SEW / LMUL */
+			lmul = 2 << (3 - (vlmul - vfrac));
+			if (vlen < vl * sew * lmul)
+				return 1;
+		} else {
+			/* integer LMUL: VL =< VLMAX = LMUL * VLEN / SEW */
+			lmul = 1 << vlmul;
+			if (vl * sew > lmul * vlen)
+				return 1;
+		}
+	}
+
+	if (has_xtheadvector()) {
+		/* do not allow to set vtype reserved bits and vill bit */
+		reserved = ~(VTYPE_VSEW_THEAD | VTYPE_VLMUL_THEAD | VTYPE_VEDIV_THEAD);
+		if (ptrace->vtype & reserved)
+			return 1;
+
+		/*
+		 * THead ISA Extension spec chapter 16:
+		 * divided element extension ('Zvediv') is not part of XTheadVector
+		 */
+		if (ptrace->vtype & VTYPE_VEDIV_THEAD)
+			return 1;
+
+		vsew = (ptrace->vtype & VTYPE_VSEW_THEAD) >> VTYPE_VSEW_THEAD_SHIFT;
+		sew = 8 << vsew;
+
+		vlmul = (ptrace->vtype & VTYPE_VLMUL_THEAD);
+		lmul = 1 << vlmul;
+
+		/* for zero vl verify that at least one element is possible */
+		vl = ptrace->vl ? ptrace->vl : 1;
+
+		if (vl * sew > lmul * vlen)
+			return 1;
+	}
+
+	return 0;
+}
+
 static int riscv_vr_set(struct task_struct *target,
 			const struct user_regset *regset,
 			unsigned int pos, unsigned int count,
@@ -145,7 +231,7 @@ static int riscv_vr_set(struct task_struct *target,
 	if (unlikely(ret))
 		return ret;
 
-	if (vstate->vlenb != ptrace_vstate.vlenb)
+	if (invalid_ptrace_v_csr(vstate, &ptrace_vstate))
 		return -EINVAL;
 
 	vstate->vstart = ptrace_vstate.vstart;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 5/9] selftests: riscv: test ptrace vector interface
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (3 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace Sergey Matyukevich
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add a test case to check ptrace behavior in the case when vector
extension is supported by the system, but vector context is not
yet enabled for the traced process.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
Reviewed-by: Andy Chiu <andybnac@gmail.com>
---
 .../testing/selftests/riscv/vector/.gitignore |  2 +
 tools/testing/selftests/riscv/vector/Makefile | 10 ++-
 .../selftests/riscv/vector/v_helpers.c        | 23 ++++++
 .../selftests/riscv/vector/v_helpers.h        |  2 +
 .../riscv/vector/validate_v_ptrace.c          | 80 +++++++++++++++++++
 5 files changed, 116 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/riscv/vector/validate_v_ptrace.c

diff --git a/tools/testing/selftests/riscv/vector/.gitignore b/tools/testing/selftests/riscv/vector/.gitignore
index 7d9c87cd0649..40a82baf364f 100644
--- a/tools/testing/selftests/riscv/vector/.gitignore
+++ b/tools/testing/selftests/riscv/vector/.gitignore
@@ -2,3 +2,5 @@ vstate_exec_nolibc
 vstate_prctl
 v_initval
 v_exec_initval_nolibc
+vstate_ptrace
+validate_v_ptrace
diff --git a/tools/testing/selftests/riscv/vector/Makefile b/tools/testing/selftests/riscv/vector/Makefile
index 2c2a33fc083e..326dafd739bf 100644
--- a/tools/testing/selftests/riscv/vector/Makefile
+++ b/tools/testing/selftests/riscv/vector/Makefile
@@ -2,11 +2,14 @@
 # Copyright (C) 2021 ARM Limited
 # Originally tools/testing/arm64/abi/Makefile
 
-TEST_GEN_PROGS := v_initval vstate_prctl vstate_ptrace
+TEST_GEN_PROGS := v_initval vstate_prctl vstate_ptrace validate_v_ptrace
 TEST_GEN_PROGS_EXTENDED := vstate_exec_nolibc v_exec_initval_nolibc
+TEST_GEN_LIBS := v_helpers.c sys_hwprobe.c
 
 include ../../lib.mk
 
+TEST_GEN_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(TEST_GEN_LIBS))
+
 $(OUTPUT)/sys_hwprobe.o: ../hwprobe/sys_hwprobe.S
 	$(CC) -static -c -o$@ $(CFLAGS) $^
 
@@ -29,3 +32,8 @@ $(OUTPUT)/v_exec_initval_nolibc: v_exec_initval_nolibc.c
 
 $(OUTPUT)/vstate_ptrace: vstate_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
 	$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
+
+$(OUTPUT)/validate_v_ptrace: validate_v_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
+	$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
+
+EXTRA_CLEAN += $(TEST_GEN_OBJ)
diff --git a/tools/testing/selftests/riscv/vector/v_helpers.c b/tools/testing/selftests/riscv/vector/v_helpers.c
index 01a8799dcb78..de6da7c8d2f1 100644
--- a/tools/testing/selftests/riscv/vector/v_helpers.c
+++ b/tools/testing/selftests/riscv/vector/v_helpers.c
@@ -26,6 +26,29 @@ bool is_vector_supported(void)
 	return pair.value & RISCV_HWPROBE_EXT_ZVE32X;
 }
 
+unsigned long get_vr_len(void)
+{
+	unsigned long vlenb;
+
+	if (is_vector_supported()) {
+		asm volatile("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb));
+		return vlenb;
+	}
+
+	if (is_xtheadvector_supported()) {
+		asm volatile (
+			// 0 | zimm[10:0] | rs1 | 1 1 1 | rd | 1010111 | vsetvli
+			// vsetvli	t4, x0, e8, m1, d1
+			".4byte		0b00000000000000000111111011010111\n\t"
+			"mv		%[vlenb], t4\n\t"
+			: [vlenb] "=r"(vlenb) : : "memory", "t4");
+		return vlenb;
+	}
+
+	printf("WARNING: vector not supported\n");
+	return 0;
+}
+
 int launch_test(char *next_program, int test_inherit, int xtheadvector)
 {
 	char *exec_argv[4], *exec_envp[1];
diff --git a/tools/testing/selftests/riscv/vector/v_helpers.h b/tools/testing/selftests/riscv/vector/v_helpers.h
index 763cddfe26da..c538077f1195 100644
--- a/tools/testing/selftests/riscv/vector/v_helpers.h
+++ b/tools/testing/selftests/riscv/vector/v_helpers.h
@@ -5,4 +5,6 @@ bool is_xtheadvector_supported(void);
 
 bool is_vector_supported(void);
 
+unsigned long get_vr_len(void);
+
 int launch_test(char *next_program, int test_inherit, int xtheadvector);
diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
new file mode 100644
index 000000000000..b64986b42270
--- /dev/null
+++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/ptrace.h>
+#include <linux/elf.h>
+
+#include "kselftest_harness.h"
+#include "v_helpers.h"
+
+volatile unsigned long chld_lock;
+
+TEST(ptrace_v_not_enabled)
+{
+	pid_t pid;
+
+	if (!(is_vector_supported() || is_xtheadvector_supported()))
+		SKIP(return, "Vector not supported");
+
+	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 volatile ("ebreak" : : : );
+	} else {
+		struct __riscv_v_regset_state *regset_data;
+		unsigned long vlenb = get_vr_len();
+		size_t regset_size;
+		struct iovec iov;
+		int status;
+		int ret;
+
+		/* 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 ebreak */
+
+		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
+		ASSERT_EQ(pid, waitpid(pid, &status, 0));
+		ASSERT_TRUE(WIFSTOPPED(status));
+
+		/* try to read vector registers from the tracee */
+
+		regset_size = sizeof(*regset_data) + vlenb * 32;
+		regset_data = calloc(1, regset_size);
+
+		iov.iov_base = regset_data;
+		iov.iov_len = regset_size;
+
+		/* V extension is available, but not yet enabled for the tracee */
+
+		errno = 0;
+		ret = ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov);
+		ASSERT_EQ(ENODATA, errno);
+		ASSERT_EQ(-1, ret);
+
+		/* cleanup */
+
+		ASSERT_EQ(0, kill(pid, SIGKILL));
+	}
+}
+
+TEST_HARNESS_MAIN
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (4 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 5/9] selftests: riscv: test ptrace vector interface Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-21 21:33   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context Sergey Matyukevich
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add a test case that attaches to a traced process immediately after its
first executed vector instructions to verify the initial vector context.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 .../riscv/vector/validate_v_ptrace.c          | 135 ++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
index b64986b42270..a8d64d351edd 100644
--- a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
+++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
@@ -13,6 +13,9 @@
 #include "kselftest_harness.h"
 #include "v_helpers.h"
 
+#define SR_FS_DIRTY	0x00006000UL
+#define CSR_VXRM_SHIFT	1
+
 volatile unsigned long chld_lock;
 
 TEST(ptrace_v_not_enabled)
@@ -77,4 +80,136 @@ TEST(ptrace_v_not_enabled)
 	}
 }
 
+TEST(ptrace_v_early_debug)
+{
+	static volatile unsigned long vstart;
+	static volatile unsigned long vtype;
+	static volatile unsigned long vlenb;
+	static volatile unsigned long vcsr;
+	static volatile unsigned long vl;
+	bool xtheadvector;
+	pid_t pid;
+
+	if (!(is_vector_supported() || is_xtheadvector_supported()))
+		SKIP(return, "Vector not supported");
+
+	xtheadvector = is_xtheadvector_supported();
+
+	chld_lock = 1;
+	pid = fork();
+	ASSERT_LE(0, pid)
+		TH_LOG("fork: %m");
+
+	if (pid == 0) {
+		unsigned long vxsat, vxrm;
+
+		vlenb = get_vr_len();
+
+		while (chld_lock == 1)
+			asm volatile ("" : : "g"(chld_lock) : "memory");
+
+		asm volatile (
+			"csrr %[vstart], vstart\n"
+			"csrr %[vtype], vtype\n"
+			"csrr %[vl], vl\n"
+			: [vtype] "=r"(vtype), [vstart] "=r"(vstart), [vl] "=r"(vl)
+			:
+			: "memory");
+
+		/* no 'is_xtheadvector_supported()' here to avoid clobbering v-state by syscall */
+		if (xtheadvector) {
+			asm volatile (
+				"csrs sstatus, %[bit]\n"
+				"csrr %[vxsat], vxsat\n"
+				"csrr %[vxrm], vxrm\n"
+				: [vxsat] "=r"(vxsat), [vxrm] "=r"(vxrm)
+				: [bit] "r" (SR_FS_DIRTY)
+				: "memory");
+			vcsr = vxsat | vxrm << CSR_VXRM_SHIFT;
+		} else {
+			asm volatile (
+				"csrr %[vcsr], vcsr\n"
+				: [vcsr] "=r"(vcsr)
+				:
+				: "memory");
+		}
+
+		asm volatile (
+			".option push\n"
+			".option norvc\n"
+			"ebreak\n"
+			".option pop\n");
+	} else {
+		struct __riscv_v_regset_state *regset_data;
+		unsigned long vstart_csr;
+		unsigned long vlenb_csr;
+		unsigned long vtype_csr;
+		unsigned long vcsr_csr;
+		unsigned long vl_csr;
+		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 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 PEEKDATA */
+
+		errno = 0;
+		vstart_csr = ptrace(PTRACE_PEEKDATA, pid, &vstart, NULL);
+		ASSERT_FALSE((errno != 0) && (vstart_csr == -1));
+
+		errno = 0;
+		vl_csr = ptrace(PTRACE_PEEKDATA, pid, &vl, NULL);
+		ASSERT_FALSE((errno != 0) && (vl_csr == -1));
+
+		errno = 0;
+		vtype_csr = ptrace(PTRACE_PEEKDATA, pid, &vtype, NULL);
+		ASSERT_FALSE((errno != 0) && (vtype_csr == -1));
+
+		errno = 0;
+		vcsr_csr = ptrace(PTRACE_PEEKDATA, pid, &vcsr, NULL);
+		ASSERT_FALSE((errno != 0) && (vcsr_csr == -1));
+
+		errno = 0;
+		vlenb_csr = ptrace(PTRACE_PEEKDATA, pid, &vlenb, NULL);
+		ASSERT_FALSE((errno != 0) && (vlenb_csr == -1));
+
+		/* read tracee csr regs using ptrace GETREGSET */
+
+		regset_size = sizeof(*regset_data) + vlenb_csr * 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));
+
+		/* compare */
+
+		EXPECT_EQ(vstart_csr, regset_data->vstart);
+		EXPECT_EQ(vtype_csr, regset_data->vtype);
+		EXPECT_EQ(vlenb_csr, regset_data->vlenb);
+		EXPECT_EQ(vcsr_csr, regset_data->vcsr);
+		EXPECT_EQ(vl_csr, regset_data->vl);
+
+		/* cleanup */
+
+		ASSERT_EQ(0, kill(pid, SIGKILL));
+	}
+}
+
 TEST_HARNESS_MAIN
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (5 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-21 21:37   ` Andy Chiu
  2025-12-14 16:35 ` [PATCH v5 8/9] selftests: riscv: verify ptrace rejects invalid vector csr inputs Sergey Matyukevich
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add a test to v_ptrace test suite to verify that vector csr registers
are clobbered on syscalls.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 .../riscv/vector/validate_v_ptrace.c          | 124 ++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
index a8d64d351edd..2dd0c727e520 100644
--- a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
+++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
@@ -212,4 +212,128 @@ TEST(ptrace_v_early_debug)
 	}
 }
 
+TEST(ptrace_v_syscall_clobbering)
+{
+	pid_t pid;
+
+	if (!is_vector_supported() && !is_xtheadvector_supported())
+		SKIP(return, "Vector not supported");
+
+	chld_lock = 1;
+	pid = fork();
+	ASSERT_LE(0, pid)
+		TH_LOG("fork: %m");
+
+	if (pid == 0) {
+		unsigned long vl;
+
+		while (chld_lock == 1)
+			asm volatile("" : : "g"(chld_lock) : "memory");
+
+		if (is_xtheadvector_supported()) {
+			asm volatile (
+				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
+				// vsetvli	t4, x0, e16, m2, d1
+				".4byte		0b00000000010100000111111011010111\n"
+				"mv		%[new_vl], t4\n"
+				: [new_vl] "=r" (vl) : : "t4");
+		} else {
+			asm volatile (
+				".option push\n"
+				".option arch, +zve32x\n"
+				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
+				".option pop\n"
+				: [new_vl] "=r"(vl) : : );
+		}
+
+		while (1) {
+			asm volatile (
+				".option push\n"
+				".option norvc\n"
+				"ebreak\n"
+				".option pop\n");
+
+			sleep(0);
+		}
+	} else {
+		struct __riscv_v_regset_state *regset_data;
+		unsigned long vlenb = get_vr_len();
+		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 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));
+
+		/* verify initial vsetvli settings */
+
+		if (is_xtheadvector_supported()) {
+			EXPECT_EQ(5UL, regset_data->vtype);
+		} else {
+			EXPECT_EQ(9UL, regset_data->vtype);
+		}
+
+		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
+		EXPECT_EQ(vlenb, regset_data->vlenb);
+		EXPECT_EQ(0UL, regset_data->vstart);
+		EXPECT_EQ(0UL, regset_data->vcsr);
+
+		/* skip 1st ebreak, then resume and wait for the 2nd ebreak */
+
+		iov.iov_base = &regs;
+		iov.iov_len = sizeof(regs);
+
+		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
+		regs.pc += 4;
+		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));
+
+		/* verify that V state is illegal after syscall */
+
+		EXPECT_EQ((1UL << (__riscv_xlen - 1)), regset_data->vtype);
+		EXPECT_EQ(vlenb, regset_data->vlenb);
+		EXPECT_EQ(0UL, regset_data->vstart);
+		EXPECT_EQ(0UL, regset_data->vcsr);
+		EXPECT_EQ(0UL, regset_data->vl);
+
+		/* cleanup */
+
+		ASSERT_EQ(0, kill(pid, SIGKILL));
+	}
+}
+
 TEST_HARNESS_MAIN
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 8/9] selftests: riscv: verify ptrace rejects invalid vector csr inputs
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (6 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2025-12-14 16:35 ` [PATCH v5 9/9] selftests: riscv: verify ptrace accepts valid vector csr values Sergey Matyukevich
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add a test to v_ptrace test suite to verify that ptrace rejects the
invalid input combinations of vector csr registers. Use kselftest
fixture variants to create multiple invalid inputs for the test.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 .../riscv/vector/validate_v_ptrace.c          | 318 ++++++++++++++++++
 1 file changed, 318 insertions(+)

diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
index 2dd0c727e520..623b13e7582e 100644
--- a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
+++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
@@ -336,4 +336,322 @@ TEST(ptrace_v_syscall_clobbering)
 	}
 }
 
+FIXTURE(v_csr_invalid)
+{
+};
+
+FIXTURE_SETUP(v_csr_invalid)
+{
+}
+
+FIXTURE_TEARDOWN(v_csr_invalid)
+{
+}
+
+#define VECTOR_1_0		(1UL << 0)
+#define XTHEAD_VECTOR_0_7	(1UL << 1)
+
+#define vector_test(x)		((x) & VECTOR_1_0)
+#define xthead_test(x)		((x) & XTHEAD_VECTOR_0_7)
+
+/* modifications of the initial vsetvli settings */
+FIXTURE_VARIANT(v_csr_invalid)
+{
+	unsigned long vstart;
+	unsigned long vl;
+	unsigned long vtype;
+	unsigned long vcsr;
+	unsigned long vlenb_mul;
+	unsigned long vlenb_min;
+	unsigned long vlenb_max;
+	unsigned long spec;
+};
+
+/* unexpected vlenb value */
+FIXTURE_VARIANT_ADD(v_csr_invalid, new_vlenb)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x3,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x2,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
+};
+
+/* invalid reserved bits in vcsr */
+FIXTURE_VARIANT_ADD(v_csr_invalid, vcsr_invalid_reserved_bits)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x3,
+	.vcsr = 0x1UL << 8,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
+};
+
+/* invalid reserved bits in vtype */
+FIXTURE_VARIANT_ADD(v_csr_invalid, vtype_invalid_reserved_bits)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = (0x1UL << 8) | 0x3,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
+};
+
+/* set vill bit */
+FIXTURE_VARIANT_ADD(v_csr_invalid, invalid_vill_bit)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = (0x1UL << (__riscv_xlen - 1)) | 0x3,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
+};
+
+/* reserved vsew value: vsew > 3 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vsew)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x4UL << 3,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0,
+};
+
+/* XTheadVector: unsupported non-zero VEDIV value */
+FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vediv)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x3UL << 5,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = XTHEAD_VECTOR_0_7,
+};
+
+/* reserved vlmul value: vlmul == 4 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vlmul)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x4,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0,
+};
+
+/* invalid fractional LMUL for VLEN <= 256: LMUL= 1/8, SEW = 64 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, frac_lmul1)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x1d,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x20,
+	.spec = VECTOR_1_0,
+};
+
+/* invalid integral LMUL for VLEN <= 16: LMUL= 2, SEW = 64 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, int_lmul1)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x19,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x2,
+	.spec = VECTOR_1_0,
+};
+
+/* XTheadVector: invalid integral LMUL for VLEN <= 16: LMUL= 2, SEW = 64 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, int_lmul2)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0xd,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x2,
+	.spec = XTHEAD_VECTOR_0_7,
+};
+
+/* invalid VL for VLEN <= 128: LMUL= 2, SEW = 64, VL = 8 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, vl1)
+{
+	.vstart = 0x0,
+	.vl = 0x8,
+	.vtype = 0x19,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x10,
+	.spec = VECTOR_1_0,
+};
+
+/* XTheadVector: invalid VL for VLEN <= 128: LMUL= 2, SEW = 64, VL = 8 */
+FIXTURE_VARIANT_ADD(v_csr_invalid, vl2)
+{
+	.vstart = 0x0,
+	.vl = 0x8,
+	.vtype = 0xd,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x0,
+	.vlenb_max = 0x10,
+	.spec = XTHEAD_VECTOR_0_7,
+};
+
+TEST_F(v_csr_invalid, ptrace_v_invalid_values)
+{
+	unsigned long vlenb;
+	pid_t pid;
+
+	if (!is_vector_supported() && !is_xtheadvector_supported())
+		SKIP(return, "Vectors not supported");
+
+	if (is_vector_supported() && !vector_test(variant->spec))
+		SKIP(return, "Test not supported for Vector");
+
+	if (is_xtheadvector_supported() && !xthead_test(variant->spec))
+		SKIP(return, "Test not supported for XTheadVector");
+
+	vlenb = get_vr_len();
+
+	if (variant->vlenb_min) {
+		if (vlenb < variant->vlenb_min)
+			SKIP(return, "This test does not support VLEN < %lu\n",
+			     variant->vlenb_min * 8);
+	}
+
+	if (variant->vlenb_max) {
+		if (vlenb > variant->vlenb_max)
+			SKIP(return, "This test does not support VLEN > %lu\n",
+			     variant->vlenb_max * 8);
+	}
+
+	chld_lock = 1;
+	pid = fork();
+	ASSERT_LE(0, pid)
+		TH_LOG("fork: %m");
+
+	if (pid == 0) {
+		unsigned long vl;
+
+		while (chld_lock == 1)
+			asm volatile("" : : "g"(chld_lock) : "memory");
+
+		if (is_xtheadvector_supported()) {
+			asm volatile (
+				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
+				// vsetvli	t4, x0, e16, m2, d1
+				".4byte		0b00000000010100000111111011010111\n"
+				"mv		%[new_vl], t4\n"
+				: [new_vl] "=r" (vl) : : "t4");
+		} else {
+			asm volatile (
+				".option push\n"
+				".option arch, +zve32x\n"
+				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
+				".option pop\n"
+				: [new_vl] "=r"(vl) : : );
+		}
+
+		while (1) {
+			asm volatile (
+				".option push\n"
+				".option norvc\n"
+				"ebreak\n"
+				"nop\n"
+				".option pop\n");
+		}
+	} else {
+		struct __riscv_v_regset_state *regset_data;
+		size_t regset_size;
+		struct iovec iov;
+		int status;
+		int ret;
+
+		/* 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 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));
+
+		/* verify initial vsetvli settings */
+
+		if (is_xtheadvector_supported()) {
+			EXPECT_EQ(5UL, regset_data->vtype);
+		} else {
+			EXPECT_EQ(9UL, regset_data->vtype);
+		}
+
+		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
+		EXPECT_EQ(vlenb, regset_data->vlenb);
+		EXPECT_EQ(0UL, regset_data->vstart);
+		EXPECT_EQ(0UL, regset_data->vcsr);
+
+		/* apply invalid settings from fixture variants */
+
+		regset_data->vlenb *= variant->vlenb_mul;
+		regset_data->vstart = variant->vstart;
+		regset_data->vtype = variant->vtype;
+		regset_data->vcsr = variant->vcsr;
+		regset_data->vl = variant->vl;
+
+		iov.iov_base = regset_data;
+		iov.iov_len = regset_size;
+
+		errno = 0;
+		ret = ptrace(PTRACE_SETREGSET, pid, NT_RISCV_VECTOR, &iov);
+		ASSERT_EQ(errno, EINVAL);
+		ASSERT_EQ(ret, -1);
+
+		/* cleanup */
+
+		ASSERT_EQ(0, kill(pid, SIGKILL));
+	}
+}
+
 TEST_HARNESS_MAIN
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 9/9] selftests: riscv: verify ptrace accepts valid vector csr values
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (7 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 8/9] selftests: riscv: verify ptrace rejects invalid vector csr inputs Sergey Matyukevich
@ 2025-12-14 16:35 ` Sergey Matyukevich
  2026-01-21 21:47 ` [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Andy Chiu
  2026-01-24  8:30 ` patchwork-bot+linux-riscv
  10 siblings, 0 replies; 19+ messages in thread
From: Sergey Matyukevich @ 2025-12-14 16:35 UTC (permalink / raw)
  To: linux-riscv, linux-kernel, linux-kselftest
  Cc: Paul Walmsley, Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov,
	Shuah Khan, Thomas Huth, Charlie Jenkins, Andy Chiu,
	Samuel Holland, Joel Granados, Conor Dooley, Yong-Xuan Wang,
	Heiko Stuebner, Guo Ren, Sergey Matyukevich

Add a test to v_ptrace test suite to verify that ptrace accepts the
valid input combinations of vector csr registers. Use kselftest
fixture variants to create multiple inputs for the test.

The test simulates a debug scenario with three breakpoints:
0. init: let the tracee set up its initial vector configuration
1. 1st bp:  modify the tracee's vector csr registers from the debugger
  - resume the tracee to execute a block without vector instructions
2. 2nd bp: read back the tracees's vector csr registers from the debugger
  - compare with values set by the debugger
  - resume the tracee to execute a block with vector instructions
3. 3rd bp: read back the tracess's vector csr registers again
  - compare with values set by the debugger

The last check helps to confirm that ptrace validation check for vector
csr registers input values works properly and maintains an accurate view
of the tracee's vector context in debugger.

Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
---
 .../riscv/vector/validate_v_ptrace.c          | 262 ++++++++++++++++++
 1 file changed, 262 insertions(+)

diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
index 623b13e7582e..c72533a331de 100644
--- a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
+++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
@@ -654,4 +654,266 @@ TEST_F(v_csr_invalid, ptrace_v_invalid_values)
 	}
 }
 
+FIXTURE(v_csr_valid)
+{
+};
+
+FIXTURE_SETUP(v_csr_valid)
+{
+}
+
+FIXTURE_TEARDOWN(v_csr_valid)
+{
+}
+
+/* modifications of the initial vsetvli settings */
+FIXTURE_VARIANT(v_csr_valid)
+{
+	unsigned long vstart;
+	unsigned long vl;
+	unsigned long vtype;
+	unsigned long vcsr;
+	unsigned long vlenb_mul;
+	unsigned long vlenb_min;
+	unsigned long vlenb_max;
+	unsigned long spec;
+};
+
+/* valid for VLEN >= 128: LMUL= 1/4, SEW = 32 */
+FIXTURE_VARIANT_ADD(v_csr_valid, frac_lmul1)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x16,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x10,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0,
+};
+
+/* valid for VLEN >= 16: LMUL= 2, SEW = 32 */
+FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul1)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x11,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x2,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0,
+};
+
+/* valid for XTheadVector VLEN >= 16: LMUL= 2, SEW = 32 */
+FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul2)
+{
+	.vstart = 0x0,
+	.vl = 0x0,
+	.vtype = 0x9,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x2,
+	.vlenb_max = 0x0,
+	.spec = XTHEAD_VECTOR_0_7,
+};
+
+/* valid for VLEN >= 32: LMUL= 2, SEW = 32, VL = 2 */
+FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul3)
+{
+	.vstart = 0x0,
+	.vl = 0x2,
+	.vtype = 0x11,
+	.vcsr = 0x0,
+	.vlenb_mul = 0x1,
+	.vlenb_min = 0x4,
+	.vlenb_max = 0x0,
+	.spec = VECTOR_1_0,
+};
+
+TEST_F(v_csr_valid, ptrace_v_valid_values)
+{
+	unsigned long vlenb;
+	pid_t pid;
+
+	if (!is_vector_supported() && !is_xtheadvector_supported())
+		SKIP(return, "Vectors not supported");
+
+	if (is_vector_supported() && !vector_test(variant->spec))
+		SKIP(return, "Test not supported for Vector");
+
+	if (is_xtheadvector_supported() && !xthead_test(variant->spec))
+		SKIP(return, "Test not supported for XTheadVector");
+
+	vlenb = get_vr_len();
+
+	if (variant->vlenb_min) {
+		if (vlenb < variant->vlenb_min)
+			SKIP(return, "This test does not support VLEN < %lu\n",
+			     variant->vlenb_min * 8);
+	}
+	if (variant->vlenb_max) {
+		if (vlenb > variant->vlenb_max)
+			SKIP(return, "This test does not support VLEN > %lu\n",
+			     variant->vlenb_max * 8);
+	}
+
+	chld_lock = 1;
+	pid = fork();
+	ASSERT_LE(0, pid)
+		TH_LOG("fork: %m");
+
+	if (pid == 0) {
+		unsigned long vl;
+
+		while (chld_lock == 1)
+			asm volatile("" : : "g"(chld_lock) : "memory");
+
+		if (is_xtheadvector_supported()) {
+			asm volatile (
+				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
+				// vsetvli	t4, x0, e16, m2, d1
+				".4byte		0b00000000010100000111111011010111\n"
+				"mv		%[new_vl], t4\n"
+				: [new_vl] "=r" (vl) : : "t4");
+		} else {
+			asm volatile (
+				".option push\n"
+				".option arch, +zve32x\n"
+				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
+				".option pop\n"
+				: [new_vl] "=r"(vl) : : );
+		}
+
+		asm volatile (
+			".option push\n"
+			".option norvc\n"
+			".option arch, +zve32x\n"
+			"ebreak\n" /* breakpoint 1: apply new V state using ptrace */
+			"nop\n"
+			"ebreak\n" /* breakpoint 2: V state clean - context will not be saved */
+			"vmv.v.i v0, -1\n"
+			"ebreak\n" /* breakpoint 3: V state dirty - context will be saved */
+			".option pop\n");
+	} 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 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));
+
+		/* verify initial vsetvli settings */
+
+		if (is_xtheadvector_supported()) {
+			EXPECT_EQ(5UL, regset_data->vtype);
+		} else {
+			EXPECT_EQ(9UL, regset_data->vtype);
+		}
+
+		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
+		EXPECT_EQ(vlenb, regset_data->vlenb);
+		EXPECT_EQ(0UL, regset_data->vstart);
+		EXPECT_EQ(0UL, regset_data->vcsr);
+
+		/* apply valid settings from fixture variants */
+
+		regset_data->vlenb *= variant->vlenb_mul;
+		regset_data->vstart = variant->vstart;
+		regset_data->vtype = variant->vtype;
+		regset_data->vcsr = variant->vcsr;
+		regset_data->vl = variant->vl;
+
+		iov.iov_base = regset_data;
+		iov.iov_len = regset_size;
+
+		ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_RISCV_VECTOR, &iov));
+
+		/* skip 1st ebreak, then resume and wait for the 2nd ebreak */
+
+		iov.iov_base = &regs;
+		iov.iov_len = sizeof(regs);
+
+		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
+		regs.pc += 4;
+		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 vector csr regs using ptrace GETREGSET */
+
+		iov.iov_base = regset_data;
+		iov.iov_len = regset_size;
+
+		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
+
+		/* verify vector csr regs from tracee context */
+
+		EXPECT_EQ(regset_data->vstart, variant->vstart);
+		EXPECT_EQ(regset_data->vtype, variant->vtype);
+		EXPECT_EQ(regset_data->vcsr, variant->vcsr);
+		EXPECT_EQ(regset_data->vl, variant->vl);
+		EXPECT_EQ(regset_data->vlenb, vlenb);
+
+		/* skip 2nd ebreak, then resume and wait for the 3rd ebreak */
+
+		iov.iov_base = &regs;
+		iov.iov_len = sizeof(regs);
+
+		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
+		regs.pc += 4;
+		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 vector csr regs using ptrace GETREGSET */
+
+		iov.iov_base = regset_data;
+		iov.iov_len = regset_size;
+
+		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
+
+		/* verify vector csr regs from tracee context */
+
+		EXPECT_EQ(regset_data->vstart, variant->vstart);
+		EXPECT_EQ(regset_data->vtype, variant->vtype);
+		EXPECT_EQ(regset_data->vcsr, variant->vcsr);
+		EXPECT_EQ(regset_data->vl, variant->vl);
+		EXPECT_EQ(regset_data->vlenb, vlenb);
+
+		/* cleanup */
+
+		ASSERT_EQ(0, kill(pid, SIGKILL));
+	}
+}
+
 TEST_HARNESS_MAIN
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension
  2025-12-14 16:35 ` [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension Sergey Matyukevich
@ 2026-01-07  6:48   ` Andy Chiu
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-07  6:48 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren, Ilya Mamay

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> From: Ilya Mamay <mmamayka01@gmail.com>
>
> Currently, ptrace returns EINVAL when the vector extension is supported
> but not yet activated for the traced process. This error code is not
> always appropriate since the ptrace arguments may be valid.
>
> Debug tools like gdbserver expect ENODATA when the requested register
> set is not active, e.g. see [1]. This expectation seems to be more
> appropriate, so modify the vector ptrace implementation to return:
> - EINVAL when V extension is not supported
> - ENODATA when V extension is supported but not active
>
> [1] https://github.com/bminor/binutils-gdb/blob/637f25e88675fa47e47f9cc5e2cf37384836b8a2/gdbserver/linux-low.cc#L5020
>
> Signed-off-by: Ilya Mamay <mmamayka01@gmail.com>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

> ---
>  arch/riscv/kernel/ptrace.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
> index e6272d74572f..9d203fb84f5e 100644
> --- a/arch/riscv/kernel/ptrace.c
> +++ b/arch/riscv/kernel/ptrace.c
> @@ -95,9 +95,12 @@ static int riscv_vr_get(struct task_struct *target,
>         struct __riscv_v_ext_state *vstate = &target->thread.vstate;
>         struct __riscv_v_regset_state ptrace_vstate;
>
> -       if (!riscv_v_vstate_query(task_pt_regs(target)))
> +       if (!(has_vector() || has_xtheadvector()))
>                 return -EINVAL;
>
> +       if (!riscv_v_vstate_query(task_pt_regs(target)))
> +               return -ENODATA;
> +
>         /*
>          * Ensure the vector registers have been saved to the memory before
>          * copying them to membuf.
> @@ -130,9 +133,12 @@ static int riscv_vr_set(struct task_struct *target,
>         struct __riscv_v_ext_state *vstate = &target->thread.vstate;
>         struct __riscv_v_regset_state ptrace_vstate;
>
> -       if (!riscv_v_vstate_query(task_pt_regs(target)))
> +       if (!(has_vector() || has_xtheadvector()))
>                 return -EINVAL;
>
> +       if (!riscv_v_vstate_query(task_pt_regs(target)))
> +               return -ENODATA;
> +
>         /* Copy rest of the vstate except datap */
>         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
>                                  sizeof(struct __riscv_v_regset_state));
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb
  2025-12-14 16:35 ` [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb Sergey Matyukevich
@ 2026-01-07  6:49   ` Andy Chiu
  2026-01-19 20:48     ` Sergey Matyukevich
  0 siblings, 1 reply; 19+ messages in thread
From: Andy Chiu @ 2026-01-07  6:49 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> The vstate in thread_struct is zeroed when the vector context is
> initialized. That includes read-only register vlenb, which holds
> the vector register length in bytes. Zeroed state persists until
> mstatus.VS becomes 'dirty' and a context switch saves the actual
> hardware values.
>
> This can expose the zero vlenb value to the user-space in early
> debug scenarios, e.g. when ptrace attaches to a traced process
> early, before any vector instruction except the first one was
> executed.
>
> Fix this by specifying proper vlenb on vector context init.
>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

> ---
>  arch/riscv/kernel/vector.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
> index 3ed071dab9d8..b112166d51e9 100644
> --- a/arch/riscv/kernel/vector.c
> +++ b/arch/riscv/kernel/vector.c
> @@ -111,8 +111,8 @@ bool insn_is_vector(u32 insn_buf)
>         return false;
>  }
>
> -static int riscv_v_thread_zalloc(struct kmem_cache *cache,
> -                                struct __riscv_v_ext_state *ctx)
> +static int riscv_v_thread_ctx_alloc(struct kmem_cache *cache,
> +                                   struct __riscv_v_ext_state *ctx)
>  {
>         void *datap;
>
> @@ -122,13 +122,15 @@ static int riscv_v_thread_zalloc(struct kmem_cache *cache,
>
>         ctx->datap = datap;
>         memset(ctx, 0, offsetof(struct __riscv_v_ext_state, datap));
> +       ctx->vlenb = riscv_v_vsize / 32;
> +
>         return 0;
>  }
>
>  void riscv_v_thread_alloc(struct task_struct *tsk)
>  {
>  #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
> -       riscv_v_thread_zalloc(riscv_v_kernel_cachep, &tsk->thread.kernel_vstate);
> +       riscv_v_thread_ctx_alloc(riscv_v_kernel_cachep, &tsk->thread.kernel_vstate);
>  #endif
>  }
>
> @@ -214,12 +216,14 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
>          * context where VS has been off. So, try to allocate the user's V
>          * context and resume execution.
>          */
> -       if (riscv_v_thread_zalloc(riscv_v_user_cachep, &current->thread.vstate)) {
> +       if (riscv_v_thread_ctx_alloc(riscv_v_user_cachep, &current->thread.vstate)) {
>                 force_sig(SIGBUS);
>                 return true;
>         }
> +
>         riscv_v_vstate_on(regs);
>         riscv_v_vstate_set_restore(current, regs);
> +
>         return true;
>  }
>
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb
  2026-01-07  6:49   ` Andy Chiu
@ 2026-01-19 20:48     ` Sergey Matyukevich
  0 siblings, 0 replies; 19+ messages in thread
From: Sergey Matyukevich @ 2026-01-19 20:48 UTC (permalink / raw)
  To: Andy Chiu, Paul Walmsley
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

Hi,

On Wed, Jan 07, 2026 at 12:49:31AM -0600, Andy Chiu wrote:
> On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
> >
> > The vstate in thread_struct is zeroed when the vector context is
> > initialized. That includes read-only register vlenb, which holds
> > the vector register length in bytes. Zeroed state persists until
> > mstatus.VS becomes 'dirty' and a context switch saves the actual
> > hardware values.
> >
> > This can expose the zero vlenb value to the user-space in early
> > debug scenarios, e.g. when ptrace attaches to a traced process
> > early, before any vector instruction except the first one was
> > executed.
> >
> > Fix this by specifying proper vlenb on vector context init.
> >
> > Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
> 
> Reviewed-by: Andy Chiu <andybnac@gmail.com>
> 

Thanks for reviews !

What would be the recommended way to proceed with these patches ?
I have reviews from Andy for the patches 1,2 and 5 (selftest for 2).
They can be used independently of the remainig ptrace v-state
validation changes and their tests.

Would it make sense to split the series into two parts, so that
the v-state validation can continue evolve independently ?

Regards,
Sergey

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 3/9] riscv: csr: define vtype register elements
  2025-12-14 16:35 ` [PATCH v5 3/9] riscv: csr: define vtype register elements Sergey Matyukevich
@ 2026-01-21 21:04   ` Andy Chiu
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-21 21:04 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

Hi Sergey,

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> Define masks and shifts for vtype CSR according to the vector specs:
> - v0.7.1 used in early T-Head cores, known as xtheadvector in the kernel
> - v1.0
>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

Thanks for putting v0.7 together,
Andy

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers
  2025-12-14 16:35 ` [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers Sergey Matyukevich
@ 2026-01-21 21:07   ` Andy Chiu
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-21 21:07 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

Hi Sergey,

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> Add strict validation for vector csr registers when setting them via
> ptrace:
> - reject attempts to set reserved bits or invalid field combinations
> - enforce strict VL checks against calculated VLMAX values
>
> Vector specs 0.7.1 and 1.0 allow normal applications to set candidate
> VL values and read back the hardware-adjusted results, see section 6
> for details. Disallow such flexibility in vector ptrace operations
> and strictly enforce valid VL input.
>
> The traced process may not update its saved vector context if no vector
> instructions execute between breakpoints. So the purpose of the strict
> ptrace approach is to make sure that debuggers maintain an accurate view
> of the tracee's vector context across multiple halt/resume debug cycles.
>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

Thanks,
Andy

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace
  2025-12-14 16:35 ` [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace Sergey Matyukevich
@ 2026-01-21 21:33   ` Andy Chiu
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-21 21:33 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

Hi Sergey,

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> Add a test case that attaches to a traced process immediately after its
> first executed vector instructions to verify the initial vector context.
>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

> ---
>  .../riscv/vector/validate_v_ptrace.c          | 135 ++++++++++++++++++
>  1 file changed, 135 insertions(+)
>
> diff --git a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
> index b64986b42270..a8d64d351edd 100644
> --- a/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
> +++ b/tools/testing/selftests/riscv/vector/validate_v_ptrace.c
> @@ -13,6 +13,9 @@
>  #include "kselftest_harness.h"
>  #include "v_helpers.h"
>
> +#define SR_FS_DIRTY    0x00006000UL
> +#define CSR_VXRM_SHIFT 1
> +
>  volatile unsigned long chld_lock;
>
>  TEST(ptrace_v_not_enabled)
> @@ -77,4 +80,136 @@ TEST(ptrace_v_not_enabled)
>         }
>  }
>
> +TEST(ptrace_v_early_debug)
> +{
> +       static volatile unsigned long vstart;
> +       static volatile unsigned long vtype;
> +       static volatile unsigned long vlenb;
> +       static volatile unsigned long vcsr;
> +       static volatile unsigned long vl;
> +       bool xtheadvector;
> +       pid_t pid;
> +
> +       if (!(is_vector_supported() || is_xtheadvector_supported()))
> +               SKIP(return, "Vector not supported");
> +
> +       xtheadvector = is_xtheadvector_supported();
> +
> +       chld_lock = 1;
> +       pid = fork();
> +       ASSERT_LE(0, pid)
> +               TH_LOG("fork: %m");
> +
> +       if (pid == 0) {
> +               unsigned long vxsat, vxrm;
> +
> +               vlenb = get_vr_len();
> +
> +               while (chld_lock == 1)
> +                       asm volatile ("" : : "g"(chld_lock) : "memory");
> +
> +               asm volatile (
> +                       "csrr %[vstart], vstart\n"
> +                       "csrr %[vtype], vtype\n"
> +                       "csrr %[vl], vl\n"
> +                       : [vtype] "=r"(vtype), [vstart] "=r"(vstart), [vl] "=r"(vl)
> +                       :
> +                       : "memory");
> +
> +               /* no 'is_xtheadvector_supported()' here to avoid clobbering v-state by syscall */
> +               if (xtheadvector) {
> +                       asm volatile (
> +                               "csrs sstatus, %[bit]\n"
> +                               "csrr %[vxsat], vxsat\n"
> +                               "csrr %[vxrm], vxrm\n"
> +                               : [vxsat] "=r"(vxsat), [vxrm] "=r"(vxrm)
> +                               : [bit] "r" (SR_FS_DIRTY)
> +                               : "memory");
> +                       vcsr = vxsat | vxrm << CSR_VXRM_SHIFT;
> +               } else {
> +                       asm volatile (
> +                               "csrr %[vcsr], vcsr\n"
> +                               : [vcsr] "=r"(vcsr)
> +                               :
> +                               : "memory");
> +               }
> +
> +               asm volatile (
> +                       ".option push\n"
> +                       ".option norvc\n"
> +                       "ebreak\n"
> +                       ".option pop\n");
> +       } else {
> +               struct __riscv_v_regset_state *regset_data;
> +               unsigned long vstart_csr;
> +               unsigned long vlenb_csr;
> +               unsigned long vtype_csr;
> +               unsigned long vcsr_csr;
> +               unsigned long vl_csr;
> +               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 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 PEEKDATA */
> +
> +               errno = 0;
> +               vstart_csr = ptrace(PTRACE_PEEKDATA, pid, &vstart, NULL);
> +               ASSERT_FALSE((errno != 0) && (vstart_csr == -1));
> +
> +               errno = 0;
> +               vl_csr = ptrace(PTRACE_PEEKDATA, pid, &vl, NULL);
> +               ASSERT_FALSE((errno != 0) && (vl_csr == -1));
> +
> +               errno = 0;
> +               vtype_csr = ptrace(PTRACE_PEEKDATA, pid, &vtype, NULL);
> +               ASSERT_FALSE((errno != 0) && (vtype_csr == -1));
> +
> +               errno = 0;
> +               vcsr_csr = ptrace(PTRACE_PEEKDATA, pid, &vcsr, NULL);
> +               ASSERT_FALSE((errno != 0) && (vcsr_csr == -1));
> +
> +               errno = 0;
> +               vlenb_csr = ptrace(PTRACE_PEEKDATA, pid, &vlenb, NULL);
> +               ASSERT_FALSE((errno != 0) && (vlenb_csr == -1));
> +
> +               /* read tracee csr regs using ptrace GETREGSET */
> +
> +               regset_size = sizeof(*regset_data) + vlenb_csr * 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));
> +
> +               /* compare */
> +
> +               EXPECT_EQ(vstart_csr, regset_data->vstart);
> +               EXPECT_EQ(vtype_csr, regset_data->vtype);
> +               EXPECT_EQ(vlenb_csr, regset_data->vlenb);
> +               EXPECT_EQ(vcsr_csr, regset_data->vcsr);
> +               EXPECT_EQ(vl_csr, regset_data->vl);
> +
> +               /* cleanup */
> +
> +               ASSERT_EQ(0, kill(pid, SIGKILL));
> +       }
> +}
> +
>  TEST_HARNESS_MAIN
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context
  2025-12-14 16:35 ` [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context Sergey Matyukevich
@ 2026-01-21 21:37   ` Andy Chiu
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-21 21:37 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> Add a test to v_ptrace test suite to verify that vector csr registers
> are clobbered on syscalls.
>
> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>

Reviewed-by: Andy Chiu <andybnac@gmail.com>

Thanks,
Andy

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (8 preceding siblings ...)
  2025-12-14 16:35 ` [PATCH v5 9/9] selftests: riscv: verify ptrace accepts valid vector csr values Sergey Matyukevich
@ 2026-01-21 21:47 ` Andy Chiu
  2026-01-24  8:30 ` patchwork-bot+linux-riscv
  10 siblings, 0 replies; 19+ messages in thread
From: Andy Chiu @ 2026-01-21 21:47 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, Paul Walmsley,
	Palmer Dabbelt, Alexandre Ghiti, Oleg Nesterov, Shuah Khan,
	Thomas Huth, Charlie Jenkins, Samuel Holland, Joel Granados,
	Conor Dooley, Yong-Xuan Wang, Heiko Stuebner, Guo Ren

Hi Sergey,

On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi@gmail.com> wrote:
>
> This patch series suggests fixes for several corner cases in the RISC-V
> vector ptrace implementation:
>
> - init vector context with proper vlenb, to avoid reading zero vlenb
>   by an early attached debugger
>
> - follow gdbserver expectations and return ENODATA instead of EINVAL
>   if vector extension is supported but not yet activated for the
>   traced process
>
> - validate input vector csr registers in ptrace, to maintain an accurate
>   view of the tracee's vector context across multiple halt/resume
>   debug cycles
>
> For detailed description see the appropriate commit messages. A new test
> suite validate_v_ptrace is added to the tools/testing/selftests/riscv/vector
> to verify some of the vector ptrace functionality and corner cases.
>
> So far tested on the following platforms:
> - test in QEMU rv32/rv64
> - test on c908 (BananaPi CanMV K230D Zero)
> - test on c906 (MangoPi MQ Pro)
>
> Previous versions:
> - v4: https://lore.kernel.org/linux-riscv/20251108194207.1257866-1-geomatsi@gmail.com/T/#u
> - v3: https://lore.kernel.org/linux-riscv/20251025210655.43099-1-geomatsi@gmail.com/T/#u
> - v2: https://lore.kernel.org/linux-riscv/20250821173957.563472-1-geomatsi@gmail.com/T/#u
> - v1: https://lore.kernel.org/linux-riscv/20251007115840.2320557-1-geomatsi@gmail.com/T/#u
>
> Changes in v5:
> - add support and minimal set of tests for XTheadVector
>
> Changes in v4:
> The form 'vsetvli x0, x0, ...' can only be used if VLMAX remains
> unchanged, see spec 6.2. This condition was not met by the initial
> values in the selftests w.r.t. the initial zeroed context. QEMU accepted
> such values, but actual hardware (c908, BananaPi CanMV Zero board) did
> not, setting vill. So fix the selftests after testing on hardware:
> - replace 'vsetvli x0, x0, ...' by 'vsetvli rd, x0, ...'
> - fixed instruction returns VLMAX, so use it in checks as well
> - replace fixed vlenb == 16 in the syscall test
>
> Changes in v3:
> Address the review comments by Andy Chiu and rework the approach:
> - drop forced vector context save entirely
> - perform strict validation of vector csr regs in ptrace
>
> Changes in v2:
> - add thread_info flag to allow to force vector context save
> - force vector context save after vector ptrace to ensure valid vector
>   context in the next ptrace operations
> - force vector context save on the first context switch after vector
>   context init to get proper vlenb
>
> ---
>
> Ilya Mamay (1):
>   riscv: ptrace: return ENODATA for inactive vector extension
>
> Sergey Matyukevich (8):
>   riscv: vector: init vector context with proper vlenb
>   riscv: csr: define vtype register elements
>   riscv: ptrace: validate input vector csr registers
>   selftests: riscv: test ptrace vector interface
>   selftests: riscv: verify initial vector state with ptrace
>   selftests: riscv: verify syscalls discard vector context
>   selftests: riscv: verify ptrace rejects invalid vector csr inputs
>   selftests: riscv: verify ptrace accepts valid vector csr values
>
>  arch/riscv/include/asm/csr.h                  |  17 +
>  arch/riscv/kernel/ptrace.c                    |  98 +-
>  arch/riscv/kernel/vector.c                    |  12 +-
>  .../testing/selftests/riscv/vector/.gitignore |   2 +
>  tools/testing/selftests/riscv/vector/Makefile |  10 +-
>  .../selftests/riscv/vector/v_helpers.c        |  23 +
>  .../selftests/riscv/vector/v_helpers.h        |   2 +
>  .../riscv/vector/validate_v_ptrace.c          | 919 ++++++++++++++++++
>  8 files changed, 1075 insertions(+), 8 deletions(-)
>  create mode 100644 tools/testing/selftests/riscv/vector/validate_v_ptrace.c
>
>
> base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> --
> 2.52.0
>

For the series:

Tested-by: Andy Chiu <andybnac@gmail.com>
(on qemu rv64gcv)

Thanks,
Andy

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases
  2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
                   ` (9 preceding siblings ...)
  2026-01-21 21:47 ` [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Andy Chiu
@ 2026-01-24  8:30 ` patchwork-bot+linux-riscv
  10 siblings, 0 replies; 19+ messages in thread
From: patchwork-bot+linux-riscv @ 2026-01-24  8:30 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-riscv, linux-kernel, linux-kselftest, pjw, palmer, alex,
	oleg, shuah, thuth, charlie, andybnac, samuel.holland,
	joel.granados, conor.dooley, yongxuan.wang, heiko, guoren

Hello:

This series was applied to riscv/linux.git (for-next)
by Paul Walmsley <pjw@kernel.org>:

On Sun, 14 Dec 2025 19:35:04 +0300 you wrote:
> This patch series suggests fixes for several corner cases in the RISC-V
> vector ptrace implementation:
> 
> - init vector context with proper vlenb, to avoid reading zero vlenb
>   by an early attached debugger
> 
> - follow gdbserver expectations and return ENODATA instead of EINVAL
>   if vector extension is supported but not yet activated for the
>   traced process
> 
> [...]

Here is the summary with links:
  - [v5,1/9] riscv: ptrace: return ENODATA for inactive vector extension
    https://git.kernel.org/riscv/c/35328975fa84
  - [v5,2/9] riscv: vector: init vector context with proper vlenb
    https://git.kernel.org/riscv/c/66d52c54e59f
  - [v5,3/9] riscv: csr: define vtype register elements
    https://git.kernel.org/riscv/c/0d9acbd7836a
  - [v5,4/9] riscv: ptrace: validate input vector csr registers
    https://git.kernel.org/riscv/c/995e66a25b26
  - [v5,5/9] selftests: riscv: test ptrace vector interface
    https://git.kernel.org/riscv/c/dca68b94a8b1
  - [v5,6/9] selftests: riscv: verify initial vector state with ptrace
    https://git.kernel.org/riscv/c/1a353e49a0dc
  - [v5,7/9] selftests: riscv: verify syscalls discard vector context
    https://git.kernel.org/riscv/c/4b7e068fe676
  - [v5,8/9] selftests: riscv: verify ptrace rejects invalid vector csr inputs
    https://git.kernel.org/riscv/c/bfdd22c430ca
  - [v5,9/9] selftests: riscv: verify ptrace accepts valid vector csr values
    https://git.kernel.org/riscv/c/ccb3038e946c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2026-01-24  8:30 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-14 16:35 [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Sergey Matyukevich
2025-12-14 16:35 ` [PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension Sergey Matyukevich
2026-01-07  6:48   ` Andy Chiu
2025-12-14 16:35 ` [PATCH v5 2/9] riscv: vector: init vector context with proper vlenb Sergey Matyukevich
2026-01-07  6:49   ` Andy Chiu
2026-01-19 20:48     ` Sergey Matyukevich
2025-12-14 16:35 ` [PATCH v5 3/9] riscv: csr: define vtype register elements Sergey Matyukevich
2026-01-21 21:04   ` Andy Chiu
2025-12-14 16:35 ` [PATCH v5 4/9] riscv: ptrace: validate input vector csr registers Sergey Matyukevich
2026-01-21 21:07   ` Andy Chiu
2025-12-14 16:35 ` [PATCH v5 5/9] selftests: riscv: test ptrace vector interface Sergey Matyukevich
2025-12-14 16:35 ` [PATCH v5 6/9] selftests: riscv: verify initial vector state with ptrace Sergey Matyukevich
2026-01-21 21:33   ` Andy Chiu
2025-12-14 16:35 ` [PATCH v5 7/9] selftests: riscv: verify syscalls discard vector context Sergey Matyukevich
2026-01-21 21:37   ` Andy Chiu
2025-12-14 16:35 ` [PATCH v5 8/9] selftests: riscv: verify ptrace rejects invalid vector csr inputs Sergey Matyukevich
2025-12-14 16:35 ` [PATCH v5 9/9] selftests: riscv: verify ptrace accepts valid vector csr values Sergey Matyukevich
2026-01-21 21:47 ` [PATCH v5 0/9] riscv: vector: misc ptrace fixes for debug use-cases Andy Chiu
2026-01-24  8:30 ` patchwork-bot+linux-riscv

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox