]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
riscv: ptrace: return ENODATA for inactive vector extension
authorIlya Mamay <mmamayka01@gmail.com>
Mon, 26 Jan 2026 04:09:56 +0000 (21:09 -0700)
committerPaul Walmsley <pjw@kernel.org>
Thu, 29 Jan 2026 09:38:40 +0000 (02:38 -0700)
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>
Tested-by: Andy Chiu <andybnac@gmail.com>
Link: https://patch.msgid.link/20251214163537.1054292-2-geomatsi@gmail.com
Signed-off-by: Paul Walmsley <pjw@kernel.org>
arch/riscv/kernel/ptrace.c

index 57e257d459e80d753be0b519423cff4d3cc9cabf..97636fdfeb77dad46150df05c9400d6de791c6a7 100644 (file)
@@ -99,9 +99,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.
@@ -134,9 +137,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));