diff options
-rw-r--r-- | arch/x86/include/asm/vmx.h | 6 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 25 |
2 files changed, 29 insertions, 2 deletions
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 42d959056f97..9642c2216f31 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h | |||
@@ -297,6 +297,12 @@ enum vmcs_field { | |||
297 | #define GUEST_INTR_STATE_SMI 0x00000004 | 297 | #define GUEST_INTR_STATE_SMI 0x00000004 |
298 | #define GUEST_INTR_STATE_NMI 0x00000008 | 298 | #define GUEST_INTR_STATE_NMI 0x00000008 |
299 | 299 | ||
300 | /* GUEST_ACTIVITY_STATE flags */ | ||
301 | #define GUEST_ACTIVITY_ACTIVE 0 | ||
302 | #define GUEST_ACTIVITY_HLT 1 | ||
303 | #define GUEST_ACTIVITY_SHUTDOWN 2 | ||
304 | #define GUEST_ACTIVITY_WAIT_SIPI 3 | ||
305 | |||
300 | /* | 306 | /* |
301 | * Exit Qualifications for MOV for Control Register Access | 307 | * Exit Qualifications for MOV for Control Register Access |
302 | */ | 308 | */ |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f3693ca93982..c1952603d580 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -69,6 +69,9 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO); | |||
69 | static int __read_mostly vmm_exclusive = 1; | 69 | static int __read_mostly vmm_exclusive = 1; |
70 | module_param(vmm_exclusive, bool, S_IRUGO); | 70 | module_param(vmm_exclusive, bool, S_IRUGO); |
71 | 71 | ||
72 | static int __read_mostly yield_on_hlt = 1; | ||
73 | module_param(yield_on_hlt, bool, S_IRUGO); | ||
74 | |||
72 | #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST \ | 75 | #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST \ |
73 | (X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD) | 76 | (X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD) |
74 | #define KVM_GUEST_CR0_MASK \ | 77 | #define KVM_GUEST_CR0_MASK \ |
@@ -1009,6 +1012,17 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) | |||
1009 | vmx_set_interrupt_shadow(vcpu, 0); | 1012 | vmx_set_interrupt_shadow(vcpu, 0); |
1010 | } | 1013 | } |
1011 | 1014 | ||
1015 | static void vmx_clear_hlt(struct kvm_vcpu *vcpu) | ||
1016 | { | ||
1017 | /* Ensure that we clear the HLT state in the VMCS. We don't need to | ||
1018 | * explicitly skip the instruction because if the HLT state is set, then | ||
1019 | * the instruction is already executing and RIP has already been | ||
1020 | * advanced. */ | ||
1021 | if (!yield_on_hlt && | ||
1022 | vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT) | ||
1023 | vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE); | ||
1024 | } | ||
1025 | |||
1012 | static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, | 1026 | static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, |
1013 | bool has_error_code, u32 error_code, | 1027 | bool has_error_code, u32 error_code, |
1014 | bool reinject) | 1028 | bool reinject) |
@@ -1035,6 +1049,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, | |||
1035 | intr_info |= INTR_TYPE_HARD_EXCEPTION; | 1049 | intr_info |= INTR_TYPE_HARD_EXCEPTION; |
1036 | 1050 | ||
1037 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); | 1051 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); |
1052 | vmx_clear_hlt(vcpu); | ||
1038 | } | 1053 | } |
1039 | 1054 | ||
1040 | static bool vmx_rdtscp_supported(void) | 1055 | static bool vmx_rdtscp_supported(void) |
@@ -1419,7 +1434,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1419 | &_pin_based_exec_control) < 0) | 1434 | &_pin_based_exec_control) < 0) |
1420 | return -EIO; | 1435 | return -EIO; |
1421 | 1436 | ||
1422 | min = CPU_BASED_HLT_EXITING | | 1437 | min = |
1423 | #ifdef CONFIG_X86_64 | 1438 | #ifdef CONFIG_X86_64 |
1424 | CPU_BASED_CR8_LOAD_EXITING | | 1439 | CPU_BASED_CR8_LOAD_EXITING | |
1425 | CPU_BASED_CR8_STORE_EXITING | | 1440 | CPU_BASED_CR8_STORE_EXITING | |
@@ -1432,6 +1447,10 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1432 | CPU_BASED_MWAIT_EXITING | | 1447 | CPU_BASED_MWAIT_EXITING | |
1433 | CPU_BASED_MONITOR_EXITING | | 1448 | CPU_BASED_MONITOR_EXITING | |
1434 | CPU_BASED_INVLPG_EXITING; | 1449 | CPU_BASED_INVLPG_EXITING; |
1450 | |||
1451 | if (yield_on_hlt) | ||
1452 | min |= CPU_BASED_HLT_EXITING; | ||
1453 | |||
1435 | opt = CPU_BASED_TPR_SHADOW | | 1454 | opt = CPU_BASED_TPR_SHADOW | |
1436 | CPU_BASED_USE_MSR_BITMAPS | | 1455 | CPU_BASED_USE_MSR_BITMAPS | |
1437 | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; | 1456 | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; |
@@ -2728,7 +2747,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) | |||
2728 | vmcs_writel(GUEST_IDTR_BASE, 0); | 2747 | vmcs_writel(GUEST_IDTR_BASE, 0); |
2729 | vmcs_write32(GUEST_IDTR_LIMIT, 0xffff); | 2748 | vmcs_write32(GUEST_IDTR_LIMIT, 0xffff); |
2730 | 2749 | ||
2731 | vmcs_write32(GUEST_ACTIVITY_STATE, 0); | 2750 | vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE); |
2732 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); | 2751 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); |
2733 | vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); | 2752 | vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); |
2734 | 2753 | ||
@@ -2821,6 +2840,7 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu) | |||
2821 | } else | 2840 | } else |
2822 | intr |= INTR_TYPE_EXT_INTR; | 2841 | intr |= INTR_TYPE_EXT_INTR; |
2823 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr); | 2842 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr); |
2843 | vmx_clear_hlt(vcpu); | ||
2824 | } | 2844 | } |
2825 | 2845 | ||
2826 | static void vmx_inject_nmi(struct kvm_vcpu *vcpu) | 2846 | static void vmx_inject_nmi(struct kvm_vcpu *vcpu) |
@@ -2848,6 +2868,7 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) | |||
2848 | } | 2868 | } |
2849 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | 2869 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, |
2850 | INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); | 2870 | INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); |
2871 | vmx_clear_hlt(vcpu); | ||
2851 | } | 2872 | } |
2852 | 2873 | ||
2853 | static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) | 2874 | static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) |