Skip to content

Commit

Permalink
x86/fpu/xstate: Use fpstate for copy_uabi_to_xstate()
Browse files Browse the repository at this point in the history
Prepare for dynamically enabled states per task. The function needs to
retrieve the features and sizes which are valid in a fpstate
context. Retrieve them from fpstate.

Move the function declarations to the core header as they are not
required anywhere else.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211013145323.233529986@linutronix.de
  • Loading branch information
Thomas Gleixner authored and Borislav Petkov committed Oct 21, 2021
1 parent 3ac8d75 commit 49e4eb4
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 25 deletions.
12 changes: 0 additions & 12 deletions arch/x86/include/asm/fpu/xstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,8 @@ extern void __init update_regset_xstate_info(unsigned int size,
u64 xstate_mask);

int xfeature_size(int xfeature_nr);
int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf);
int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);

void xsaves(struct xregs_state *xsave, u64 mask);
void xrstors(struct xregs_state *xsave, u64 mask);

enum xstate_copy_mode {
XSTATE_COPY_FP,
XSTATE_COPY_FX,
XSTATE_COPY_XSAVE,
};

struct membuf;
void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode mode);

#endif
2 changes: 1 addition & 1 deletion arch/x86/kernel/fpu/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ int fpu_copy_kvm_uabi_to_fpstate(struct fpu *fpu, const void *buf, u64 xcr0,
if (ustate->xsave.header.xfeatures & ~xcr0)
return -EINVAL;

ret = copy_uabi_from_kernel_to_xstate(&kstate->regs.xsave, ustate);
ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
if (ret)
return ret;

Expand Down
5 changes: 2 additions & 3 deletions arch/x86/kernel/fpu/regset.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
#include <asm/fpu/api.h>
#include <asm/fpu/signal.h>
#include <asm/fpu/regset.h>
#include <asm/fpu/xstate.h>

#include "context.h"
#include "internal.h"
#include "legacy.h"
#include "xstate.h"

/*
* The xstateregs_active() routine is the same as the regset_fpregs_active() routine,
Expand Down Expand Up @@ -168,8 +168,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
}

fpu_force_restore(fpu);
ret = copy_uabi_from_kernel_to_xstate(&fpu->fpstate->regs.xsave,
kbuf ?: tmpbuf);
ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf);

out:
vfree(tmpbuf);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/fpu/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,

fpregs = &fpu->fpstate->regs;
if (use_xsave() && !fx_only) {
if (copy_sigframe_from_user_to_xstate(&fpregs->xsave, buf_fx))
if (copy_sigframe_from_user_to_xstate(fpu->fpstate, buf_fx))
return false;
} else {
if (__copy_from_user(&fpregs->fxsave, buf_fx,
Expand Down
18 changes: 10 additions & 8 deletions arch/x86/kernel/fpu/xstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,10 +463,11 @@ int xfeature_size(int xfeature_nr)
}

/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */
static int validate_user_xstate_header(const struct xstate_header *hdr)
static int validate_user_xstate_header(const struct xstate_header *hdr,
struct fpstate *fpstate)
{
/* No unknown or supervisor features may be set */
if (hdr->xfeatures & ~xfeatures_mask_uabi())
if (hdr->xfeatures & ~fpstate->user_xfeatures)
return -EINVAL;

/* Userspace must use the uncompacted format */
Expand Down Expand Up @@ -1115,9 +1116,10 @@ static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
}


static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
const void __user *ubuf)
{
struct xregs_state *xsave = &fpstate->regs.xsave;
unsigned int offset, size;
struct xstate_header hdr;
u64 mask;
Expand All @@ -1127,7 +1129,7 @@ static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
if (copy_from_buffer(&hdr, offset, sizeof(hdr), kbuf, ubuf))
return -EFAULT;

if (validate_user_xstate_header(&hdr))
if (validate_user_xstate_header(&hdr, fpstate))
return -EINVAL;

/* Validate MXCSR when any of the related features is in use */
Expand Down Expand Up @@ -1182,20 +1184,20 @@ static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
* Convert from a ptrace standard-format kernel buffer to kernel XSAVE[S]
* format and copy to the target thread. Used by ptrace and KVM.
*/
int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
{
return copy_uabi_to_xstate(xsave, kbuf, NULL);
return copy_uabi_to_xstate(fpstate, kbuf, NULL);
}

/*
* Convert from a sigreturn standard-format user-space buffer to kernel
* XSAVE[S] format and copy to the target thread. This is called from the
* sigreturn() and rt_sigreturn() system calls.
*/
int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave,
int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate,
const void __user *ubuf)
{
return copy_uabi_to_xstate(xsave, NULL, ubuf);
return copy_uabi_to_xstate(fpstate, NULL, ubuf);
}

static bool validate_independent_components(u64 mask)
Expand Down
12 changes: 12 additions & 0 deletions arch/x86/kernel/fpu/xstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ static inline void xstate_init_xcomp_bv(struct xregs_state *xsave, u64 mask)
xsave->header.xcomp_bv = mask | XCOMP_BV_COMPACTED_FORMAT;
}

enum xstate_copy_mode {
XSTATE_COPY_FP,
XSTATE_COPY_FX,
XSTATE_COPY_XSAVE,
};

struct membuf;
extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
u32 pkru_val, enum xstate_copy_mode copy_mode);
extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode mode);
extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf);
extern int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate, const void __user *ubuf);


extern void fpu__init_cpu_xstate(void);
extern void fpu__init_system_xstate(void);
Expand Down

0 comments on commit 49e4eb4

Please sign in to comment.