diff mbox series

[2/2] KVM: nVMX: Fix emulation of VM_ENTRY_LOAD_BNDCFGS

Message ID 20180913124319.49663-3-liran.alon@oracle.com (mailing list archive)
State New, archived
Headers show
Series : KVM: nVMX: Fix bugs in MPX VMX controls emulation | expand

Commit Message

Liran Alon Sept. 13, 2018, 12:43 p.m. UTC
L2 IA32_BNDCFGS should be updated with vmcs12->guest_bndcfgs only
when VM_ENTRY_LOAD_BNDCFGS is specified in vmcs12->vm_entry_controls.

Otherwise, L2 IA32_BNDCFGS should be set to vmcs01->guest_bndcfgs which
is L1 IA32_BNDCFGS.

Reviewed-by: Nikita Leshchenko <nikita.leshchenko@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 arch/x86/kvm/vmx.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Sean Christopherson Sept. 13, 2018, 1:41 p.m. UTC | #1
On Thu, Sep 13, 2018 at 03:43:19PM +0300, Liran Alon wrote:
> L2 IA32_BNDCFGS should be updated with vmcs12->guest_bndcfgs only
> when VM_ENTRY_LOAD_BNDCFGS is specified in vmcs12->vm_entry_controls.
> 
> Otherwise, L2 IA32_BNDCFGS should be set to vmcs01->guest_bndcfgs which
> is L1 IA32_BNDCFGS.
> 
> Reviewed-by: Nikita Leshchenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
> Signed-off-by: Liran Alon <liran.alon@oracle.com>
> ---
>  arch/x86/kvm/vmx.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 6a82e603f2c5..3259775814d0 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -856,6 +856,7 @@ struct nested_vmx {
>  
>  	/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
>  	u64 vmcs01_debugctl;
> +	u64 vmcs01_guest_bndcfgs;
>  
>  	u16 vpid02;
>  	u16 last_vpid;
> @@ -12028,8 +12029,13 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
>  
>  	set_cr4_guest_host_mask(vmx);
>  
> -	if (vmx_mpx_supported())
> -		vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
> +	if (vmx_mpx_supported()) {
> +		if (vmx->nested.nested_run_pending &&
> +			(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
> +			vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
> +		else
> +			vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
> +	}
>  
>  	if (enable_vpid) {
>  		u16 vmcs02_vpid;
> @@ -12597,6 +12603,8 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
>  
>  	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
>  		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
> +	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
> +		vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);

This needs to be wrapped with vmx_mpx_supported() else you'll VMREAD a
non-existent field.

>  
>  	vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
>  	vmx_segment_cache_clear(vmx);
> -- 
> 2.16.1
>
Liran Alon Sept. 13, 2018, 1:45 p.m. UTC | #2
> On 13 Sep 2018, at 16:41, Sean Christopherson <sean.j.christopherson@intel.com> wrote:
> 
> On Thu, Sep 13, 2018 at 03:43:19PM +0300, Liran Alon wrote:
>> L2 IA32_BNDCFGS should be updated with vmcs12->guest_bndcfgs only
>> when VM_ENTRY_LOAD_BNDCFGS is specified in vmcs12->vm_entry_controls.
>> 
>> Otherwise, L2 IA32_BNDCFGS should be set to vmcs01->guest_bndcfgs which
>> is L1 IA32_BNDCFGS.
>> 
>> Reviewed-by: Nikita Leshchenko <nikita.leshchenko@oracle.com>
>> Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
>> Signed-off-by: Liran Alon <liran.alon@oracle.com>
>> ---
>> arch/x86/kvm/vmx.c | 12 ++++++++++--
>> 1 file changed, 10 insertions(+), 2 deletions(-)
>> 
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index 6a82e603f2c5..3259775814d0 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -856,6 +856,7 @@ struct nested_vmx {
>> 
>> 	/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
>> 	u64 vmcs01_debugctl;
>> +	u64 vmcs01_guest_bndcfgs;
>> 
>> 	u16 vpid02;
>> 	u16 last_vpid;
>> @@ -12028,8 +12029,13 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
>> 
>> 	set_cr4_guest_host_mask(vmx);
>> 
>> -	if (vmx_mpx_supported())
>> -		vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
>> +	if (vmx_mpx_supported()) {
>> +		if (vmx->nested.nested_run_pending &&
>> +			(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
>> +			vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
>> +		else
>> +			vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
>> +	}
>> 
>> 	if (enable_vpid) {
>> 		u16 vmcs02_vpid;
>> @@ -12597,6 +12603,8 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
>> 
>> 	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
>> 		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
>> +	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
>> +		vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
> 
> This needs to be wrapped with vmx_mpx_supported() else you'll VMREAD a
> non-existent field.

Oops. You are right. Will fix in v2.

Thanks,
-Liran

> 
>> 
>> 	vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
>> 	vmx_segment_cache_clear(vmx);
>> -- 
>> 2.16.1
>>
Sean Christopherson Sept. 13, 2018, 1:59 p.m. UTC | #3
On Thu, Sep 13, 2018 at 04:45:01PM +0300, Liran Alon wrote:
> 
> 
> > On 13 Sep 2018, at 16:41, Sean Christopherson <sean.j.christopherson@intel.com> wrote:
> > 
> > On Thu, Sep 13, 2018 at 03:43:19PM +0300, Liran Alon wrote:
> >> L2 IA32_BNDCFGS should be updated with vmcs12->guest_bndcfgs only
> >> when VM_ENTRY_LOAD_BNDCFGS is specified in vmcs12->vm_entry_controls.
> >> 
> >> Otherwise, L2 IA32_BNDCFGS should be set to vmcs01->guest_bndcfgs which
> >> is L1 IA32_BNDCFGS.
> >> 
> >> Reviewed-by: Nikita Leshchenko <nikita.leshchenko@oracle.com>
> >> Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
> >> Signed-off-by: Liran Alon <liran.alon@oracle.com>
> >> ---
> >> arch/x86/kvm/vmx.c | 12 ++++++++++--
> >> 1 file changed, 10 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> >> index 6a82e603f2c5..3259775814d0 100644
> >> --- a/arch/x86/kvm/vmx.c
> >> +++ b/arch/x86/kvm/vmx.c
> >> @@ -856,6 +856,7 @@ struct nested_vmx {
> >> 
> >> 	/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
> >> 	u64 vmcs01_debugctl;
> >> +	u64 vmcs01_guest_bndcfgs;
> >> 
> >> 	u16 vpid02;
> >> 	u16 last_vpid;
> >> @@ -12028,8 +12029,13 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
> >> 
> >> 	set_cr4_guest_host_mask(vmx);
> >> 
> >> -	if (vmx_mpx_supported())
> >> -		vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
> >> +	if (vmx_mpx_supported()) {
> >> +		if (vmx->nested.nested_run_pending &&
> >> +			(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
> >> +			vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
> >> +		else
> >> +			vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
> >> +	}
> >> 
> >> 	if (enable_vpid) {
> >> 		u16 vmcs02_vpid;
> >> @@ -12597,6 +12603,8 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
> >> 
> >> 	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
> >> 		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
> >> +	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
> >> +		vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
> > 
> > This needs to be wrapped with vmx_mpx_supported() else you'll VMREAD a
> > non-existent field.
> 
> Oops. You are right. Will fix in v2.

After reading through the existing code a bit more, I think all calls
to vmx_mpx_supported() should be replaced with kvm_mpx_supported().
The KVM version returns true iff MPX is enabled in the host, and was
added by commit a87036add092 ("KVM: x86: disable MPX if host did not
enable MPX XSAVE features").
Liran Alon Sept. 13, 2018, 11:14 p.m. UTC | #4
> On 13 Sep 2018, at 16:59, Sean Christopherson <sean.j.christopherson@intel.com> wrote:
> 
> After reading through the existing code a bit more, I think all calls
> to vmx_mpx_supported() should be replaced with kvm_mpx_supported().
> The KVM version returns true iff MPX is enabled in the host, and was
> added by commit a87036add092 ("KVM: x86: disable MPX if host did not
> enable MPX XSAVE features").

I agree.
This should also include the call kvm_x86_ops->mpx_supported() inside kvm_init_msr_list().
Do you think it is preferable to do your suggested patch before or after the patch discussed in this email thread?

-Liran
Sean Christopherson Sept. 13, 2018, 11:38 p.m. UTC | #5
On Fri, Sep 14, 2018 at 02:14:49AM +0300, Liran Alon wrote:
> 
> 
> > On 13 Sep 2018, at 16:59, Sean Christopherson <sean.j.christopherson@intel.com> wrote:
> > 
> > After reading through the existing code a bit more, I think all calls
> > to vmx_mpx_supported() should be replaced with kvm_mpx_supported().
> > The KVM version returns true iff MPX is enabled in the host, and was
> > added by commit a87036add092 ("KVM: x86: disable MPX if host did not
> > enable MPX XSAVE features").
> 
> I agree.
> This should also include the call kvm_x86_ops->mpx_supported() inside kvm_init_msr_list().
> Do you think it is preferable to do your suggested patch before or after the patch discussed in this email thread?

Probably before?  Only because it seems weird to knowingly do the
wrong thing.
diff mbox series

Patch

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6a82e603f2c5..3259775814d0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -856,6 +856,7 @@  struct nested_vmx {
 
 	/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
 	u64 vmcs01_debugctl;
+	u64 vmcs01_guest_bndcfgs;
 
 	u16 vpid02;
 	u16 last_vpid;
@@ -12028,8 +12029,13 @@  static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 
 	set_cr4_guest_host_mask(vmx);
 
-	if (vmx_mpx_supported())
-		vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
+	if (vmx_mpx_supported()) {
+		if (vmx->nested.nested_run_pending &&
+			(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
+			vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
+		else
+			vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
+	}
 
 	if (enable_vpid) {
 		u16 vmcs02_vpid;
@@ -12597,6 +12603,8 @@  static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
 
 	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
 		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
+		vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
 
 	vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
 	vmx_segment_cache_clear(vmx);