2017-06-23 17:22 GMT+08:00 Wanpeng Li <kernellwp@xxxxxxxxx>: > From: Wanpeng Li <wanpeng.li@xxxxxxxxxxx> > > Linux as a guest will prevent to program the next event to the clock event > device when the event is in the past. However, it is not guaranteed by all > the guests, the guest like kvm-unit-tests/apic.flat will write current tsc > value visible in guest to MSR_IA32_TSCDEADLINE, lapic timer which is emulated > by vmx preemption timer will program the absolute target tsc value to vmcs > preemption timer field w/ delta == 0, then plays a vmentry and an upcoming > vmx preemption timer fire vmexit dance, the lapic timer injection is delayed > for this duration. Actually the lapic timer which is emulated by hrtimer can > handle this correctly. > > This patch fixes it by firing the lapic timer and injecting a timer interrupt > immediately during the next vmentry if guest programs an expired timer to > the emulated timer device. > > Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> > Cc: Radim Krčmář <rkrcmar@xxxxxxxxxx> > Signed-off-by: Wanpeng Li <wanpeng.li@xxxxxxxxxxx> > --- > arch/x86/kvm/lapic.c | 6 +++++- > arch/x86/kvm/vmx.c | 3 +++ > 2 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c > index d24c874..8a1263a 100644 > --- a/arch/x86/kvm/lapic.c > +++ b/arch/x86/kvm/lapic.c > @@ -1504,12 +1504,16 @@ static void cancel_hv_timer(struct kvm_lapic *apic) > static bool start_hv_timer(struct kvm_lapic *apic) > { > u64 tscdeadline = apic->lapic_timer.tscdeadline; > + int ret = 0; > > if ((atomic_read(&apic->lapic_timer.pending) && > !apic_lvtt_period(apic)) || > - kvm_x86_ops->set_hv_timer(apic->vcpu, tscdeadline)) { > + (ret = kvm_x86_ops->set_hv_timer(apic->vcpu, tscdeadline))) { > if (apic->lapic_timer.hv_timer_in_use) > cancel_hv_timer(apic); > + if (ret == 1) > + apic_timer_expired(apic); > + return true; Ouch! I just sent a wrong version. Regards, Wanpeng Li > } else { > apic->lapic_timer.hv_timer_in_use = true; > hrtimer_cancel(&apic->lapic_timer.timer); > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 2e906cf..2008e9b 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -11149,6 +11149,9 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc) > u64 guest_tscl = kvm_read_l1_tsc(vcpu, tscl); > u64 delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl; > > + if (delta_tsc == 0) > + return 1; > + > /* Convert to host delta tsc if tsc scaling is enabled */ > if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio && > u64_shl_div_u64(delta_tsc, > -- > 2.7.4 >