diff options
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r-- | arch/x86/kvm/svm.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index b756e876dce3..8233b86c778c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -62,6 +62,7 @@ static int npt = 1; | |||
62 | module_param(npt, int, S_IRUGO); | 62 | module_param(npt, int, S_IRUGO); |
63 | 63 | ||
64 | static void kvm_reput_irq(struct vcpu_svm *svm); | 64 | static void kvm_reput_irq(struct vcpu_svm *svm); |
65 | static void svm_flush_tlb(struct kvm_vcpu *vcpu); | ||
65 | 66 | ||
66 | static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) | 67 | static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) |
67 | { | 68 | { |
@@ -453,7 +454,8 @@ static __init int svm_hardware_setup(void) | |||
453 | if (npt_enabled) { | 454 | if (npt_enabled) { |
454 | printk(KERN_INFO "kvm: Nested Paging enabled\n"); | 455 | printk(KERN_INFO "kvm: Nested Paging enabled\n"); |
455 | kvm_enable_tdp(); | 456 | kvm_enable_tdp(); |
456 | } | 457 | } else |
458 | kvm_disable_tdp(); | ||
457 | 459 | ||
458 | return 0; | 460 | return 0; |
459 | 461 | ||
@@ -877,6 +879,10 @@ set: | |||
877 | static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | 879 | static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) |
878 | { | 880 | { |
879 | unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE; | 881 | unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE; |
882 | unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4; | ||
883 | |||
884 | if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE)) | ||
885 | force_new_asid(vcpu); | ||
880 | 886 | ||
881 | vcpu->arch.cr4 = cr4; | 887 | vcpu->arch.cr4 = cr4; |
882 | if (!npt_enabled) | 888 | if (!npt_enabled) |
@@ -1007,10 +1013,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | |||
1007 | struct kvm *kvm = svm->vcpu.kvm; | 1013 | struct kvm *kvm = svm->vcpu.kvm; |
1008 | u64 fault_address; | 1014 | u64 fault_address; |
1009 | u32 error_code; | 1015 | u32 error_code; |
1016 | bool event_injection = false; | ||
1010 | 1017 | ||
1011 | if (!irqchip_in_kernel(kvm) && | 1018 | if (!irqchip_in_kernel(kvm) && |
1012 | is_external_interrupt(exit_int_info)) | 1019 | is_external_interrupt(exit_int_info)) { |
1020 | event_injection = true; | ||
1013 | push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); | 1021 | push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); |
1022 | } | ||
1014 | 1023 | ||
1015 | fault_address = svm->vmcb->control.exit_info_2; | 1024 | fault_address = svm->vmcb->control.exit_info_2; |
1016 | error_code = svm->vmcb->control.exit_info_1; | 1025 | error_code = svm->vmcb->control.exit_info_1; |
@@ -1023,7 +1032,16 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | |||
1023 | KVMTRACE_3D(TDP_FAULT, &svm->vcpu, error_code, | 1032 | KVMTRACE_3D(TDP_FAULT, &svm->vcpu, error_code, |
1024 | (u32)fault_address, (u32)(fault_address >> 32), | 1033 | (u32)fault_address, (u32)(fault_address >> 32), |
1025 | handler); | 1034 | handler); |
1035 | /* | ||
1036 | * FIXME: Tis shouldn't be necessary here, but there is a flush | ||
1037 | * missing in the MMU code. Until we find this bug, flush the | ||
1038 | * complete TLB here on an NPF | ||
1039 | */ | ||
1040 | if (npt_enabled) | ||
1041 | svm_flush_tlb(&svm->vcpu); | ||
1026 | 1042 | ||
1043 | if (event_injection) | ||
1044 | kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address); | ||
1027 | return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); | 1045 | return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); |
1028 | } | 1046 | } |
1029 | 1047 | ||