mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 05:04:00 +08:00
x86/fpu: Use a feature number instead of mask in two more helpers
After changing the argument of __raw_xsave_addr() from a mask to number Dave suggested to check if it makes sense to do the same for get_xsave_addr(). As it turns out it does. Only get_xsave_addr() needs the mask to check if the requested feature is part of what is supported/saved and then uses the number again. The shift operation is cheaper compared to fls64() (find last bit set). Also, the feature number uses less opcode space compared to the mask. :) Make the get_xsave_addr() argument a xfeature number instead of a mask and fix up its callers. Furthermore, use xfeature_nr and xfeature_mask consistently. This results in the following changes to the kvm code: feature -> xfeature_mask index -> xfeature_nr Suggested-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Dave Hansen <dave.hansen@intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jann Horn <jannh@google.com> Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> Cc: kvm ML <kvm@vger.kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Rik van Riel <riel@surriel.com> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Siarhei Liakh <Siarhei.Liakh@concurrent-rt.com> Cc: x86-ml <x86@kernel.org> Link: https://lkml.kernel.org/r/20190403164156.19645-12-bigeasy@linutronix.de
This commit is contained in:
parent
07baeb04f3
commit
abd16d68d6
@ -46,8 +46,8 @@ extern void __init update_regset_xstate_info(unsigned int size,
|
|||||||
u64 xstate_mask);
|
u64 xstate_mask);
|
||||||
|
|
||||||
void fpu__xstate_clear_all_cpu_caps(void);
|
void fpu__xstate_clear_all_cpu_caps(void);
|
||||||
void *get_xsave_addr(struct xregs_state *xsave, int xstate);
|
void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
|
||||||
const void *get_xsave_field_ptr(int xstate_field);
|
const void *get_xsave_field_ptr(int xfeature_nr);
|
||||||
int using_compacted_format(void);
|
int using_compacted_format(void);
|
||||||
int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
|
int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
|
||||||
int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
|
int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
|
||||||
|
@ -830,15 +830,14 @@ static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
|
|||||||
*
|
*
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* xstate: the thread's storage area for all FPU data
|
* xstate: the thread's storage area for all FPU data
|
||||||
* xstate_feature: state which is defined in xsave.h (e.g.
|
* xfeature_nr: state which is defined in xsave.h (e.g. XFEATURE_FP,
|
||||||
* XFEATURE_MASK_FP, XFEATURE_MASK_SSE, etc...)
|
* XFEATURE_SSE, etc...)
|
||||||
* Output:
|
* Output:
|
||||||
* address of the state in the xsave area, or NULL if the
|
* address of the state in the xsave area, or NULL if the
|
||||||
* field is not present in the xsave buffer.
|
* field is not present in the xsave buffer.
|
||||||
*/
|
*/
|
||||||
void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
|
void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
|
||||||
{
|
{
|
||||||
int xfeature_nr;
|
|
||||||
/*
|
/*
|
||||||
* Do we even *have* xsave state?
|
* Do we even *have* xsave state?
|
||||||
*/
|
*/
|
||||||
@ -850,11 +849,11 @@ void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
|
|||||||
* have not enabled. Remember that pcntxt_mask is
|
* have not enabled. Remember that pcntxt_mask is
|
||||||
* what we write to the XCR0 register.
|
* what we write to the XCR0 register.
|
||||||
*/
|
*/
|
||||||
WARN_ONCE(!(xfeatures_mask & xstate_feature),
|
WARN_ONCE(!(xfeatures_mask & BIT_ULL(xfeature_nr)),
|
||||||
"get of unsupported state");
|
"get of unsupported state");
|
||||||
/*
|
/*
|
||||||
* This assumes the last 'xsave*' instruction to
|
* This assumes the last 'xsave*' instruction to
|
||||||
* have requested that 'xstate_feature' be saved.
|
* have requested that 'xfeature_nr' be saved.
|
||||||
* If it did not, we might be seeing and old value
|
* If it did not, we might be seeing and old value
|
||||||
* of the field in the buffer.
|
* of the field in the buffer.
|
||||||
*
|
*
|
||||||
@ -863,10 +862,9 @@ void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
|
|||||||
* or because the "init optimization" caused it
|
* or because the "init optimization" caused it
|
||||||
* to not be saved.
|
* to not be saved.
|
||||||
*/
|
*/
|
||||||
if (!(xsave->header.xfeatures & xstate_feature))
|
if (!(xsave->header.xfeatures & BIT_ULL(xfeature_nr)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xfeature_nr = fls64(xstate_feature) - 1;
|
|
||||||
return __raw_xsave_addr(xsave, xfeature_nr);
|
return __raw_xsave_addr(xsave, xfeature_nr);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(get_xsave_addr);
|
EXPORT_SYMBOL_GPL(get_xsave_addr);
|
||||||
@ -882,13 +880,13 @@ EXPORT_SYMBOL_GPL(get_xsave_addr);
|
|||||||
* Note that this only works on the current task.
|
* Note that this only works on the current task.
|
||||||
*
|
*
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* @xsave_state: state which is defined in xsave.h (e.g. XFEATURE_MASK_FP,
|
* @xfeature_nr: state which is defined in xsave.h (e.g. XFEATURE_FP,
|
||||||
* XFEATURE_MASK_SSE, etc...)
|
* XFEATURE_SSE, etc...)
|
||||||
* Output:
|
* Output:
|
||||||
* address of the state in the xsave area or NULL if the state
|
* address of the state in the xsave area or NULL if the state
|
||||||
* is not present or is in its 'init state'.
|
* is not present or is in its 'init state'.
|
||||||
*/
|
*/
|
||||||
const void *get_xsave_field_ptr(int xsave_state)
|
const void *get_xsave_field_ptr(int xfeature_nr)
|
||||||
{
|
{
|
||||||
struct fpu *fpu = ¤t->thread.fpu;
|
struct fpu *fpu = ¤t->thread.fpu;
|
||||||
|
|
||||||
@ -898,7 +896,7 @@ const void *get_xsave_field_ptr(int xsave_state)
|
|||||||
*/
|
*/
|
||||||
fpu__save(fpu);
|
fpu__save(fpu);
|
||||||
|
|
||||||
return get_xsave_addr(&fpu->state.xsave, xsave_state);
|
return get_xsave_addr(&fpu->state.xsave, xfeature_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_HAS_PKEYS
|
#ifdef CONFIG_ARCH_HAS_PKEYS
|
||||||
|
@ -456,7 +456,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
|
|||||||
* which is all zeros which indicates MPX was not
|
* which is all zeros which indicates MPX was not
|
||||||
* responsible for the exception.
|
* responsible for the exception.
|
||||||
*/
|
*/
|
||||||
bndcsr = get_xsave_field_ptr(XFEATURE_MASK_BNDCSR);
|
bndcsr = get_xsave_field_ptr(XFEATURE_BNDCSR);
|
||||||
if (!bndcsr)
|
if (!bndcsr)
|
||||||
goto exit_trap;
|
goto exit_trap;
|
||||||
|
|
||||||
|
@ -3674,15 +3674,15 @@ static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
|
|||||||
*/
|
*/
|
||||||
valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
|
valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
|
||||||
while (valid) {
|
while (valid) {
|
||||||
u64 feature = valid & -valid;
|
u64 xfeature_mask = valid & -valid;
|
||||||
int index = fls64(feature) - 1;
|
int xfeature_nr = fls64(xfeature_mask) - 1;
|
||||||
void *src = get_xsave_addr(xsave, feature);
|
void *src = get_xsave_addr(xsave, xfeature_nr);
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
u32 size, offset, ecx, edx;
|
u32 size, offset, ecx, edx;
|
||||||
cpuid_count(XSTATE_CPUID, index,
|
cpuid_count(XSTATE_CPUID, xfeature_nr,
|
||||||
&size, &offset, &ecx, &edx);
|
&size, &offset, &ecx, &edx);
|
||||||
if (feature == XFEATURE_MASK_PKRU)
|
if (xfeature_nr == XFEATURE_PKRU)
|
||||||
memcpy(dest + offset, &vcpu->arch.pkru,
|
memcpy(dest + offset, &vcpu->arch.pkru,
|
||||||
sizeof(vcpu->arch.pkru));
|
sizeof(vcpu->arch.pkru));
|
||||||
else
|
else
|
||||||
@ -3690,7 +3690,7 @@ static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valid -= feature;
|
valid -= xfeature_mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3717,22 +3717,22 @@ static void load_xsave(struct kvm_vcpu *vcpu, u8 *src)
|
|||||||
*/
|
*/
|
||||||
valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
|
valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
|
||||||
while (valid) {
|
while (valid) {
|
||||||
u64 feature = valid & -valid;
|
u64 xfeature_mask = valid & -valid;
|
||||||
int index = fls64(feature) - 1;
|
int xfeature_nr = fls64(xfeature_mask) - 1;
|
||||||
void *dest = get_xsave_addr(xsave, feature);
|
void *dest = get_xsave_addr(xsave, xfeature_nr);
|
||||||
|
|
||||||
if (dest) {
|
if (dest) {
|
||||||
u32 size, offset, ecx, edx;
|
u32 size, offset, ecx, edx;
|
||||||
cpuid_count(XSTATE_CPUID, index,
|
cpuid_count(XSTATE_CPUID, xfeature_nr,
|
||||||
&size, &offset, &ecx, &edx);
|
&size, &offset, &ecx, &edx);
|
||||||
if (feature == XFEATURE_MASK_PKRU)
|
if (xfeature_nr == XFEATURE_PKRU)
|
||||||
memcpy(&vcpu->arch.pkru, src + offset,
|
memcpy(&vcpu->arch.pkru, src + offset,
|
||||||
sizeof(vcpu->arch.pkru));
|
sizeof(vcpu->arch.pkru));
|
||||||
else
|
else
|
||||||
memcpy(dest, src + offset, size);
|
memcpy(dest, src + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
valid -= feature;
|
valid -= xfeature_mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8850,11 +8850,11 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||||||
if (init_event)
|
if (init_event)
|
||||||
kvm_put_guest_fpu(vcpu);
|
kvm_put_guest_fpu(vcpu);
|
||||||
mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
|
mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
|
||||||
XFEATURE_MASK_BNDREGS);
|
XFEATURE_BNDREGS);
|
||||||
if (mpx_state_buffer)
|
if (mpx_state_buffer)
|
||||||
memset(mpx_state_buffer, 0, sizeof(struct mpx_bndreg_state));
|
memset(mpx_state_buffer, 0, sizeof(struct mpx_bndreg_state));
|
||||||
mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
|
mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
|
||||||
XFEATURE_MASK_BNDCSR);
|
XFEATURE_BNDCSR);
|
||||||
if (mpx_state_buffer)
|
if (mpx_state_buffer)
|
||||||
memset(mpx_state_buffer, 0, sizeof(struct mpx_bndcsr));
|
memset(mpx_state_buffer, 0, sizeof(struct mpx_bndcsr));
|
||||||
if (init_event)
|
if (init_event)
|
||||||
|
@ -142,7 +142,7 @@ int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
/* get bndregs field from current task's xsave area */
|
/* get bndregs field from current task's xsave area */
|
||||||
bndregs = get_xsave_field_ptr(XFEATURE_MASK_BNDREGS);
|
bndregs = get_xsave_field_ptr(XFEATURE_BNDREGS);
|
||||||
if (!bndregs) {
|
if (!bndregs) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
@ -190,7 +190,7 @@ static __user void *mpx_get_bounds_dir(void)
|
|||||||
* The bounds directory pointer is stored in a register
|
* The bounds directory pointer is stored in a register
|
||||||
* only accessible if we first do an xsave.
|
* only accessible if we first do an xsave.
|
||||||
*/
|
*/
|
||||||
bndcsr = get_xsave_field_ptr(XFEATURE_MASK_BNDCSR);
|
bndcsr = get_xsave_field_ptr(XFEATURE_BNDCSR);
|
||||||
if (!bndcsr)
|
if (!bndcsr)
|
||||||
return MPX_INVALID_BOUNDS_DIR;
|
return MPX_INVALID_BOUNDS_DIR;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ static int do_mpx_bt_fault(void)
|
|||||||
const struct mpx_bndcsr *bndcsr;
|
const struct mpx_bndcsr *bndcsr;
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
|
|
||||||
bndcsr = get_xsave_field_ptr(XFEATURE_MASK_BNDCSR);
|
bndcsr = get_xsave_field_ptr(XFEATURE_BNDCSR);
|
||||||
if (!bndcsr)
|
if (!bndcsr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user