Message ID | 1587468026-15753-3-git-send-email-wanpengli@tencent.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: VMX: Tscdeadline timer emulation fastpath | expand |
On 21/04/20 13:20, Wanpeng Li wrote: > + > + if (!vmx->req_immediate_exit && > + !unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled)) { > + if (!vmx_interrupt_allowed(vcpu) || > + !apic_lvtt_tscdeadline(apic) || > + vmx->rmode.vm86_active || > + is_smm(vcpu) || > + !kvm_apic_hw_enabled(apic)) > + return EXIT_FASTPATH_NONE; > + > + if (!apic->lapic_timer.hv_timer_in_use) > + return EXIT_FASTPATH_CONT_RUN; > + > + WARN_ON(swait_active(&vcpu->wq)); > + vmx_cancel_hv_timer(vcpu); > + apic->lapic_timer.hv_timer_in_use = false; > + > + if (atomic_read(&apic->lapic_timer.pending)) > + return EXIT_FASTPATH_CONT_RUN; > + > + ktimer->expired_tscdeadline = ktimer->tscdeadline; > + vmx_fast_deliver_interrupt(vcpu); > + ktimer->tscdeadline = 0; > + return EXIT_FASTPATH_CONT_RUN; > + } > + Can you explain all the checks you have here, and why you need something more complex than apic_timer_expired (possibly by adding some optimizations to kvm_apic_local_deliver)? This code is impossible to maintain. Paolo
On Tue, 21 Apr 2020 at 19:40, Paolo Bonzini <pbonzini@redhat.com> wrote: > > On 21/04/20 13:20, Wanpeng Li wrote: > > + > > + if (!vmx->req_immediate_exit && > > + !unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled)) { > > + if (!vmx_interrupt_allowed(vcpu) || For non-APICv case, we need to request interrupt-window. > > + !apic_lvtt_tscdeadline(apic) || Now just add fastpath for tscdeadline mode. > > + vmx->rmode.vm86_active || > > + is_smm(vcpu) || > > + !kvm_apic_hw_enabled(apic)) These stuff can be removed, kvm_apic_hw_enable() is check in vmx_fast_deliver_interrupt(). > > + return EXIT_FASTPATH_NONE; > > + > > + if (!apic->lapic_timer.hv_timer_in_use) > > + return EXIT_FASTPATH_CONT_RUN; > > + > > + WARN_ON(swait_active(&vcpu->wq)); > > + vmx_cancel_hv_timer(vcpu); > > + apic->lapic_timer.hv_timer_in_use = false; > > + > > + if (atomic_read(&apic->lapic_timer.pending)) > > + return EXIT_FASTPATH_CONT_RUN; Other two checks are the same in kvm_lapic_expired_hv_timer(). Wanpeng > > + > > + ktimer->expired_tscdeadline = ktimer->tscdeadline; > > + vmx_fast_deliver_interrupt(vcpu); > > + ktimer->tscdeadline = 0; > > + return EXIT_FASTPATH_CONT_RUN; > > + } > > + > > Can you explain all the checks you have here, and why you need something > more complex than apic_timer_expired (possibly by adding some > optimizations to kvm_apic_local_deliver)? This code is impossible to > maintain. > > Paolo >
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 7688e40..623c4a0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6593,12 +6593,53 @@ static void vmx_fast_deliver_interrupt(struct kvm_vcpu *vcpu) } } +static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu); + +static enum exit_fastpath_completion handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct kvm_lapic *apic = vcpu->arch.apic; + struct kvm_timer *ktimer = &apic->lapic_timer; + + if (vmx_event_needs_reinjection(vcpu)) + return EXIT_FASTPATH_NONE; + + if (!vmx->req_immediate_exit && + !unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled)) { + if (!vmx_interrupt_allowed(vcpu) || + !apic_lvtt_tscdeadline(apic) || + vmx->rmode.vm86_active || + is_smm(vcpu) || + !kvm_apic_hw_enabled(apic)) + return EXIT_FASTPATH_NONE; + + if (!apic->lapic_timer.hv_timer_in_use) + return EXIT_FASTPATH_CONT_RUN; + + WARN_ON(swait_active(&vcpu->wq)); + vmx_cancel_hv_timer(vcpu); + apic->lapic_timer.hv_timer_in_use = false; + + if (atomic_read(&apic->lapic_timer.pending)) + return EXIT_FASTPATH_CONT_RUN; + + ktimer->expired_tscdeadline = ktimer->tscdeadline; + vmx_fast_deliver_interrupt(vcpu); + ktimer->tscdeadline = 0; + return EXIT_FASTPATH_CONT_RUN; + } + + return EXIT_FASTPATH_NONE; +} + static enum exit_fastpath_completion vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu) { if (!is_guest_mode(vcpu)) { switch(to_vmx(vcpu)->exit_reason) { case EXIT_REASON_MSR_WRITE: return handle_fastpath_set_msr_irqoff(vcpu); + case EXIT_REASON_PREEMPTION_TIMER: + return handle_fastpath_preemption_timer(vcpu); default: return EXIT_FASTPATH_NONE; }