kvm: svm: Only propagate next_rip when guest supports it
PATCH 1/1 kvm: svm: Only propagate next_rip when guest supports it
From: Joerg Roedel <[email protected]>
Currently we always write the next_rip of the shadow vmcb to the guests vmcb when we emulate a vmexit. This could confuse the guest when its cpuid indicated no support for the next_rip feature.
Fix this by only propagating next_rip if the guest actually supports it.
--- arch/x86/kvm/cpuid.h | 21 +++++++++++++++++++++ arch/x86/kvm/svm.c | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-)
arch/x86/kvm/cpuid.h +21 -0
@@ -133,4 +133,25 @@ static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) best =kvm_find_cpuid_entry (vcpu,7 ,0 ); return best && (best->ebx & bit(X86_FEATURE_MPX)); } + +/* +* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3 +*/ +#define BIT_NRIPS 3 + +static inline bool guest_cpuid_has_nrips (struct kvm_vcpu *vcpu) +{ +struct kvm_cpuid_entry2 *best; + + best =kvm_find_cpuid_entry (vcpu,0x8000000a ,0 ); + +/* +* NRIPS is a scattered cpuid feature, so we can't use +* X86_FEATURE_NRIPS here (X86_FEATURE_NRIPS would be bit +* position 8, not 3). +*/ +return best && (best->edx &bit (BIT_NRIPS )); +} +#undef BIT_NRIPS +#endif
arch/x86/kvm/svm.c +3 -1
@@ -2365,7 +2365,9 @@ static int nested_svm_vmexit(struct vcpu_svm *svm) nested_vmcb->control.exit_info_2 = vmcb->control.exit_info_2; nested_vmcb->control.exit_int_info = vmcb->control.exit_int_info; nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err; - nested_vmcb->control.next_rip = vmcb->control.next_rip; + +if (guest_cpuid_has_nrips (&svm->vcpu)) + nested_vmcb->control.next_rip = vmcb->control.next_rip;/* * If we emulate a VMRUN/#VMEXIT in the same host #vmexit cycle we have
Signature · 1 line
1.9.1
Paolo Bonzini
maintainerQuoted 54 lines · Joerg Roedel
From: Joerg Roedel <[email protected]>
Currently we always write the
next_ripof the shadow vmcb to the guests vmcb when we emulate a vmexit. This could confuse the guest when its cpuid indicated no support for thenext_ripfeature.Fix this by only propagating
next_ripif the guest actually supports it.Cc Bandan Das <[email protected]>Cc Dirk Mueller <[email protected]>Tested-by Dirk Mueller <[email protected]>Signed-off-by Joerg Roedel <[email protected]>--- arch/x86/kvm/cpuid.h | 21 +++++++++++++++++++++ arch/x86/kvm/svm.c | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-)arch/x86/kvm/cpuid.h +21
-0@@ -133,4 +133,25 @@ static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) best =kvm_find_cpuid_entry (vcpu,7 ,0 ); return best && (best->ebx & bit(X86_FEATURE_MPX)); } + +/* +* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3 +*/ +#define BIT_NRIPS 3 + +static inline bool guest_cpuid_has_nrips (struct kvm_vcpu *vcpu) +{ +struct kvm_cpuid_entry2 *best; + + best =kvm_find_cpuid_entry (vcpu,0x8000000a ,0 ); + +/* +* NRIPS is a scattered cpuid feature, so we can't use +* X86_FEATURE_NRIPS here (X86_FEATURE_NRIPS would be bit +* position 8, not 3). +*/ +return best && (best->edx &bit (BIT_NRIPS )); +} +#undef BIT_NRIPS +#endif arch/x86/kvm/svm.c +0
-0
arch/x86/kvm/svm.c static int nested_svm_vmexit(struct vcpu_svm *svm) · line 2369
Quoted 6 lines
arch/x86/kvm/svm.c +2
-1@@ -2365,7 +2365,9 @@ static int nested_svm_vmexit(struct vcpu_svm *svm) nested_vmcb->control.exit_info_2 = vmcb->control.exit_info_2; nested_vmcb->control.exit_int_info = vmcb->control.exit_int_info; nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err; - nested_vmcb->control.next_rip = vmcb->control.next_rip; + +if (guest_cpuid_has_nrips (&svm->vcpu))
This could be a bit expensive to do on every vmexit. Can you benchmark it with kvm-unit-tests, or just cache the result in struct vcpu_svm?
Thanks,
Paolo
Quoted 5 lines
arch/x86/kvm/svm.c +1
-0+ nested_vmcb->control.next_rip = vmcb->control.next_rip;/* * If we emulate a VMRUN/#VMEXIT in the same host #vmexit cycle we have
PATCH v2 1/1 kvm: svm: Only propagate next_rip when guest supports it
Quoted 2 lines · Paolo Bonzini
This could be a bit expensive to do on every vmexit. Can you benchmark it with kvm-unit-tests, or just cache the result in struct
vcpu_svm?
Yes, caching it is certainly a good idea. I updated the patch:
Quoted 1 line
From
94ee662c527683c26ea5fa98a5a8f2c798c58470Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Wed, 7 Oct 2015 13:38:19 +0200
Subject: [PATCH] kvm: svm: Only propagate next_rip when guest supports it
Currently we always write the next_rip of the shadow vmcb to the guests vmcb when we emulate a vmexit. This could confuse the guest when its cpuid indicated no support for the next_rip feature.
Fix this by only propagating next_rip if the guest actually supports it.
--- arch/x86/kvm/cpuid.h | 21 +++++++++++++++++++++ arch/x86/kvm/svm.c | 11 ++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-)
arch/x86/kvm/cpuid.h +21 -0
@@ -133,4 +133,25 @@ static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) best =kvm_find_cpuid_entry (vcpu,7 ,0 ); return best && (best->ebx & bit(X86_FEATURE_MPX)); } + +/* +* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3 +*/ +#define BIT_NRIPS 3 + +static inline bool guest_cpuid_has_nrips (struct kvm_vcpu *vcpu) +{ +struct kvm_cpuid_entry2 *best; + + best =kvm_find_cpuid_entry (vcpu,0x8000000a ,0 ); + +/* +* NRIPS is a scattered cpuid feature, so we can't use +* X86_FEATURE_NRIPS here (X86_FEATURE_NRIPS would be bit +* position 8, not 3). +*/ +return best && (best->edx &bit (BIT_NRIPS )); +} +#undef BIT_NRIPS +#endif
arch/x86/kvm/svm.c +10 -1
@@ -159,6 +159,9 @@ struct vcpu_svm {u32 apf_reason;u64 tsc_ratio; + +/* cached guest cpuid flags for faster access */ + bool nrips_enabled : 1; }; static DEFINE_PER_CPU(u64, current_tsc_ratio);
@@ -2365,7 +2368,9 @@ static int nested_svm_vmexit(struct vcpu_svm *svm) nested_vmcb->control.exit_info_2 = vmcb->control.exit_info_2; nested_vmcb->control.exit_int_info = vmcb->control.exit_int_info; nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err; - nested_vmcb->control.next_rip = vmcb->control.next_rip; + +if (svm->nrips_enabled) + nested_vmcb->control.next_rip = vmcb->control.next_rip;/* * If we emulate a VMRUN/#VMEXIT in the same host #vmexit cycle we have
@@ -4098,6 +4103,10 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)static void svm_cpuid_update (struct kvm_vcpu *vcpu) { +struct vcpu_svm *svm =to_svm (vcpu); + +/* Update nrips enabled cache */ + svm->nrips_enabled = !!guest_cpuid_has_nrips (&svm->vcpu); }static void svm_set_supported_cpuid (u32 func,struct kvm_cpuid_entry2 *entry)
Signature · 1 line
1.8.4.5
Quoted 79 lines · Joerg Roedel
From
94ee662c527683c26ea5fa98a5a8f2c798c58470Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Wed, 7 Oct 2015 13:38:19 +0200
Subject: [PATCH] kvm: svm: Only propagatenext_ripwhen guest supports itCurrently we always write the
next_ripof the shadow vmcb to the guests vmcb when we emulate a vmexit. This could confuse the guest when its cpuid indicated no support for thenext_ripfeature.Fix this by only propagating
next_ripif the guest actually supports it.Cc Bandan Das <[email protected]>Cc Dirk Mueller <[email protected]>Tested-by Dirk Mueller <[email protected]>Signed-off-by Joerg Roedel <[email protected]>--- arch/x86/kvm/cpuid.h | 21 +++++++++++++++++++++ arch/x86/kvm/svm.c | 11 ++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-)arch/x86/kvm/cpuid.h +21
-0@@ -133,4 +133,25 @@ static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) best =kvm_find_cpuid_entry (vcpu,7 ,0 ); return best && (best->ebx & bit(X86_FEATURE_MPX)); } + +/* +* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3 +*/ +#define BIT_NRIPS 3 + +static inline bool guest_cpuid_has_nrips (struct kvm_vcpu *vcpu) +{ +struct kvm_cpuid_entry2 *best; + + best =kvm_find_cpuid_entry (vcpu,0x8000000a ,0 ); + +/* +* NRIPS is a scattered cpuid feature, so we can't use +* X86_FEATURE_NRIPS here (X86_FEATURE_NRIPS would be bit +* position 8, not 3). +*/ +return best && (best->edx &bit (BIT_NRIPS )); +} +#undef BIT_NRIPS +#endif arch/x86/kvm/svm.c +6
-1@@ -159,6 +159,9 @@ struct vcpu_svm {u32 apf_reason;u64 tsc_ratio; + +/* cached guest cpuid flags for faster access */ + bool nrips_enabled : 1; }; static DEFINE_PER_CPU(u64, current_tsc_ratio);@@ -2365,7 +2368,9 @@ static int nested_svm_vmexit(struct vcpu_svm *svm) nested_vmcb->control.exit_info_2 = vmcb->control.exit_info_2; nested_vmcb->control.exit_int_info = vmcb->control.exit_int_info; nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err; - nested_vmcb->control.next_rip = vmcb->control.next_rip; + +if (svm->nrips_enabled) + nested_vmcb->control.next_rip = vmcb->control.next_rip;/* * If we emulate a VMRUN/#VMEXIT in the same host #vmexit cycle we have
arch/x86/kvm/svm.c static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) · line 4112
Quoted 10 lines
arch/x86/kvm/svm.c +4
-0@@ -4098,6 +4103,10 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)static void svm_cpuid_update (struct kvm_vcpu *vcpu) { +struct vcpu_svm *svm =to_svm (vcpu); + +/* Update nrips enabled cache */ + svm->nrips_enabled = !!guest_cpuid_has_nrips (&svm->vcpu); }static void svm_set_supported_cpuid (u32 func,struct kvm_cpuid_entry2 *entry)
Applied to kvm/queue, thanks.
Paolo