aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2010-12-06 11:53:38 -0500
committerAvi Kivity <avi@redhat.com>2011-01-12 04:30:46 -0500
commit443381a828910efa3d71ba4491d180f2d0bb4212 (patch)
treec8deb311dc30d9a88aba1b17581dbb46ba2c3023 /arch
parent38e5e92fe8c02a8766459d505423b855caf9af1f (diff)
KVM: VMX: add module parameter to avoid trapping HLT instructions (v5)
In certain use-cases, we want to allocate guests fixed time slices where idle guest cycles leave the machine idling. There are many approaches to achieve this but the most direct is to simply avoid trapping the HLT instruction which lets the guest directly execute the instruction putting the processor to sleep. Introduce this as a module-level option for kvm-vmx.ko since if you do this for one guest, you probably want to do it for all. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-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)