[PATCH v5 1/9] riscv: ptrace: return ENODATA for inactive vector extension

Andy Chiu andybnac at gmail.com
Tue Jan 6 22:48:45 PST 2026


On Sun, Dec 14, 2025 at 10:35 AM Sergey Matyukevich <geomatsi at gmail.com> wrote:
>
> From: Ilya Mamay <mmamayka01 at 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 at gmail.com>
> Signed-off-by: Sergey Matyukevich <geomatsi at gmail.com>

Reviewed-by: Andy Chiu <andybnac at 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
>



More information about the linux-riscv mailing list