aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/vmx.h6
-rw-r--r--arch/x86/kvm/vmx.c25
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);
69static int __read_mostly vmm_exclusive = 1; 69static int __read_mostly vmm_exclusive = 1;
70module_param(vmm_exclusive, bool, S_IRUGO); 70module_param(vmm_exclusive, bool, S_IRUGO);
71 71
72static int __read_mostly yield_on_hlt = 1;
73module_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
1015static 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
1012static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, 1026static 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
1040static bool vmx_rdtscp_supported(void) 1055static 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
2826static void vmx_inject_nmi(struct kvm_vcpu *vcpu) 2846static 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
2853static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) 2874static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)