aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2018-12-19 11:25:14 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2018-12-19 16:19:22 -0500
commit3cf85f9f6bd7b172122865432b4c6f0ec844e22a (patch)
treece8aae5b8f1bc9328af30fb3c8bb67e976dc49ac
parent0e1b869fff60c81b510c2d00602d778f8f59dd9a (diff)
KVM: x86: nSVM: fix switch to guest mmu
Recent optimizations in MMU code broke nested SVM with NPT in L1 completely: when we do nested_svm_{,un}init_mmu_context() we want to switch from TDP MMU to shadow MMU, both init_kvm_tdp_mmu() and kvm_init_shadow_mmu() check if re-configuration is needed by looking at cache source data. The data, however, doesn't change - it's only the type of the MMU which changes. We end up not re-initializing guest MMU as shadow and everything goes off the rails. The issue could have been fixed by putting MMU type into extended MMU role but this is not really needed. We can just split root and guest MMUs the exact same way we did for nVMX, their types never change in the lifetime of a vCPU. There is still room for improvement: currently, we reset all MMU roots when switching from L1 to L2 and back and this is not needed. Fixes: 7dcd57552008 ("x86/kvm/mmu: check if tdp/shadow MMU reconfiguration is needed") Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/svm.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index cc6467b35a85..101f53ccf571 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2937,6 +2937,8 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
2937static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu) 2937static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
2938{ 2938{
2939 WARN_ON(mmu_is_nested(vcpu)); 2939 WARN_ON(mmu_is_nested(vcpu));
2940
2941 vcpu->arch.mmu = &vcpu->arch.guest_mmu;
2940 kvm_init_shadow_mmu(vcpu); 2942 kvm_init_shadow_mmu(vcpu);
2941 vcpu->arch.mmu->set_cr3 = nested_svm_set_tdp_cr3; 2943 vcpu->arch.mmu->set_cr3 = nested_svm_set_tdp_cr3;
2942 vcpu->arch.mmu->get_cr3 = nested_svm_get_tdp_cr3; 2944 vcpu->arch.mmu->get_cr3 = nested_svm_get_tdp_cr3;
@@ -2949,6 +2951,7 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
2949 2951
2950static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu) 2952static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu)
2951{ 2953{
2954 vcpu->arch.mmu = &vcpu->arch.root_mmu;
2952 vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; 2955 vcpu->arch.walk_mmu = &vcpu->arch.root_mmu;
2953} 2956}
2954 2957
@@ -3458,7 +3461,6 @@ static void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa,
3458 svm->vcpu.arch.hflags &= ~HF_HIF_MASK; 3461 svm->vcpu.arch.hflags &= ~HF_HIF_MASK;
3459 3462
3460 if (nested_vmcb->control.nested_ctl & SVM_NESTED_CTL_NP_ENABLE) { 3463 if (nested_vmcb->control.nested_ctl & SVM_NESTED_CTL_NP_ENABLE) {
3461 kvm_mmu_unload(&svm->vcpu);
3462 svm->nested.nested_cr3 = nested_vmcb->control.nested_cr3; 3464 svm->nested.nested_cr3 = nested_vmcb->control.nested_cr3;
3463 nested_svm_init_mmu_context(&svm->vcpu); 3465 nested_svm_init_mmu_context(&svm->vcpu);
3464 } 3466 }