aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorArthur Chunqi Li <yzt356@gmail.com>2013-09-16 04:11:44 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-10-10 12:22:54 -0400
commit7854cbca815562a49d50bbc6f31599312853d1f4 (patch)
tree514f0a7a9e0bb345a371a4288d0ab2318cb4a7a3 /arch/x86
parent8a3c1a33476f6bfebd07954e2277dbc88003bd37 (diff)
KVM: nVMX: Fully support nested VMX preemption timer
This patch contains the following two changes: 1. Fix the bug in nested preemption timer support. If vmexit L2->L0 with some reasons not emulated by L1, preemption timer value should be save in such exits. 2. Add support of "Save VMX-preemption timer value" VM-Exit controls to nVMX. With this patch, nested VMX preemption timer features are fully supported. Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com> Reviewed-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/uapi/asm/msr-index.h1
-rw-r--r--arch/x86/kvm/vmx.c42
2 files changed, 41 insertions, 2 deletions
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index bb0465090ae5..b93e09a0fa21 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -536,6 +536,7 @@
536 536
537/* MSR_IA32_VMX_MISC bits */ 537/* MSR_IA32_VMX_MISC bits */
538#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29) 538#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
539#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE 0x1F
539/* AMD-V MSRs */ 540/* AMD-V MSRs */
540 541
541#define MSR_VM_CR 0xc0010114 542#define MSR_VM_CR 0xc0010114
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2db91645a6cc..0156560c68a8 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2200,7 +2200,13 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2200#ifdef CONFIG_X86_64 2200#ifdef CONFIG_X86_64
2201 VM_EXIT_HOST_ADDR_SPACE_SIZE | 2201 VM_EXIT_HOST_ADDR_SPACE_SIZE |
2202#endif 2202#endif
2203 VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT; 2203 VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT |
2204 VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
2205 if (!(nested_vmx_pinbased_ctls_high & PIN_BASED_VMX_PREEMPTION_TIMER) ||
2206 !(nested_vmx_exit_ctls_high & VM_EXIT_SAVE_VMX_PREEMPTION_TIMER)) {
2207 nested_vmx_exit_ctls_high &= ~VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
2208 nested_vmx_pinbased_ctls_high &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
2209 }
2204 nested_vmx_exit_ctls_high |= (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | 2210 nested_vmx_exit_ctls_high |= (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
2205 VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER); 2211 VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER);
2206 2212
@@ -6724,6 +6730,27 @@ static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
6724 *info2 = vmcs_read32(VM_EXIT_INTR_INFO); 6730 *info2 = vmcs_read32(VM_EXIT_INTR_INFO);
6725} 6731}
6726 6732
6733static void nested_adjust_preemption_timer(struct kvm_vcpu *vcpu)
6734{
6735 u64 delta_tsc_l1;
6736 u32 preempt_val_l1, preempt_val_l2, preempt_scale;
6737
6738 if (!(get_vmcs12(vcpu)->pin_based_vm_exec_control &
6739 PIN_BASED_VMX_PREEMPTION_TIMER))
6740 return;
6741 preempt_scale = native_read_msr(MSR_IA32_VMX_MISC) &
6742 MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE;
6743 preempt_val_l2 = vmcs_read32(VMX_PREEMPTION_TIMER_VALUE);
6744 delta_tsc_l1 = vmx_read_l1_tsc(vcpu, native_read_tsc())
6745 - vcpu->arch.last_guest_tsc;
6746 preempt_val_l1 = delta_tsc_l1 >> preempt_scale;
6747 if (preempt_val_l2 <= preempt_val_l1)
6748 preempt_val_l2 = 0;
6749 else
6750 preempt_val_l2 -= preempt_val_l1;
6751 vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, preempt_val_l2);
6752}
6753
6727/* 6754/*
6728 * The guest has exited. See if we can fix it or if we need userspace 6755 * The guest has exited. See if we can fix it or if we need userspace
6729 * assistance. 6756 * assistance.
@@ -7134,6 +7161,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
7134 atomic_switch_perf_msrs(vmx); 7161 atomic_switch_perf_msrs(vmx);
7135 debugctlmsr = get_debugctlmsr(); 7162 debugctlmsr = get_debugctlmsr();
7136 7163
7164 if (is_guest_mode(vcpu) && !vmx->nested.nested_run_pending)
7165 nested_adjust_preemption_timer(vcpu);
7137 vmx->__launched = vmx->loaded_vmcs->launched; 7166 vmx->__launched = vmx->loaded_vmcs->launched;
7138 asm( 7167 asm(
7139 /* Store host registers */ 7168 /* Store host registers */
@@ -7543,6 +7572,7 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7543{ 7572{
7544 struct vcpu_vmx *vmx = to_vmx(vcpu); 7573 struct vcpu_vmx *vmx = to_vmx(vcpu);
7545 u32 exec_control; 7574 u32 exec_control;
7575 u32 exit_control;
7546 7576
7547 vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector); 7577 vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
7548 vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector); 7578 vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
@@ -7716,7 +7746,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7716 * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER 7746 * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER
7717 * bits are further modified by vmx_set_efer() below. 7747 * bits are further modified by vmx_set_efer() below.
7718 */ 7748 */
7719 vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl); 7749 exit_control = vmcs_config.vmexit_ctrl;
7750 if (vmcs12->pin_based_vm_exec_control & PIN_BASED_VMX_PREEMPTION_TIMER)
7751 exit_control |= VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
7752 vmcs_write32(VM_EXIT_CONTROLS, exit_control);
7720 7753
7721 /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are 7754 /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are
7722 * emulated by vmx_set_efer(), below. 7755 * emulated by vmx_set_efer(), below.
@@ -8124,6 +8157,11 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
8124 vmcs12->guest_pending_dbg_exceptions = 8157 vmcs12->guest_pending_dbg_exceptions =
8125 vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS); 8158 vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
8126 8159
8160 if ((vmcs12->pin_based_vm_exec_control & PIN_BASED_VMX_PREEMPTION_TIMER) &&
8161 (vmcs12->vm_exit_controls & VM_EXIT_SAVE_VMX_PREEMPTION_TIMER))
8162 vmcs12->vmx_preemption_timer_value =
8163 vmcs_read32(VMX_PREEMPTION_TIMER_VALUE);
8164
8127 /* 8165 /*
8128 * In some cases (usually, nested EPT), L2 is allowed to change its 8166 * In some cases (usually, nested EPT), L2 is allowed to change its
8129 * own CR3 without exiting. If it has changed it, we must keep it. 8167 * own CR3 without exiting. If it has changed it, we must keep it.