Merge tag 'kvm-4.20-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-block.git] / arch / x86 / kvm / svm.c
index 61ccfb13899ed702d8ab7dc88bdb5489b34bcfeb..0e21ccc46792f6bcc6665ff63979f23979aa1829 100644 (file)
@@ -809,6 +809,8 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu)
            nested_svm_check_exception(svm, nr, has_error_code, error_code))
                return;
 
+       kvm_deliver_exception_payload(&svm->vcpu);
+
        if (nr == BP_VECTOR && !static_cpu_has(X86_FEATURE_NRIPS)) {
                unsigned long rip, old_rip = kvm_rip_read(&svm->vcpu);
 
@@ -2922,18 +2924,18 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
 {
        WARN_ON(mmu_is_nested(vcpu));
        kvm_init_shadow_mmu(vcpu);
-       vcpu->arch.mmu.set_cr3           = nested_svm_set_tdp_cr3;
-       vcpu->arch.mmu.get_cr3           = nested_svm_get_tdp_cr3;
-       vcpu->arch.mmu.get_pdptr         = nested_svm_get_tdp_pdptr;
-       vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
-       vcpu->arch.mmu.shadow_root_level = get_npt_level(vcpu);
-       reset_shadow_zero_bits_mask(vcpu, &vcpu->arch.mmu);
+       vcpu->arch.mmu->set_cr3           = nested_svm_set_tdp_cr3;
+       vcpu->arch.mmu->get_cr3           = nested_svm_get_tdp_cr3;
+       vcpu->arch.mmu->get_pdptr         = nested_svm_get_tdp_pdptr;
+       vcpu->arch.mmu->inject_page_fault = nested_svm_inject_npf_exit;
+       vcpu->arch.mmu->shadow_root_level = get_npt_level(vcpu);
+       reset_shadow_zero_bits_mask(vcpu, vcpu->arch.mmu);
        vcpu->arch.walk_mmu              = &vcpu->arch.nested_mmu;
 }
 
 static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu)
 {
-       vcpu->arch.walk_mmu = &vcpu->arch.mmu;
+       vcpu->arch.walk_mmu = &vcpu->arch.root_mmu;
 }
 
 static int nested_svm_check_permissions(struct vcpu_svm *svm)
@@ -2969,16 +2971,13 @@ static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
        svm->vmcb->control.exit_info_1 = error_code;
 
        /*
-        * FIXME: we should not write CR2 when L1 intercepts an L2 #PF exception.
-        * The fix is to add the ancillary datum (CR2 or DR6) to structs
-        * kvm_queued_exception and kvm_vcpu_events, so that CR2 and DR6 can be
-        * written only when inject_pending_event runs (DR6 would written here
-        * too).  This should be conditional on a new capability---if the
-        * capability is disabled, kvm_multiple_exception would write the
-        * ancillary information to CR2 or DR6, for backwards ABI-compatibility.
+        * EXITINFO2 is undefined for all exception intercepts other
+        * than #PF.
         */
        if (svm->vcpu.arch.exception.nested_apf)
                svm->vmcb->control.exit_info_2 = svm->vcpu.arch.apf.nested_apf_token;
+       else if (svm->vcpu.arch.exception.has_payload)
+               svm->vmcb->control.exit_info_2 = svm->vcpu.arch.exception.payload;
        else
                svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2;
 
@@ -5642,26 +5641,24 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
                "mov %%r13, %c[r13](%[svm]) \n\t"
                "mov %%r14, %c[r14](%[svm]) \n\t"
                "mov %%r15, %c[r15](%[svm]) \n\t"
-#endif
                /*
                * Clear host registers marked as clobbered to prevent
                * speculative use.
                */
-               "xor %%" _ASM_BX ", %%" _ASM_BX " \n\t"
-               "xor %%" _ASM_CX ", %%" _ASM_CX " \n\t"
-               "xor %%" _ASM_DX ", %%" _ASM_DX " \n\t"
-               "xor %%" _ASM_SI ", %%" _ASM_SI " \n\t"
-               "xor %%" _ASM_DI ", %%" _ASM_DI " \n\t"
-#ifdef CONFIG_X86_64
-               "xor %%r8, %%r8 \n\t"
-               "xor %%r9, %%r9 \n\t"
-               "xor %%r10, %%r10 \n\t"
-               "xor %%r11, %%r11 \n\t"
-               "xor %%r12, %%r12 \n\t"
-               "xor %%r13, %%r13 \n\t"
-               "xor %%r14, %%r14 \n\t"
-               "xor %%r15, %%r15 \n\t"
+               "xor %%r8d, %%r8d \n\t"
+               "xor %%r9d, %%r9d \n\t"
+               "xor %%r10d, %%r10d \n\t"
+               "xor %%r11d, %%r11d \n\t"
+               "xor %%r12d, %%r12d \n\t"
+               "xor %%r13d, %%r13d \n\t"
+               "xor %%r14d, %%r14d \n\t"
+               "xor %%r15d, %%r15d \n\t"
 #endif
+               "xor %%ebx, %%ebx \n\t"
+               "xor %%ecx, %%ecx \n\t"
+               "xor %%edx, %%edx \n\t"
+               "xor %%esi, %%esi \n\t"
+               "xor %%edi, %%edi \n\t"
                "pop %%" _ASM_BP
                :
                : [svm]"a"(svm),
@@ -7040,6 +7037,13 @@ failed:
        return ret;
 }
 
+static int nested_enable_evmcs(struct kvm_vcpu *vcpu,
+                                  uint16_t *vmcs_version)
+{
+       /* Intel-only feature */
+       return -ENODEV;
+}
+
 static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
@@ -7169,6 +7173,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .mem_enc_op = svm_mem_enc_op,
        .mem_enc_reg_region = svm_register_enc_region,
        .mem_enc_unreg_region = svm_unregister_enc_region,
+
+       .nested_enable_evmcs = nested_enable_evmcs,
 };
 
 static int __init svm_init(void)