--- arch/x86/kvm/vmx/vmx.c | 33 +++++++++++++++++++++++++++++---- arch/x86/kvm/vmx/vmx.h | 1 + arch/x86/kvm/x86.c | 1 + 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index f18c2d8c7476..e83351c690d9 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4431,8 +4431,7 @@ static u32 vmx_vmexit_ctrl(void) * Not used by KVM and never set in vmcs01 or vmcs02, but emulated for * nested virtualization and thus allowed to be set in vmcs12. */ - vmexit_ctrl &= ~(VM_EXIT_SAVE_IA32_PAT | VM_EXIT_SAVE_IA32_EFER | - VM_EXIT_SAVE_VMX_PREEMPTION_TIMER); + vmexit_ctrl &= ~(VM_EXIT_SAVE_IA32_PAT | VM_EXIT_SAVE_IA32_EFER); if (vmx_pt_mode_is_system()) vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP | @@ -5997,6 +5996,8 @@ static fastpath_t handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu, bool force_immediate_exit) { struct vcpu_vmx *vmx = to_vmx(vcpu); + u32 delta_tsc; + u64 tscl; /* * In the *extremely* unlikely scenario that this is a spurious VM-Exit @@ -6020,6 +6021,16 @@ static fastpath_t handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu, if (is_guest_mode(vcpu)) return EXIT_FASTPATH_NONE; + tscl = rdtsc(); + if (vmx->hv_deadline_tsc > tscl) + delta_tsc = (u32)((vmx->hv_deadline_tsc - tscl) >> cpu_preemption_timer_multi); + else + delta_tsc = 0; + + pr_warn("VMX timer exit, EXIT_REASON = %x, VMCS = %x, delta = %x\n", + vmcs_read32(VM_EXIT_REASON), + vmcs_read32(VMX_PREEMPTION_TIMER_VALUE), delta_tsc); + kvm_lapic_expired_hv_timer(vcpu); return EXIT_FASTPATH_REENTER_GUEST; } @@ -7197,6 +7208,8 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu, bool force_immediate_exit u32 delta_tsc; if (force_immediate_exit) { + trace_kvm_hypercall(0, 0, 0, 0, 0); + vmx->preemption_timer = 0; vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, 0); vmx->loaded_vmcs->hv_timer_soft_disabled = false; } else if (vmx->hv_deadline_tsc != -1) { @@ -7208,9 +7221,14 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu, bool force_immediate_exit else delta_tsc = 0; + trace_kvm_hypercall(tscl, vmx->hv_deadline_tsc, delta_tsc, + ((vmx->hv_deadline_tsc - tscl) >> cpu_preemption_timer_multi), + cpu_preemption_timer_multi); + vmx->preemption_timer = delta_tsc; vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, delta_tsc); vmx->loaded_vmcs->hv_timer_soft_disabled = false; } else if (!vmx->loaded_vmcs->hv_timer_soft_disabled) { + trace_kvm_hypercall(-1, -1, -1, -1, -1); vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, -1); vmx->loaded_vmcs->hv_timer_soft_disabled = true; } @@ -7218,6 +7236,8 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu, bool force_immediate_exit void noinstr vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp) { + WARN_ON(!vmx->loaded_vmcs->hv_timer_soft_disabled && + vmcs_read32(VMX_PREEMPTION_TIMER_VALUE) != vmx->preemption_timer); if (unlikely(host_rsp != vmx->loaded_vmcs->host_state.rsp)) { vmx->loaded_vmcs->host_state.rsp = host_rsp; vmcs_writel(HOST_RSP, host_rsp); @@ -8128,7 +8148,7 @@ int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, delta_tsc && u64_shl_div_u64(delta_tsc, kvm_caps.tsc_scaling_ratio_frac_bits, vcpu->arch.l1_tsc_scaling_ratio, &delta_tsc)) - return -ERANGE; + goto out_of_range; /* * If the delta tsc can't fit in the 32 bit after the multi shift, @@ -8137,11 +8157,16 @@ int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, * on every vmentry is costly so we just use an hrtimer. */ if (delta_tsc >> (cpu_preemption_timer_multi + 32)) - return -ERANGE; + goto out_of_range; + trace_kvm_hypercall(tscl, vmx->hv_deadline_tsc, delta_tsc, -1, -1); vmx->hv_deadline_tsc = tscl + delta_tsc; *expired = !delta_tsc; return 0; + +out_of_range: + vmx->hv_deadline_tsc = -1; + return -ERANGE; } void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 42498fa63abb..ecafbb11519d 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -341,6 +341,7 @@ struct vcpu_vmx { /* apic deadline value in host tsc */ u64 hv_deadline_tsc; + u32 preemption_timer; unsigned long host_debugctlmsr; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 994743266480..00847259bcc4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -14024,6 +14024,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_nested_intercepts); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_write_tsc_offset); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ple_window_update); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pml_full); +EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_hypercall); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_unaccelerated_access); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_incomplete_ipi); base-commit: 128c71b7f489d8115d29a487367c648f8acc8374 -- 2.45.2.803.g4e1b14247a-goog --FoqhM4pZbXonoqbf--