[PATCH] um: always use the internal copy of the FP registers

Tiwei Bie tiwei.btw at antgroup.com
Fri Sep 13 06:09:24 PDT 2024


On 2024/9/13 16:22, Benjamin Berg wrote:
> From: Benjamin Berg <benjamin.berg at intel.com>
> 
> When switching from userspace to the kernel, all registers including the
> FP registers are copied into the kernel and restored later on. As such,
> the true source for the FP register state is actually already in the
> kernel and they should never be grabbed from the userspace process.
> 
> Change the various places to simply copy the data from the internal FP
> register storage area.

Cool! I had similar thoughts, but I haven't tried to make it happen.

> Note that on i386 the format of PTRACE_GETFPREGS
> and PTRACE_GETFPXREGS is different enough that conversion would be
> needed. With this patch, -EINVAL is returned if the non-native format is
> requested.
> 
> The upside is, that this patchset fixes setting registers via ptrace
> (which simply did not work before) as well as fixing setting floating
> point registers using the mcontext on signal return on i386.
> 
> Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
> 
> ---
> 
> I think that ideally more changs should be done in this space. For a
> start, one can remove support for hosts without PTRACE_GETFPXREGS. But,
> more importantly, UML should probably implement the regset API, which
> would considerably improve both ptrace and coredump generation and
> should also make it easy to fix the cases where this patch returns an
> error.
> ---
>  arch/um/include/shared/registers.h |  6 ---
>  arch/um/kernel/process.c           | 11 ++++-
>  arch/x86/um/os-Linux/registers.c   | 12 +++---
>  arch/x86/um/ptrace_32.c            | 50 ++++++++++++-----------
>  arch/x86/um/ptrace_64.c            | 20 ++++-----
>  arch/x86/um/signal.c               | 65 ++++++++++++++----------------
>  6 files changed, 80 insertions(+), 84 deletions(-)
> 
> diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h
> index a0450326521c..7d81b2339a48 100644
> --- a/arch/um/include/shared/registers.h
> +++ b/arch/um/include/shared/registers.h
> @@ -8,12 +8,6 @@
>  
>  #include <sysdep/ptrace.h>
>  
> -extern int save_i387_registers(int pid, unsigned long *fp_regs);
> -extern int restore_i387_registers(int pid, unsigned long *fp_regs);
> -extern int save_fp_registers(int pid, unsigned long *fp_regs);
> -extern int restore_fp_registers(int pid, unsigned long *fp_regs);
> -extern int save_fpx_registers(int pid, unsigned long *fp_regs);
> -extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
>  extern int init_pid_registers(int pid);
>  extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs);
>  extern int get_fp_registers(int pid, unsigned long *regs);
> diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
> index be2856af6d4c..ad798d40f8a4 100644
> --- a/arch/um/kernel/process.c
> +++ b/arch/um/kernel/process.c
> @@ -290,8 +290,15 @@ unsigned long __get_wchan(struct task_struct *p)
>  
>  int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
>  {
> -	int cpu = current_thread_info()->cpu;
> +#ifdef CONFIG_X86_32
> +	extern int have_fpx_regs;
>  
> -	return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
> +	/* FIXME: A plain copy does not work on i386 with have_fpx_regs */
> +	if (have_fpx_regs)
> +		return -1;
> +#endif
> +	memcpy(fpu, &t->thread.regs.regs.fp, sizeof(*fpu));
> +
> +	return 0;
>  }

This function is expected to return a boolean value which should be
true on success.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_elf.c?h=v6.11-rc7#n1816

Regards,
Tiwei



More information about the linux-um mailing list