aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorWincy Van <fanwenyi0529@gmail.com>2015-02-03 10:57:51 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2015-02-03 11:07:38 -0500
commit608406e290ca31d8f217cb765ee50152b41a7c9c (patch)
tree65987792d2f32410b87e2e2a0082c0381b3fee34 /arch
parent82f0dd4b2749ece2e48509cbd768e9bcf44d2124 (diff)
KVM: nVMX: Enable nested virtual interrupt delivery
With virtual interrupt delivery, the hardware lets KVM use a more efficient mechanism for interrupt injection. This is an important feature for nested VMX, because it reduces vmexits substantially and they are much more expensive with nested virtualization. This is especially important for throughput-bound scenarios. Signed-off-by: Wincy Van <fanwenyi0529@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/vmx.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ea9b2e938ed1..955eff21f14a 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -219,6 +219,10 @@ struct __packed vmcs12 {
219 u64 virtual_apic_page_addr; 219 u64 virtual_apic_page_addr;
220 u64 apic_access_addr; 220 u64 apic_access_addr;
221 u64 ept_pointer; 221 u64 ept_pointer;
222 u64 eoi_exit_bitmap0;
223 u64 eoi_exit_bitmap1;
224 u64 eoi_exit_bitmap2;
225 u64 eoi_exit_bitmap3;
222 u64 xss_exit_bitmap; 226 u64 xss_exit_bitmap;
223 u64 guest_physical_address; 227 u64 guest_physical_address;
224 u64 vmcs_link_pointer; 228 u64 vmcs_link_pointer;
@@ -341,6 +345,7 @@ struct __packed vmcs12 {
341 u16 guest_gs_selector; 345 u16 guest_gs_selector;
342 u16 guest_ldtr_selector; 346 u16 guest_ldtr_selector;
343 u16 guest_tr_selector; 347 u16 guest_tr_selector;
348 u16 guest_intr_status;
344 u16 host_es_selector; 349 u16 host_es_selector;
345 u16 host_cs_selector; 350 u16 host_cs_selector;
346 u16 host_ss_selector; 351 u16 host_ss_selector;
@@ -626,6 +631,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
626 FIELD(GUEST_GS_SELECTOR, guest_gs_selector), 631 FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
627 FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector), 632 FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
628 FIELD(GUEST_TR_SELECTOR, guest_tr_selector), 633 FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
634 FIELD(GUEST_INTR_STATUS, guest_intr_status),
629 FIELD(HOST_ES_SELECTOR, host_es_selector), 635 FIELD(HOST_ES_SELECTOR, host_es_selector),
630 FIELD(HOST_CS_SELECTOR, host_cs_selector), 636 FIELD(HOST_CS_SELECTOR, host_cs_selector),
631 FIELD(HOST_SS_SELECTOR, host_ss_selector), 637 FIELD(HOST_SS_SELECTOR, host_ss_selector),
@@ -643,6 +649,10 @@ static const unsigned short vmcs_field_to_offset_table[] = {
643 FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr), 649 FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
644 FIELD64(APIC_ACCESS_ADDR, apic_access_addr), 650 FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
645 FIELD64(EPT_POINTER, ept_pointer), 651 FIELD64(EPT_POINTER, ept_pointer),
652 FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0),
653 FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1),
654 FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2),
655 FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3),
646 FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap), 656 FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap),
647 FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), 657 FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
648 FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), 658 FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
@@ -1142,6 +1152,11 @@ static inline bool nested_cpu_has_apic_reg_virt(struct vmcs12 *vmcs12)
1142 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_APIC_REGISTER_VIRT); 1152 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_APIC_REGISTER_VIRT);
1143} 1153}
1144 1154
1155static inline bool nested_cpu_has_vid(struct vmcs12 *vmcs12)
1156{
1157 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
1158}
1159
1145static inline bool is_exception(u32 intr_info) 1160static inline bool is_exception(u32 intr_info)
1146{ 1161{
1147 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 1162 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
@@ -2436,6 +2451,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
2436 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | 2451 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
2437 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | 2452 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
2438 SECONDARY_EXEC_APIC_REGISTER_VIRT | 2453 SECONDARY_EXEC_APIC_REGISTER_VIRT |
2454 SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
2439 SECONDARY_EXEC_WBINVD_EXITING | 2455 SECONDARY_EXEC_WBINVD_EXITING |
2440 SECONDARY_EXEC_XSAVES; 2456 SECONDARY_EXEC_XSAVES;
2441 2457
@@ -7441,7 +7457,8 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
7441 return nested_cpu_has2(vmcs12, 7457 return nested_cpu_has2(vmcs12,
7442 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); 7458 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
7443 case EXIT_REASON_APIC_WRITE: 7459 case EXIT_REASON_APIC_WRITE:
7444 /* apic_write should exit unconditionally. */ 7460 case EXIT_REASON_EOI_INDUCED:
7461 /* apic_write and eoi_induced should exit unconditionally. */
7445 return 1; 7462 return 1;
7446 case EXIT_REASON_EPT_VIOLATION: 7463 case EXIT_REASON_EPT_VIOLATION:
7447 /* 7464 /*
@@ -8633,6 +8650,19 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
8633 vmx_msr_bitmap_nested, 8650 vmx_msr_bitmap_nested,
8634 APIC_BASE_MSR + (APIC_TASKPRI >> 4), 8651 APIC_BASE_MSR + (APIC_TASKPRI >> 4),
8635 MSR_TYPE_R | MSR_TYPE_W); 8652 MSR_TYPE_R | MSR_TYPE_W);
8653 if (nested_cpu_has_vid(vmcs12)) {
8654 /* EOI and self-IPI are allowed */
8655 nested_vmx_disable_intercept_for_msr(
8656 msr_bitmap,
8657 vmx_msr_bitmap_nested,
8658 APIC_BASE_MSR + (APIC_EOI >> 4),
8659 MSR_TYPE_W);
8660 nested_vmx_disable_intercept_for_msr(
8661 msr_bitmap,
8662 vmx_msr_bitmap_nested,
8663 APIC_BASE_MSR + (APIC_SELF_IPI >> 4),
8664 MSR_TYPE_W);
8665 }
8636 } else { 8666 } else {
8637 /* 8667 /*
8638 * Enable reading intercept of all the x2apic 8668 * Enable reading intercept of all the x2apic
@@ -8650,6 +8680,14 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
8650 vmx_msr_bitmap_nested, 8680 vmx_msr_bitmap_nested,
8651 APIC_BASE_MSR + (APIC_TASKPRI >> 4), 8681 APIC_BASE_MSR + (APIC_TASKPRI >> 4),
8652 MSR_TYPE_W); 8682 MSR_TYPE_W);
8683 __vmx_enable_intercept_for_msr(
8684 vmx_msr_bitmap_nested,
8685 APIC_BASE_MSR + (APIC_EOI >> 4),
8686 MSR_TYPE_W);
8687 __vmx_enable_intercept_for_msr(
8688 vmx_msr_bitmap_nested,
8689 APIC_BASE_MSR + (APIC_SELF_IPI >> 4),
8690 MSR_TYPE_W);
8653 } 8691 }
8654 kunmap(page); 8692 kunmap(page);
8655 nested_release_page_clean(page); 8693 nested_release_page_clean(page);
@@ -8661,7 +8699,8 @@ static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
8661 struct vmcs12 *vmcs12) 8699 struct vmcs12 *vmcs12)
8662{ 8700{
8663 if (!nested_cpu_has_virt_x2apic_mode(vmcs12) && 8701 if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
8664 !nested_cpu_has_apic_reg_virt(vmcs12)) 8702 !nested_cpu_has_apic_reg_virt(vmcs12) &&
8703 !nested_cpu_has_vid(vmcs12))
8665 return 0; 8704 return 0;
8666 8705
8667 /* 8706 /*
@@ -8672,6 +8711,14 @@ static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
8672 nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) 8711 nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
8673 return -EINVAL; 8712 return -EINVAL;
8674 8713
8714 /*
8715 * If virtual interrupt delivery is enabled,
8716 * we must exit on external interrupts.
8717 */
8718 if (nested_cpu_has_vid(vmcs12) &&
8719 !nested_exit_on_intr(vcpu))
8720 return -EINVAL;
8721
8675 /* tpr shadow is needed by all apicv features. */ 8722 /* tpr shadow is needed by all apicv features. */
8676 if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) 8723 if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
8677 return -EINVAL; 8724 return -EINVAL;
@@ -8979,6 +9026,19 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
8979 kvm_vcpu_reload_apic_access_page(vcpu); 9026 kvm_vcpu_reload_apic_access_page(vcpu);
8980 } 9027 }
8981 9028
9029 if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) {
9030 vmcs_write64(EOI_EXIT_BITMAP0,
9031 vmcs12->eoi_exit_bitmap0);
9032 vmcs_write64(EOI_EXIT_BITMAP1,
9033 vmcs12->eoi_exit_bitmap1);
9034 vmcs_write64(EOI_EXIT_BITMAP2,
9035 vmcs12->eoi_exit_bitmap2);
9036 vmcs_write64(EOI_EXIT_BITMAP3,
9037 vmcs12->eoi_exit_bitmap3);
9038 vmcs_write16(GUEST_INTR_STATUS,
9039 vmcs12->guest_intr_status);
9040 }
9041
8982 vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); 9042 vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
8983 } 9043 }
8984 9044
@@ -9550,6 +9610,9 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
9550 vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3); 9610 vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
9551 } 9611 }
9552 9612
9613 if (nested_cpu_has_vid(vmcs12))
9614 vmcs12->guest_intr_status = vmcs_read16(GUEST_INTR_STATUS);
9615
9553 vmcs12->vm_entry_controls = 9616 vmcs12->vm_entry_controls =
9554 (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) | 9617 (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
9555 (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE); 9618 (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);