diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2013-01-24 21:18:49 -0500 |
---|---|---|
committer | Gleb Natapov <gleb@redhat.com> | 2013-01-29 03:47:54 -0500 |
commit | 83d4c286931c9d28c5be21bac3c73a2332cab681 (patch) | |
tree | 524885d4cad7e7f1d98357711eff11b8224dc01e /arch/x86/kvm/vmx.c | |
parent | d47510e295c0f82699192a61d715351cf00f65de (diff) |
x86, apicv: add APICv register virtualization support
- APIC read doesn't cause VM-Exit
- APIC write becomes trap-like
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 02eeba86328d..5ad7c8531083 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 = 1; | ||
88 | module_param(enable_apicv_reg, 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 |
@@ -764,6 +767,12 @@ static inline bool cpu_has_vmx_virtualize_apic_accesses(void) | |||
764 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | 767 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; |
765 | } | 768 | } |
766 | 769 | ||
770 | static inline bool cpu_has_vmx_apic_register_virt(void) | ||
771 | { | ||
772 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
773 | SECONDARY_EXEC_APIC_REGISTER_VIRT; | ||
774 | } | ||
775 | |||
767 | static inline bool cpu_has_vmx_flexpriority(void) | 776 | static inline bool cpu_has_vmx_flexpriority(void) |
768 | { | 777 | { |
769 | return cpu_has_vmx_tpr_shadow() && | 778 | return cpu_has_vmx_tpr_shadow() && |
@@ -2540,7 +2549,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2540 | SECONDARY_EXEC_UNRESTRICTED_GUEST | | 2549 | SECONDARY_EXEC_UNRESTRICTED_GUEST | |
2541 | SECONDARY_EXEC_PAUSE_LOOP_EXITING | | 2550 | SECONDARY_EXEC_PAUSE_LOOP_EXITING | |
2542 | SECONDARY_EXEC_RDTSCP | | 2551 | SECONDARY_EXEC_RDTSCP | |
2543 | SECONDARY_EXEC_ENABLE_INVPCID; | 2552 | SECONDARY_EXEC_ENABLE_INVPCID | |
2553 | SECONDARY_EXEC_APIC_REGISTER_VIRT; | ||
2544 | if (adjust_vmx_controls(min2, opt2, | 2554 | if (adjust_vmx_controls(min2, opt2, |
2545 | MSR_IA32_VMX_PROCBASED_CTLS2, | 2555 | MSR_IA32_VMX_PROCBASED_CTLS2, |
2546 | &_cpu_based_2nd_exec_control) < 0) | 2556 | &_cpu_based_2nd_exec_control) < 0) |
@@ -2551,6 +2561,11 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2551 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) | 2561 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) |
2552 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; | 2562 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; |
2553 | #endif | 2563 | #endif |
2564 | |||
2565 | if (!(_cpu_based_exec_control & CPU_BASED_TPR_SHADOW)) | ||
2566 | _cpu_based_2nd_exec_control &= ~( | ||
2567 | SECONDARY_EXEC_APIC_REGISTER_VIRT); | ||
2568 | |||
2554 | if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) { | 2569 | if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) { |
2555 | /* CR3 accesses and invlpg don't need to cause VM Exits when EPT | 2570 | /* CR3 accesses and invlpg don't need to cause VM Exits when EPT |
2556 | enabled */ | 2571 | enabled */ |
@@ -2748,6 +2763,9 @@ static __init int hardware_setup(void) | |||
2748 | if (!cpu_has_vmx_ple()) | 2763 | if (!cpu_has_vmx_ple()) |
2749 | ple_gap = 0; | 2764 | ple_gap = 0; |
2750 | 2765 | ||
2766 | if (!cpu_has_vmx_apic_register_virt()) | ||
2767 | enable_apicv_reg = 0; | ||
2768 | |||
2751 | if (nested) | 2769 | if (nested) |
2752 | nested_vmx_setup_ctls_msrs(); | 2770 | nested_vmx_setup_ctls_msrs(); |
2753 | 2771 | ||
@@ -3829,6 +3847,8 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) | |||
3829 | exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; | 3847 | exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; |
3830 | if (!ple_gap) | 3848 | if (!ple_gap) |
3831 | exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; | 3849 | exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; |
3850 | if (!enable_apicv_reg || !irqchip_in_kernel(vmx->vcpu.kvm)) | ||
3851 | exec_control &= ~SECONDARY_EXEC_APIC_REGISTER_VIRT; | ||
3832 | return exec_control; | 3852 | return exec_control; |
3833 | } | 3853 | } |
3834 | 3854 | ||
@@ -4787,6 +4807,16 @@ static int handle_apic_access(struct kvm_vcpu *vcpu) | |||
4787 | return emulate_instruction(vcpu, 0) == EMULATE_DONE; | 4807 | return emulate_instruction(vcpu, 0) == EMULATE_DONE; |
4788 | } | 4808 | } |
4789 | 4809 | ||
4810 | static int handle_apic_write(struct kvm_vcpu *vcpu) | ||
4811 | { | ||
4812 | unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | ||
4813 | u32 offset = exit_qualification & 0xfff; | ||
4814 | |||
4815 | /* APIC-write VM exit is trap-like and thus no need to adjust IP */ | ||
4816 | kvm_apic_write_nodecode(vcpu, offset); | ||
4817 | return 1; | ||
4818 | } | ||
4819 | |||
4790 | static int handle_task_switch(struct kvm_vcpu *vcpu) | 4820 | static int handle_task_switch(struct kvm_vcpu *vcpu) |
4791 | { | 4821 | { |
4792 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 4822 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
@@ -5721,6 +5751,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { | |||
5721 | [EXIT_REASON_VMON] = handle_vmon, | 5751 | [EXIT_REASON_VMON] = handle_vmon, |
5722 | [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, | 5752 | [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, |
5723 | [EXIT_REASON_APIC_ACCESS] = handle_apic_access, | 5753 | [EXIT_REASON_APIC_ACCESS] = handle_apic_access, |
5754 | [EXIT_REASON_APIC_WRITE] = handle_apic_write, | ||
5724 | [EXIT_REASON_WBINVD] = handle_wbinvd, | 5755 | [EXIT_REASON_WBINVD] = handle_wbinvd, |
5725 | [EXIT_REASON_XSETBV] = handle_xsetbv, | 5756 | [EXIT_REASON_XSETBV] = handle_xsetbv, |
5726 | [EXIT_REASON_TASK_SWITCH] = handle_task_switch, | 5757 | [EXIT_REASON_TASK_SWITCH] = handle_task_switch, |