Commit ca834def authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Borislav Petkov

x86/fpu: Rework copy_xstate_to_uabi_buf()

Prepare for replacing the KVM copy xstate to user function by extending
copy_xstate_to_uabi_buf() with a pkru argument which allows the caller to
hand in the pkru value, which is required for KVM because the guest PKRU is
not accessible via current. Fixup all callsites accordingly.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211015011539.191902137@linutronix.de
parent ea4d6938
...@@ -940,9 +940,10 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, ...@@ -940,9 +940,10 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
} }
/** /**
* copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer * __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer
* @to: membuf descriptor * @to: membuf descriptor
* @tsk: The task from which to copy the saved xstate * @xsave: The xsave from which to copy
* @pkru_val: The PKRU value to store in the PKRU component
* @copy_mode: The requested copy mode * @copy_mode: The requested copy mode
* *
* Converts from kernel XSAVE or XSAVES compacted format to UABI conforming * Converts from kernel XSAVE or XSAVES compacted format to UABI conforming
...@@ -951,11 +952,10 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, ...@@ -951,11 +952,10 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
* *
* It supports partial copy but @to.pos always starts from zero. * It supports partial copy but @to.pos always starts from zero.
*/ */
void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk, void __copy_xstate_to_uabi_buf(struct membuf to, struct xregs_state *xsave,
enum xstate_copy_mode copy_mode) u32 pkru_val, enum xstate_copy_mode copy_mode)
{ {
const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr); const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr);
struct xregs_state *xsave = &tsk->thread.fpu.state.xsave;
struct xregs_state *xinit = &init_fpstate.xsave; struct xregs_state *xinit = &init_fpstate.xsave;
struct xstate_header header; struct xstate_header header;
unsigned int zerofrom; unsigned int zerofrom;
...@@ -1033,10 +1033,9 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk, ...@@ -1033,10 +1033,9 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
struct pkru_state pkru = {0}; struct pkru_state pkru = {0};
/* /*
* PKRU is not necessarily up to date in the * PKRU is not necessarily up to date in the
* thread's XSAVE buffer. Fill this part from the * XSAVE buffer. Use the provided value.
* per-thread storage.
*/ */
pkru.pkru = tsk->thread.pkru; pkru.pkru = pkru_val;
membuf_write(&to, &pkru, sizeof(pkru)); membuf_write(&to, &pkru, sizeof(pkru));
} else { } else {
copy_feature(header.xfeatures & BIT_ULL(i), &to, copy_feature(header.xfeatures & BIT_ULL(i), &to,
...@@ -1056,6 +1055,25 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk, ...@@ -1056,6 +1055,25 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
membuf_zero(&to, to.left); membuf_zero(&to, to.left);
} }
/**
* copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer
* @to: membuf descriptor
* @tsk: The task from which to copy the saved xstate
* @copy_mode: The requested copy mode
*
* Converts from kernel XSAVE or XSAVES compacted format to UABI conforming
* format, i.e. from the kernel internal hardware dependent storage format
* to the requested @mode. UABI XSTATE is always uncompacted!
*
* It supports partial copy but @to.pos always starts from zero.
*/
void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode copy_mode)
{
__copy_xstate_to_uabi_buf(to, &tsk->thread.fpu.state.xsave,
tsk->thread.pkru, copy_mode);
}
static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size, static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
const void *kbuf, const void __user *ubuf) const void *kbuf, const void __user *ubuf)
{ {
......
...@@ -15,4 +15,7 @@ static inline void xstate_init_xcomp_bv(struct xregs_state *xsave, u64 mask) ...@@ -15,4 +15,7 @@ static inline void xstate_init_xcomp_bv(struct xregs_state *xsave, u64 mask)
xsave->header.xcomp_bv = mask | XCOMP_BV_COMPACTED_FORMAT; xsave->header.xcomp_bv = mask | XCOMP_BV_COMPACTED_FORMAT;
} }
extern void __copy_xstate_to_uabi_buf(struct membuf to, struct xregs_state *xsave,
u32 pkru_val, enum xstate_copy_mode copy_mode);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment