aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWincy Van <fanwenyi0529@gmail.com>2015-02-03 10:56:03 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2015-02-03 11:06:17 -0500
commitf2b93280edee5c7e95eecba48707a4e4a19b17c8 (patch)
tree6b4ac484f00e60309f5878a17833dbd881ebb90f
parent3af18d9c5fe95a6b377dca7b9ff9c6d3ab7f0969 (diff)
KVM: nVMX: Enable nested virtualize x2apic mode
When L2 is using x2apic, we can use virtualize x2apic mode to gain higher performance, especially in apicv case. This patch also introduces nested_vmx_check_apicv_controls for the nested apicv patches. Signed-off-by: Wincy Van <fanwenyi0529@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6d1d26f017c1..25984e7e8a4d 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1115,6 +1115,11 @@ static inline bool nested_cpu_has_xsaves(struct vmcs12 *vmcs12)
1115 vmx_xsaves_supported(); 1115 vmx_xsaves_supported();
1116} 1116}
1117 1117
1118static inline bool nested_cpu_has_virt_x2apic_mode(struct vmcs12 *vmcs12)
1119{
1120 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
1121}
1122
1118static inline bool is_exception(u32 intr_info) 1123static inline bool is_exception(u32 intr_info)
1119{ 1124{
1120 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 1125 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
@@ -2402,6 +2407,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2402 nested_vmx_secondary_ctls_low = 0; 2407 nested_vmx_secondary_ctls_low = 0;
2403 nested_vmx_secondary_ctls_high &= 2408 nested_vmx_secondary_ctls_high &=
2404 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | 2409 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
2410 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
2405 SECONDARY_EXEC_WBINVD_EXITING | 2411 SECONDARY_EXEC_WBINVD_EXITING |
2406 SECONDARY_EXEC_XSAVES; 2412 SECONDARY_EXEC_XSAVES;
2407 2413
@@ -4163,6 +4169,52 @@ static void __vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
4163 } 4169 }
4164} 4170}
4165 4171
4172/*
4173 * If a msr is allowed by L0, we should check whether it is allowed by L1.
4174 * The corresponding bit will be cleared unless both of L0 and L1 allow it.
4175 */
4176static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1,
4177 unsigned long *msr_bitmap_nested,
4178 u32 msr, int type)
4179{
4180 int f = sizeof(unsigned long);
4181
4182 if (!cpu_has_vmx_msr_bitmap()) {
4183 WARN_ON(1);
4184 return;
4185 }
4186
4187 /*
4188 * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
4189 * have the write-low and read-high bitmap offsets the wrong way round.
4190 * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
4191 */
4192 if (msr <= 0x1fff) {
4193 if (type & MSR_TYPE_R &&
4194 !test_bit(msr, msr_bitmap_l1 + 0x000 / f))
4195 /* read-low */
4196 __clear_bit(msr, msr_bitmap_nested + 0x000 / f);
4197
4198 if (type & MSR_TYPE_W &&
4199 !test_bit(msr, msr_bitmap_l1 + 0x800 / f))
4200 /* write-low */
4201 __clear_bit(msr, msr_bitmap_nested + 0x800 / f);
4202
4203 } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
4204 msr &= 0x1fff;
4205 if (type & MSR_TYPE_R &&
4206 !test_bit(msr, msr_bitmap_l1 + 0x400 / f))
4207 /* read-high */
4208 __clear_bit(msr, msr_bitmap_nested + 0x400 / f);
4209
4210 if (type & MSR_TYPE_W &&
4211 !test_bit(msr, msr_bitmap_l1 + 0xc00 / f))
4212 /* write-high */
4213 __clear_bit(msr, msr_bitmap_nested + 0xc00 / f);
4214
4215 }
4216}
4217
4166static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only) 4218static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
4167{ 4219{
4168 if (!longmode_only) 4220 if (!longmode_only)
@@ -8500,7 +8552,59 @@ static int nested_vmx_check_msr_bitmap_controls(struct kvm_vcpu *vcpu,
8500static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu, 8552static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
8501 struct vmcs12 *vmcs12) 8553 struct vmcs12 *vmcs12)
8502{ 8554{
8503 return false; 8555 struct page *page;
8556 unsigned long *msr_bitmap;
8557
8558 if (!nested_cpu_has_virt_x2apic_mode(vmcs12))
8559 return false;
8560
8561 page = nested_get_page(vcpu, vmcs12->msr_bitmap);
8562 if (!page) {
8563 WARN_ON(1);
8564 return false;
8565 }
8566 msr_bitmap = (unsigned long *)kmap(page);
8567 if (!msr_bitmap) {
8568 nested_release_page_clean(page);
8569 WARN_ON(1);
8570 return false;
8571 }
8572
8573 if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
8574 /* TPR is allowed */
8575 nested_vmx_disable_intercept_for_msr(msr_bitmap,
8576 vmx_msr_bitmap_nested,
8577 APIC_BASE_MSR + (APIC_TASKPRI >> 4),
8578 MSR_TYPE_R | MSR_TYPE_W);
8579 } else
8580 __vmx_enable_intercept_for_msr(
8581 vmx_msr_bitmap_nested,
8582 APIC_BASE_MSR + (APIC_TASKPRI >> 4),
8583 MSR_TYPE_R | MSR_TYPE_W);
8584 kunmap(page);
8585 nested_release_page_clean(page);
8586
8587 return true;
8588}
8589
8590static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
8591 struct vmcs12 *vmcs12)
8592{
8593 if (!nested_cpu_has_virt_x2apic_mode(vmcs12))
8594 return 0;
8595
8596 /*
8597 * If virtualize x2apic mode is enabled,
8598 * virtualize apic access must be disabled.
8599 */
8600 if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
8601 return -EINVAL;
8602
8603 /* tpr shadow is needed by all apicv features. */
8604 if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
8605 return -EINVAL;
8606
8607 return 0;
8504} 8608}
8505 8609
8506static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu, 8610static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
@@ -8796,7 +8900,8 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
8796 else 8900 else
8797 vmcs_write64(APIC_ACCESS_ADDR, 8901 vmcs_write64(APIC_ACCESS_ADDR,
8798 page_to_phys(vmx->nested.apic_access_page)); 8902 page_to_phys(vmx->nested.apic_access_page));
8799 } else if (vm_need_virtualize_apic_accesses(vmx->vcpu.kvm)) { 8903 } else if (!(nested_cpu_has_virt_x2apic_mode(vmcs12)) &&
8904 (vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))) {
8800 exec_control |= 8905 exec_control |=
8801 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; 8906 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
8802 kvm_vcpu_reload_apic_access_page(vcpu); 8907 kvm_vcpu_reload_apic_access_page(vcpu);
@@ -9007,6 +9112,11 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
9007 return 1; 9112 return 1;
9008 } 9113 }
9009 9114
9115 if (nested_vmx_check_apicv_controls(vcpu, vmcs12)) {
9116 nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
9117 return 1;
9118 }
9119
9010 if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) { 9120 if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) {
9011 nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); 9121 nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
9012 return 1; 9122 return 1;