Skip to content

Commit 4cdf351

Browse files
sean-jcbonzini
authored andcommitted
KVM: SVM: Update EFER software model on CR0 trap for SEV-ES
In general, activating long mode involves setting the EFER_LME bit in the EFER register and then enabling the X86_CR0_PG bit in the CR0 register. At this point, the EFER_LMA bit will be set automatically by hardware. In the case of SVM/SEV guests where writes to CR0 are intercepted, it's necessary for the host to set EFER_LMA on behalf of the guest since hardware does not see the actual CR0 write. In the case of SEV-ES guests where writes to CR0 are trapped instead of intercepted, the hardware *does* see/record the write to CR0 before exiting and passing the value on to the host, so as part of enabling SEV-ES support commit f1c6366 ("KVM: SVM: Add required changes to support intercepts under SEV-ES") dropped special handling of the EFER_LMA bit with the understanding that it would be set automatically. However, since the guest never explicitly sets the EFER_LMA bit, the host never becomes aware that it has been set. This becomes problematic when userspace tries to get/set the EFER values via KVM_GET_SREGS/KVM_SET_SREGS, since the EFER contents tracked by the host will be missing the EFER_LMA bit, and when userspace attempts to pass the EFER value back via KVM_SET_SREGS it will fail a sanity check that asserts that EFER_LMA should always be set when X86_CR0_PG and EFER_LME are set. Fix this by always inferring the value of EFER_LMA based on X86_CR0_PG and EFER_LME, regardless of whether or not SEV-ES is enabled. Fixes: f1c6366 ("KVM: SVM: Add required changes to support intercepts under SEV-ES") Reported-by: Peter Gonda <pgonda@google.com> Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20210507165947.2502412-2-seanjc@google.com> [A two year old patch that was revived after we noticed the failure in KVM_SET_SREGS and a similar patch was posted by Michael Roth. This is Sean's patch, but with Michael's more complete commit message. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 96f1240 commit 4cdf351

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

arch/x86/kvm/svm/svm.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,15 +1855,17 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
18551855
bool old_paging = is_paging(vcpu);
18561856

18571857
#ifdef CONFIG_X86_64
1858-
if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) {
1858+
if (vcpu->arch.efer & EFER_LME) {
18591859
if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
18601860
vcpu->arch.efer |= EFER_LMA;
1861-
svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
1861+
if (!vcpu->arch.guest_state_protected)
1862+
svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
18621863
}
18631864

18641865
if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
18651866
vcpu->arch.efer &= ~EFER_LMA;
1866-
svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
1867+
if (!vcpu->arch.guest_state_protected)
1868+
svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
18671869
}
18681870
}
18691871
#endif

0 commit comments

Comments
 (0)