Use preemption timer to handle host timer

Signed-off-by: Zhimin Feng <fengzhi...@bytedance.com>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx/vmx.c          | 54 +++++++++++++++++++++++++++++++++++++++++
 arch/x86/kvm/x86.c              |  1 +
 3 files changed, 56 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index eb6a611963b7..82a51f0d01a2 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -826,6 +826,7 @@ struct kvm_vcpu_arch {
        } pv_cpuid;
 
        bool timer_passth_enable;
+       u64 tscd;
 };
 
 struct kvm_lpage_info {
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 38b8d80fa157..0bf9941df842 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5629,6 +5629,13 @@ static fastpath_t 
handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       if (vcpu->arch.timer_passth_enable) {
+               local_irq_disable();
+               apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), 
LOCAL_TIMER_VECTOR);
+               local_irq_enable();
+
+               return EXIT_FASTPATH_NONE;
+       }
        if (!vmx->req_immediate_exit &&
            !unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled)) {
                kvm_lapic_expired_hv_timer(vcpu);
@@ -6640,6 +6647,51 @@ static fastpath_t vmx_exit_handlers_fastpath(struct 
kvm_vcpu *vcpu)
 
 bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched);
 
+static void vmx_host_lapic_timer_offload(struct kvm_vcpu *vcpu)
+{
+       struct timer_passth_info *local_timer_info;
+       u64 tscl;
+       u64 guest_tscl;
+       u64 delta_tsc;
+       struct hrtimer *timer;
+
+       if (!vcpu->arch.timer_passth_enable)
+               return;
+
+       local_timer_info = &per_cpu(passth_info, smp_processor_id());
+
+       tscl = rdtsc();
+       guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
+
+       timer = &vcpu->arch.apic->lapic_timer.timer;
+       if (hrtimer_active(timer))
+               hrtimer_cancel(timer);
+
+       if (local_timer_info->host_tscd > tscl) {
+               delta_tsc = (u32)((local_timer_info->host_tscd - tscl) >>
+                               cpu_preemption_timer_multi);
+               vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, delta_tsc);
+               vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
+                               PIN_BASED_VMX_PREEMPTION_TIMER);
+       } else {
+               vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
+                               PIN_BASED_VMX_PREEMPTION_TIMER);
+       }
+
+       wrmsrl(MSR_IA32_TSCDEADLINE, 0);
+       if (vcpu->arch.tscd > guest_tscl) {
+               wrmsrl(MSR_IA32_TSCDEADLINE, vcpu->arch.tscd);
+       } else {
+               if (vcpu->arch.tscd > 0) {
+                       if 
(!atomic_read(&vcpu->arch.apic->lapic_timer.pending)) {
+                               
atomic_inc(&vcpu->arch.apic->lapic_timer.pending);
+                               kvm_inject_pending_timer_irqs(vcpu);
+                               kvm_x86_ops.sync_pir_to_irr(vcpu);
+                       }
+               }
+       }
+}
+
 static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
                                        struct vcpu_vmx *vmx)
 {
@@ -6761,6 +6813,8 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
 
        kvm_wait_lapic_expire(vcpu);
 
+       vmx_host_lapic_timer_offload(vcpu);
+
        /*
         * If this vCPU has touched SPEC_CTRL, restore the guest's value if
         * it's non-zero. Since vmentry is serialising on affected CPUs, there
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5d353a9c9881..e51fd52a4862 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9912,6 +9912,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
        vcpu->arch.pending_external_vector = -1;
        vcpu->arch.preempted_in_kernel = false;
        vcpu->arch.timer_passth_enable = false;
+       vcpu->arch.tscd = 0;
 
        kvm_hv_vcpu_init(vcpu);
 
-- 
2.11.0

Reply via email to