Commit c447e76b authored by Liang Li's avatar Liang Li Committed by Paolo Bonzini

kvm/fpu: Enable eager restore kvm FPU for MPX

The MPX feature requires eager KVM FPU restore support. We have verified
that MPX cannot work correctly with the current lazy KVM FPU restore
mechanism. Eager KVM FPU restore should be enabled if the MPX feature is
exposed to VM.
Signed-off-by: default avatarYang Zhang <yang.z.zhang@intel.com>
Signed-off-by: default avatarLiang Li <liang.z.li@intel.com>
[Also activate the FPU on AMD processors. - Paolo]
Cc: stable@vger.kernel.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 0fdd74f7
...@@ -401,6 +401,7 @@ struct kvm_vcpu_arch { ...@@ -401,6 +401,7 @@ struct kvm_vcpu_arch {
struct kvm_mmu_memory_cache mmu_page_header_cache; struct kvm_mmu_memory_cache mmu_page_header_cache;
struct fpu guest_fpu; struct fpu guest_fpu;
bool eager_fpu;
u64 xcr0; u64 xcr0;
u64 guest_supported_xcr0; u64 guest_supported_xcr0;
u32 guest_xstate_size; u32 guest_xstate_size;
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/i387.h> /* For use_eager_fpu. Ugh! */
#include <asm/fpu-internal.h> /* For use_eager_fpu. Ugh! */
#include <asm/user.h> #include <asm/user.h>
#include <asm/xsave.h> #include <asm/xsave.h>
#include "cpuid.h" #include "cpuid.h"
...@@ -95,6 +97,8 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) ...@@ -95,6 +97,8 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
if (best && (best->eax & (F(XSAVES) | F(XSAVEC)))) if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
best->ebx = xstate_required_size(vcpu->arch.xcr0, true); best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
vcpu->arch.eager_fpu = guest_cpuid_has_mpx(vcpu);
/* /*
* The existing code assumes virtual address is 48-bit in the canonical * The existing code assumes virtual address is 48-bit in the canonical
* address checks; exit if it is ever changed. * address checks; exit if it is ever changed.
......
...@@ -117,4 +117,12 @@ static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu) ...@@ -117,4 +117,12 @@ static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu)
best = kvm_find_cpuid_entry(vcpu, 7, 0); best = kvm_find_cpuid_entry(vcpu, 7, 0);
return best && (best->ebx & bit(X86_FEATURE_RTM)); return best && (best->ebx & bit(X86_FEATURE_RTM));
} }
static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
best = kvm_find_cpuid_entry(vcpu, 7, 0);
return best && (best->ebx & bit(X86_FEATURE_MPX));
}
#endif #endif
...@@ -7060,7 +7060,9 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) ...@@ -7060,7 +7060,9 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
fpu_save_init(&vcpu->arch.guest_fpu); fpu_save_init(&vcpu->arch.guest_fpu);
__kernel_fpu_end(); __kernel_fpu_end();
++vcpu->stat.fpu_reload; ++vcpu->stat.fpu_reload;
kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); if (!vcpu->arch.eager_fpu)
kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
trace_kvm_fpu(0); trace_kvm_fpu(0);
} }
...@@ -7076,11 +7078,21 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) ...@@ -7076,11 +7078,21 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
unsigned int id) unsigned int id)
{ {
struct kvm_vcpu *vcpu;
if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0) if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0)
printk_once(KERN_WARNING printk_once(KERN_WARNING
"kvm: SMP vm created on host with unstable TSC; " "kvm: SMP vm created on host with unstable TSC; "
"guest TSC will not be reliable\n"); "guest TSC will not be reliable\n");
return kvm_x86_ops->vcpu_create(kvm, id);
vcpu = kvm_x86_ops->vcpu_create(kvm, id);
/*
* Activate fpu unconditionally in case the guest needs eager FPU. It will be
* deactivated soon if it doesn't.
*/
kvm_x86_ops->fpu_activate(vcpu);
return vcpu;
} }
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
......
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