Skip to content

Commit

Permalink
KVM: nVMX: Reset eVMCS clean fields data from prepare_vmcs02()
Browse files Browse the repository at this point in the history
When nested state migration happens during L1's execution, it
is incorrect to modify eVMCS as it is L1 who 'owns' it at the moment.
At least genuine Hyper-V seems to not be very happy when 'clean fields'
data changes underneath it.

'Clean fields' data is used in KVM twice: by copy_enlightened_to_vmcs12()
and prepare_vmcs02_rare() so we can reset it from prepare_vmcs02() instead.

While at it, update a comment stating why exactly we need to reset
'hv_clean_fields' data from L0.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20210526132026.270394-10-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
Vitaly Kuznetsov authored and Paolo Bonzini committed Jun 17, 2021
1 parent b7685cf commit dc31338
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions arch/x86/kvm/vmx/nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -2059,14 +2059,10 @@ void nested_sync_vmcs12_to_shadow(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);

if (evmptr_is_valid(vmx->nested.hv_evmcs_vmptr)) {
if (evmptr_is_valid(vmx->nested.hv_evmcs_vmptr))
copy_vmcs12_to_enlightened(vmx);
/* All fields are clean */
vmx->nested.hv_evmcs->hv_clean_fields |=
HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL;
} else {
else
copy_vmcs12_to_shadow(vmx);
}

vmx->nested.need_vmcs12_to_shadow_sync = false;
}
Expand Down Expand Up @@ -2616,6 +2612,17 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,

kvm_rsp_write(vcpu, vmcs12->guest_rsp);
kvm_rip_write(vcpu, vmcs12->guest_rip);

/*
* It was observed that genuine Hyper-V running in L1 doesn't reset
* 'hv_clean_fields' by itself, it only sets the corresponding dirty
* bits when it changes a field in eVMCS. Mark all fields as clean
* here.
*/
if (evmptr_is_valid(vmx->nested.hv_evmcs_vmptr))
vmx->nested.hv_evmcs->hv_clean_fields |=
HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL;

return 0;
}

Expand Down

0 comments on commit dc31338

Please sign in to comment.