diff options
| -rw-r--r-- | arch/x86/kvm/vmx.c | 67 |
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 | ||
| 1155 | static inline bool nested_cpu_has_vid(struct vmcs12 *vmcs12) | ||
| 1156 | { | ||
| 1157 | return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); | ||
| 1158 | } | ||
| 1159 | |||
| 1145 | static inline bool is_exception(u32 intr_info) | 1160 | static 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); |
