diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 336 |
1 files changed, 316 insertions, 20 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 02eeba86328d..fe9a9cfadbd6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -84,6 +84,9 @@ module_param(vmm_exclusive, bool, S_IRUGO); | |||
84 | static bool __read_mostly fasteoi = 1; | 84 | static bool __read_mostly fasteoi = 1; |
85 | module_param(fasteoi, bool, S_IRUGO); | 85 | module_param(fasteoi, bool, S_IRUGO); |
86 | 86 | ||
87 | static bool __read_mostly enable_apicv_reg_vid = 1; | ||
88 | module_param(enable_apicv_reg_vid, bool, S_IRUGO); | ||
89 | |||
87 | /* | 90 | /* |
88 | * If nested=1, nested virtualization is supported, i.e., guests may use | 91 | * If nested=1, nested virtualization is supported, i.e., guests may use |
89 | * VMX and be a hypervisor for its own guests. If nested=0, guests may not | 92 | * VMX and be a hypervisor for its own guests. If nested=0, guests may not |
@@ -640,6 +643,8 @@ static unsigned long *vmx_io_bitmap_a; | |||
640 | static unsigned long *vmx_io_bitmap_b; | 643 | static unsigned long *vmx_io_bitmap_b; |
641 | static unsigned long *vmx_msr_bitmap_legacy; | 644 | static unsigned long *vmx_msr_bitmap_legacy; |
642 | static unsigned long *vmx_msr_bitmap_longmode; | 645 | static unsigned long *vmx_msr_bitmap_longmode; |
646 | static unsigned long *vmx_msr_bitmap_legacy_x2apic; | ||
647 | static unsigned long *vmx_msr_bitmap_longmode_x2apic; | ||
643 | 648 | ||
644 | static bool cpu_has_load_ia32_efer; | 649 | static bool cpu_has_load_ia32_efer; |
645 | static bool cpu_has_load_perf_global_ctrl; | 650 | static bool cpu_has_load_perf_global_ctrl; |
@@ -764,6 +769,24 @@ static inline bool cpu_has_vmx_virtualize_apic_accesses(void) | |||
764 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | 769 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; |
765 | } | 770 | } |
766 | 771 | ||
772 | static inline bool cpu_has_vmx_virtualize_x2apic_mode(void) | ||
773 | { | ||
774 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
775 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | ||
776 | } | ||
777 | |||
778 | static inline bool cpu_has_vmx_apic_register_virt(void) | ||
779 | { | ||
780 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
781 | SECONDARY_EXEC_APIC_REGISTER_VIRT; | ||
782 | } | ||
783 | |||
784 | static inline bool cpu_has_vmx_virtual_intr_delivery(void) | ||
785 | { | ||
786 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
787 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; | ||
788 | } | ||
789 | |||
767 | static inline bool cpu_has_vmx_flexpriority(void) | 790 | static inline bool cpu_has_vmx_flexpriority(void) |
768 | { | 791 | { |
769 | return cpu_has_vmx_tpr_shadow() && | 792 | return cpu_has_vmx_tpr_shadow() && |
@@ -1821,6 +1844,25 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to) | |||
1821 | vmx->guest_msrs[from] = tmp; | 1844 | vmx->guest_msrs[from] = tmp; |
1822 | } | 1845 | } |
1823 | 1846 | ||
1847 | static void vmx_set_msr_bitmap(struct kvm_vcpu *vcpu) | ||
1848 | { | ||
1849 | unsigned long *msr_bitmap; | ||
1850 | |||
1851 | if (irqchip_in_kernel(vcpu->kvm) && apic_x2apic_mode(vcpu->arch.apic)) { | ||
1852 | if (is_long_mode(vcpu)) | ||
1853 | msr_bitmap = vmx_msr_bitmap_longmode_x2apic; | ||
1854 | else | ||
1855 | msr_bitmap = vmx_msr_bitmap_legacy_x2apic; | ||
1856 | } else { | ||
1857 | if (is_long_mode(vcpu)) | ||
1858 | msr_bitmap = vmx_msr_bitmap_longmode; | ||
1859 | else | ||
1860 | msr_bitmap = vmx_msr_bitmap_legacy; | ||
1861 | } | ||
1862 | |||
1863 | vmcs_write64(MSR_BITMAP, __pa(msr_bitmap)); | ||
1864 | } | ||
1865 | |||
1824 | /* | 1866 | /* |
1825 | * Set up the vmcs to automatically save and restore system | 1867 | * Set up the vmcs to automatically save and restore system |
1826 | * msrs. Don't touch the 64-bit msrs if the guest is in legacy | 1868 | * msrs. Don't touch the 64-bit msrs if the guest is in legacy |
@@ -1829,7 +1871,6 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to) | |||
1829 | static void setup_msrs(struct vcpu_vmx *vmx) | 1871 | static void setup_msrs(struct vcpu_vmx *vmx) |
1830 | { | 1872 | { |
1831 | int save_nmsrs, index; | 1873 | int save_nmsrs, index; |
1832 | unsigned long *msr_bitmap; | ||
1833 | 1874 | ||
1834 | save_nmsrs = 0; | 1875 | save_nmsrs = 0; |
1835 | #ifdef CONFIG_X86_64 | 1876 | #ifdef CONFIG_X86_64 |
@@ -1861,14 +1902,8 @@ static void setup_msrs(struct vcpu_vmx *vmx) | |||
1861 | 1902 | ||
1862 | vmx->save_nmsrs = save_nmsrs; | 1903 | vmx->save_nmsrs = save_nmsrs; |
1863 | 1904 | ||
1864 | if (cpu_has_vmx_msr_bitmap()) { | 1905 | if (cpu_has_vmx_msr_bitmap()) |
1865 | if (is_long_mode(&vmx->vcpu)) | 1906 | vmx_set_msr_bitmap(&vmx->vcpu); |
1866 | msr_bitmap = vmx_msr_bitmap_longmode; | ||
1867 | else | ||
1868 | msr_bitmap = vmx_msr_bitmap_legacy; | ||
1869 | |||
1870 | vmcs_write64(MSR_BITMAP, __pa(msr_bitmap)); | ||
1871 | } | ||
1872 | } | 1907 | } |
1873 | 1908 | ||
1874 | /* | 1909 | /* |
@@ -2534,13 +2569,16 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2534 | if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) { | 2569 | if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) { |
2535 | min2 = 0; | 2570 | min2 = 0; |
2536 | opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | | 2571 | opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
2572 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | | ||
2537 | SECONDARY_EXEC_WBINVD_EXITING | | 2573 | SECONDARY_EXEC_WBINVD_EXITING | |
2538 | SECONDARY_EXEC_ENABLE_VPID | | 2574 | SECONDARY_EXEC_ENABLE_VPID | |
2539 | SECONDARY_EXEC_ENABLE_EPT | | 2575 | SECONDARY_EXEC_ENABLE_EPT | |
2540 | SECONDARY_EXEC_UNRESTRICTED_GUEST | | 2576 | SECONDARY_EXEC_UNRESTRICTED_GUEST | |
2541 | SECONDARY_EXEC_PAUSE_LOOP_EXITING | | 2577 | SECONDARY_EXEC_PAUSE_LOOP_EXITING | |
2542 | SECONDARY_EXEC_RDTSCP | | 2578 | SECONDARY_EXEC_RDTSCP | |
2543 | SECONDARY_EXEC_ENABLE_INVPCID; | 2579 | SECONDARY_EXEC_ENABLE_INVPCID | |
2580 | SECONDARY_EXEC_APIC_REGISTER_VIRT | | ||
2581 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; | ||
2544 | if (adjust_vmx_controls(min2, opt2, | 2582 | if (adjust_vmx_controls(min2, opt2, |
2545 | MSR_IA32_VMX_PROCBASED_CTLS2, | 2583 | MSR_IA32_VMX_PROCBASED_CTLS2, |
2546 | &_cpu_based_2nd_exec_control) < 0) | 2584 | &_cpu_based_2nd_exec_control) < 0) |
@@ -2551,6 +2589,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2551 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) | 2589 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) |
2552 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; | 2590 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; |
2553 | #endif | 2591 | #endif |
2592 | |||
2593 | if (!(_cpu_based_exec_control & CPU_BASED_TPR_SHADOW)) | ||
2594 | _cpu_based_2nd_exec_control &= ~( | ||
2595 | SECONDARY_EXEC_APIC_REGISTER_VIRT | | ||
2596 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | | ||
2597 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); | ||
2598 | |||
2554 | if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) { | 2599 | if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) { |
2555 | /* CR3 accesses and invlpg don't need to cause VM Exits when EPT | 2600 | /* CR3 accesses and invlpg don't need to cause VM Exits when EPT |
2556 | enabled */ | 2601 | enabled */ |
@@ -2748,6 +2793,15 @@ static __init int hardware_setup(void) | |||
2748 | if (!cpu_has_vmx_ple()) | 2793 | if (!cpu_has_vmx_ple()) |
2749 | ple_gap = 0; | 2794 | ple_gap = 0; |
2750 | 2795 | ||
2796 | if (!cpu_has_vmx_apic_register_virt() || | ||
2797 | !cpu_has_vmx_virtual_intr_delivery()) | ||
2798 | enable_apicv_reg_vid = 0; | ||
2799 | |||
2800 | if (enable_apicv_reg_vid) | ||
2801 | kvm_x86_ops->update_cr8_intercept = NULL; | ||
2802 | else | ||
2803 | kvm_x86_ops->hwapic_irr_update = NULL; | ||
2804 | |||
2751 | if (nested) | 2805 | if (nested) |
2752 | nested_vmx_setup_ctls_msrs(); | 2806 | nested_vmx_setup_ctls_msrs(); |
2753 | 2807 | ||
@@ -3173,6 +3227,14 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
3173 | if (!is_paging(vcpu)) { | 3227 | if (!is_paging(vcpu)) { |
3174 | hw_cr4 &= ~X86_CR4_PAE; | 3228 | hw_cr4 &= ~X86_CR4_PAE; |
3175 | hw_cr4 |= X86_CR4_PSE; | 3229 | hw_cr4 |= X86_CR4_PSE; |
3230 | /* | ||
3231 | * SMEP is disabled if CPU is in non-paging mode in | ||
3232 | * hardware. However KVM always uses paging mode to | ||
3233 | * emulate guest non-paging mode with TDP. | ||
3234 | * To emulate this behavior, SMEP needs to be manually | ||
3235 | * disabled when guest switches to non-paging mode. | ||
3236 | */ | ||
3237 | hw_cr4 &= ~X86_CR4_SMEP; | ||
3176 | } else if (!(cr4 & X86_CR4_PAE)) { | 3238 | } else if (!(cr4 & X86_CR4_PAE)) { |
3177 | hw_cr4 &= ~X86_CR4_PAE; | 3239 | hw_cr4 &= ~X86_CR4_PAE; |
3178 | } | 3240 | } |
@@ -3707,7 +3769,10 @@ static void free_vpid(struct vcpu_vmx *vmx) | |||
3707 | spin_unlock(&vmx_vpid_lock); | 3769 | spin_unlock(&vmx_vpid_lock); |
3708 | } | 3770 | } |
3709 | 3771 | ||
3710 | static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, u32 msr) | 3772 | #define MSR_TYPE_R 1 |
3773 | #define MSR_TYPE_W 2 | ||
3774 | static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, | ||
3775 | u32 msr, int type) | ||
3711 | { | 3776 | { |
3712 | int f = sizeof(unsigned long); | 3777 | int f = sizeof(unsigned long); |
3713 | 3778 | ||
@@ -3720,20 +3785,93 @@ static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, u32 msr) | |||
3720 | * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff. | 3785 | * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff. |
3721 | */ | 3786 | */ |
3722 | if (msr <= 0x1fff) { | 3787 | if (msr <= 0x1fff) { |
3723 | __clear_bit(msr, msr_bitmap + 0x000 / f); /* read-low */ | 3788 | if (type & MSR_TYPE_R) |
3724 | __clear_bit(msr, msr_bitmap + 0x800 / f); /* write-low */ | 3789 | /* read-low */ |
3790 | __clear_bit(msr, msr_bitmap + 0x000 / f); | ||
3791 | |||
3792 | if (type & MSR_TYPE_W) | ||
3793 | /* write-low */ | ||
3794 | __clear_bit(msr, msr_bitmap + 0x800 / f); | ||
3795 | |||
3725 | } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { | 3796 | } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { |
3726 | msr &= 0x1fff; | 3797 | msr &= 0x1fff; |
3727 | __clear_bit(msr, msr_bitmap + 0x400 / f); /* read-high */ | 3798 | if (type & MSR_TYPE_R) |
3728 | __clear_bit(msr, msr_bitmap + 0xc00 / f); /* write-high */ | 3799 | /* read-high */ |
3800 | __clear_bit(msr, msr_bitmap + 0x400 / f); | ||
3801 | |||
3802 | if (type & MSR_TYPE_W) | ||
3803 | /* write-high */ | ||
3804 | __clear_bit(msr, msr_bitmap + 0xc00 / f); | ||
3805 | |||
3806 | } | ||
3807 | } | ||
3808 | |||
3809 | static void __vmx_enable_intercept_for_msr(unsigned long *msr_bitmap, | ||
3810 | u32 msr, int type) | ||
3811 | { | ||
3812 | int f = sizeof(unsigned long); | ||
3813 | |||
3814 | if (!cpu_has_vmx_msr_bitmap()) | ||
3815 | return; | ||
3816 | |||
3817 | /* | ||
3818 | * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals | ||
3819 | * have the write-low and read-high bitmap offsets the wrong way round. | ||
3820 | * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff. | ||
3821 | */ | ||
3822 | if (msr <= 0x1fff) { | ||
3823 | if (type & MSR_TYPE_R) | ||
3824 | /* read-low */ | ||
3825 | __set_bit(msr, msr_bitmap + 0x000 / f); | ||
3826 | |||
3827 | if (type & MSR_TYPE_W) | ||
3828 | /* write-low */ | ||
3829 | __set_bit(msr, msr_bitmap + 0x800 / f); | ||
3830 | |||
3831 | } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { | ||
3832 | msr &= 0x1fff; | ||
3833 | if (type & MSR_TYPE_R) | ||
3834 | /* read-high */ | ||
3835 | __set_bit(msr, msr_bitmap + 0x400 / f); | ||
3836 | |||
3837 | if (type & MSR_TYPE_W) | ||
3838 | /* write-high */ | ||
3839 | __set_bit(msr, msr_bitmap + 0xc00 / f); | ||
3840 | |||
3729 | } | 3841 | } |
3730 | } | 3842 | } |
3731 | 3843 | ||
3732 | static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only) | 3844 | static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only) |
3733 | { | 3845 | { |
3734 | if (!longmode_only) | 3846 | if (!longmode_only) |
3735 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, msr); | 3847 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, |
3736 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr); | 3848 | msr, MSR_TYPE_R | MSR_TYPE_W); |
3849 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, | ||
3850 | msr, MSR_TYPE_R | MSR_TYPE_W); | ||
3851 | } | ||
3852 | |||
3853 | static void vmx_enable_intercept_msr_read_x2apic(u32 msr) | ||
3854 | { | ||
3855 | __vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, | ||
3856 | msr, MSR_TYPE_R); | ||
3857 | __vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, | ||
3858 | msr, MSR_TYPE_R); | ||
3859 | } | ||
3860 | |||
3861 | static void vmx_disable_intercept_msr_read_x2apic(u32 msr) | ||
3862 | { | ||
3863 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, | ||
3864 | msr, MSR_TYPE_R); | ||
3865 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, | ||
3866 | msr, MSR_TYPE_R); | ||
3867 | } | ||
3868 | |||
3869 | static void vmx_disable_intercept_msr_write_x2apic(u32 msr) | ||
3870 | { | ||
3871 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, | ||
3872 | msr, MSR_TYPE_W); | ||
3873 | __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, | ||
3874 | msr, MSR_TYPE_W); | ||
3737 | } | 3875 | } |
3738 | 3876 | ||
3739 | /* | 3877 | /* |
@@ -3812,6 +3950,11 @@ static u32 vmx_exec_control(struct vcpu_vmx *vmx) | |||
3812 | return exec_control; | 3950 | return exec_control; |
3813 | } | 3951 | } |
3814 | 3952 | ||
3953 | static int vmx_vm_has_apicv(struct kvm *kvm) | ||
3954 | { | ||
3955 | return enable_apicv_reg_vid && irqchip_in_kernel(kvm); | ||
3956 | } | ||
3957 | |||
3815 | static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) | 3958 | static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) |
3816 | { | 3959 | { |
3817 | u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl; | 3960 | u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl; |
@@ -3829,6 +3972,10 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) | |||
3829 | exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; | 3972 | exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; |
3830 | if (!ple_gap) | 3973 | if (!ple_gap) |
3831 | exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; | 3974 | exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; |
3975 | if (!vmx_vm_has_apicv(vmx->vcpu.kvm)) | ||
3976 | exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT | | ||
3977 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); | ||
3978 | exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | ||
3832 | return exec_control; | 3979 | return exec_control; |
3833 | } | 3980 | } |
3834 | 3981 | ||
@@ -3873,6 +4020,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
3873 | vmx_secondary_exec_control(vmx)); | 4020 | vmx_secondary_exec_control(vmx)); |
3874 | } | 4021 | } |
3875 | 4022 | ||
4023 | if (enable_apicv_reg_vid) { | ||
4024 | vmcs_write64(EOI_EXIT_BITMAP0, 0); | ||
4025 | vmcs_write64(EOI_EXIT_BITMAP1, 0); | ||
4026 | vmcs_write64(EOI_EXIT_BITMAP2, 0); | ||
4027 | vmcs_write64(EOI_EXIT_BITMAP3, 0); | ||
4028 | |||
4029 | vmcs_write16(GUEST_INTR_STATUS, 0); | ||
4030 | } | ||
4031 | |||
3876 | if (ple_gap) { | 4032 | if (ple_gap) { |
3877 | vmcs_write32(PLE_GAP, ple_gap); | 4033 | vmcs_write32(PLE_GAP, ple_gap); |
3878 | vmcs_write32(PLE_WINDOW, ple_window); | 4034 | vmcs_write32(PLE_WINDOW, ple_window); |
@@ -4787,6 +4943,26 @@ static int handle_apic_access(struct kvm_vcpu *vcpu) | |||
4787 | return emulate_instruction(vcpu, 0) == EMULATE_DONE; | 4943 | return emulate_instruction(vcpu, 0) == EMULATE_DONE; |
4788 | } | 4944 | } |
4789 | 4945 | ||
4946 | static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu) | ||
4947 | { | ||
4948 | unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | ||
4949 | int vector = exit_qualification & 0xff; | ||
4950 | |||
4951 | /* EOI-induced VM exit is trap-like and thus no need to adjust IP */ | ||
4952 | kvm_apic_set_eoi_accelerated(vcpu, vector); | ||
4953 | return 1; | ||
4954 | } | ||
4955 | |||
4956 | static int handle_apic_write(struct kvm_vcpu *vcpu) | ||
4957 | { | ||
4958 | unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | ||
4959 | u32 offset = exit_qualification & 0xfff; | ||
4960 | |||
4961 | /* APIC-write VM exit is trap-like and thus no need to adjust IP */ | ||
4962 | kvm_apic_write_nodecode(vcpu, offset); | ||
4963 | return 1; | ||
4964 | } | ||
4965 | |||
4790 | static int handle_task_switch(struct kvm_vcpu *vcpu) | 4966 | static int handle_task_switch(struct kvm_vcpu *vcpu) |
4791 | { | 4967 | { |
4792 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 4968 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
@@ -5721,6 +5897,8 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { | |||
5721 | [EXIT_REASON_VMON] = handle_vmon, | 5897 | [EXIT_REASON_VMON] = handle_vmon, |
5722 | [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, | 5898 | [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, |
5723 | [EXIT_REASON_APIC_ACCESS] = handle_apic_access, | 5899 | [EXIT_REASON_APIC_ACCESS] = handle_apic_access, |
5900 | [EXIT_REASON_APIC_WRITE] = handle_apic_write, | ||
5901 | [EXIT_REASON_EOI_INDUCED] = handle_apic_eoi_induced, | ||
5724 | [EXIT_REASON_WBINVD] = handle_wbinvd, | 5902 | [EXIT_REASON_WBINVD] = handle_wbinvd, |
5725 | [EXIT_REASON_XSETBV] = handle_xsetbv, | 5903 | [EXIT_REASON_XSETBV] = handle_xsetbv, |
5726 | [EXIT_REASON_TASK_SWITCH] = handle_task_switch, | 5904 | [EXIT_REASON_TASK_SWITCH] = handle_task_switch, |
@@ -6070,6 +6248,85 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) | |||
6070 | vmcs_write32(TPR_THRESHOLD, irr); | 6248 | vmcs_write32(TPR_THRESHOLD, irr); |
6071 | } | 6249 | } |
6072 | 6250 | ||
6251 | static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set) | ||
6252 | { | ||
6253 | u32 sec_exec_control; | ||
6254 | |||
6255 | /* | ||
6256 | * There is not point to enable virtualize x2apic without enable | ||
6257 | * apicv | ||
6258 | */ | ||
6259 | if (!cpu_has_vmx_virtualize_x2apic_mode() || | ||
6260 | !vmx_vm_has_apicv(vcpu->kvm)) | ||
6261 | return; | ||
6262 | |||
6263 | if (!vm_need_tpr_shadow(vcpu->kvm)) | ||
6264 | return; | ||
6265 | |||
6266 | sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); | ||
6267 | |||
6268 | if (set) { | ||
6269 | sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | ||
6270 | sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | ||
6271 | } else { | ||
6272 | sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | ||
6273 | sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | ||
6274 | } | ||
6275 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control); | ||
6276 | |||
6277 | vmx_set_msr_bitmap(vcpu); | ||
6278 | } | ||
6279 | |||
6280 | static void vmx_hwapic_isr_update(struct kvm *kvm, int isr) | ||
6281 | { | ||
6282 | u16 status; | ||
6283 | u8 old; | ||
6284 | |||
6285 | if (!vmx_vm_has_apicv(kvm)) | ||
6286 | return; | ||
6287 | |||
6288 | if (isr == -1) | ||
6289 | isr = 0; | ||
6290 | |||
6291 | status = vmcs_read16(GUEST_INTR_STATUS); | ||
6292 | old = status >> 8; | ||
6293 | if (isr != old) { | ||
6294 | status &= 0xff; | ||
6295 | status |= isr << 8; | ||
6296 | vmcs_write16(GUEST_INTR_STATUS, status); | ||
6297 | } | ||
6298 | } | ||
6299 | |||
6300 | static void vmx_set_rvi(int vector) | ||
6301 | { | ||
6302 | u16 status; | ||
6303 | u8 old; | ||
6304 | |||
6305 | status = vmcs_read16(GUEST_INTR_STATUS); | ||
6306 | old = (u8)status & 0xff; | ||
6307 | if ((u8)vector != old) { | ||
6308 | status &= ~0xff; | ||
6309 | status |= (u8)vector; | ||
6310 | vmcs_write16(GUEST_INTR_STATUS, status); | ||
6311 | } | ||
6312 | } | ||
6313 | |||
6314 | static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr) | ||
6315 | { | ||
6316 | if (max_irr == -1) | ||
6317 | return; | ||
6318 | |||
6319 | vmx_set_rvi(max_irr); | ||
6320 | } | ||
6321 | |||
6322 | static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) | ||
6323 | { | ||
6324 | vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); | ||
6325 | vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); | ||
6326 | vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]); | ||
6327 | vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]); | ||
6328 | } | ||
6329 | |||
6073 | static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx) | 6330 | static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx) |
6074 | { | 6331 | { |
6075 | u32 exit_intr_info; | 6332 | u32 exit_intr_info; |
@@ -7333,6 +7590,11 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
7333 | .enable_nmi_window = enable_nmi_window, | 7590 | .enable_nmi_window = enable_nmi_window, |
7334 | .enable_irq_window = enable_irq_window, | 7591 | .enable_irq_window = enable_irq_window, |
7335 | .update_cr8_intercept = update_cr8_intercept, | 7592 | .update_cr8_intercept = update_cr8_intercept, |
7593 | .set_virtual_x2apic_mode = vmx_set_virtual_x2apic_mode, | ||
7594 | .vm_has_apicv = vmx_vm_has_apicv, | ||
7595 | .load_eoi_exitmap = vmx_load_eoi_exitmap, | ||
7596 | .hwapic_irr_update = vmx_hwapic_irr_update, | ||
7597 | .hwapic_isr_update = vmx_hwapic_isr_update, | ||
7336 | 7598 | ||
7337 | .set_tss_addr = vmx_set_tss_addr, | 7599 | .set_tss_addr = vmx_set_tss_addr, |
7338 | .get_tdp_level = get_ept_level, | 7600 | .get_tdp_level = get_ept_level, |
@@ -7365,7 +7627,7 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
7365 | 7627 | ||
7366 | static int __init vmx_init(void) | 7628 | static int __init vmx_init(void) |
7367 | { | 7629 | { |
7368 | int r, i; | 7630 | int r, i, msr; |
7369 | 7631 | ||
7370 | rdmsrl_safe(MSR_EFER, &host_efer); | 7632 | rdmsrl_safe(MSR_EFER, &host_efer); |
7371 | 7633 | ||
@@ -7386,11 +7648,19 @@ static int __init vmx_init(void) | |||
7386 | if (!vmx_msr_bitmap_legacy) | 7648 | if (!vmx_msr_bitmap_legacy) |
7387 | goto out1; | 7649 | goto out1; |
7388 | 7650 | ||
7651 | vmx_msr_bitmap_legacy_x2apic = | ||
7652 | (unsigned long *)__get_free_page(GFP_KERNEL); | ||
7653 | if (!vmx_msr_bitmap_legacy_x2apic) | ||
7654 | goto out2; | ||
7389 | 7655 | ||
7390 | vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL); | 7656 | vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL); |
7391 | if (!vmx_msr_bitmap_longmode) | 7657 | if (!vmx_msr_bitmap_longmode) |
7392 | goto out2; | 7658 | goto out3; |
7393 | 7659 | ||
7660 | vmx_msr_bitmap_longmode_x2apic = | ||
7661 | (unsigned long *)__get_free_page(GFP_KERNEL); | ||
7662 | if (!vmx_msr_bitmap_longmode_x2apic) | ||
7663 | goto out4; | ||
7394 | 7664 | ||
7395 | /* | 7665 | /* |
7396 | * Allow direct access to the PC debug port (it is often used for I/O | 7666 | * Allow direct access to the PC debug port (it is often used for I/O |
@@ -7422,6 +7692,28 @@ static int __init vmx_init(void) | |||
7422 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | 7692 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); |
7423 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | 7693 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); |
7424 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | 7694 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); |
7695 | memcpy(vmx_msr_bitmap_legacy_x2apic, | ||
7696 | vmx_msr_bitmap_legacy, PAGE_SIZE); | ||
7697 | memcpy(vmx_msr_bitmap_longmode_x2apic, | ||
7698 | vmx_msr_bitmap_longmode, PAGE_SIZE); | ||
7699 | |||
7700 | if (enable_apicv_reg_vid) { | ||
7701 | for (msr = 0x800; msr <= 0x8ff; msr++) | ||
7702 | vmx_disable_intercept_msr_read_x2apic(msr); | ||
7703 | |||
7704 | /* According SDM, in x2apic mode, the whole id reg is used. | ||
7705 | * But in KVM, it only use the highest eight bits. Need to | ||
7706 | * intercept it */ | ||
7707 | vmx_enable_intercept_msr_read_x2apic(0x802); | ||
7708 | /* TMCCT */ | ||
7709 | vmx_enable_intercept_msr_read_x2apic(0x839); | ||
7710 | /* TPR */ | ||
7711 | vmx_disable_intercept_msr_write_x2apic(0x808); | ||
7712 | /* EOI */ | ||
7713 | vmx_disable_intercept_msr_write_x2apic(0x80b); | ||
7714 | /* SELF-IPI */ | ||
7715 | vmx_disable_intercept_msr_write_x2apic(0x83f); | ||
7716 | } | ||
7425 | 7717 | ||
7426 | if (enable_ept) { | 7718 | if (enable_ept) { |
7427 | kvm_mmu_set_mask_ptes(0ull, | 7719 | kvm_mmu_set_mask_ptes(0ull, |
@@ -7435,8 +7727,10 @@ static int __init vmx_init(void) | |||
7435 | 7727 | ||
7436 | return 0; | 7728 | return 0; |
7437 | 7729 | ||
7438 | out3: | 7730 | out4: |
7439 | free_page((unsigned long)vmx_msr_bitmap_longmode); | 7731 | free_page((unsigned long)vmx_msr_bitmap_longmode); |
7732 | out3: | ||
7733 | free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||
7440 | out2: | 7734 | out2: |
7441 | free_page((unsigned long)vmx_msr_bitmap_legacy); | 7735 | free_page((unsigned long)vmx_msr_bitmap_legacy); |
7442 | out1: | 7736 | out1: |
@@ -7448,6 +7742,8 @@ out: | |||
7448 | 7742 | ||
7449 | static void __exit vmx_exit(void) | 7743 | static void __exit vmx_exit(void) |
7450 | { | 7744 | { |
7745 | free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||
7746 | free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); | ||
7451 | free_page((unsigned long)vmx_msr_bitmap_legacy); | 7747 | free_page((unsigned long)vmx_msr_bitmap_legacy); |
7452 | free_page((unsigned long)vmx_msr_bitmap_longmode); | 7748 | free_page((unsigned long)vmx_msr_bitmap_longmode); |
7453 | free_page((unsigned long)vmx_io_bitmap_b); | 7749 | free_page((unsigned long)vmx_io_bitmap_b); |