Re: hard lockup in wait_lapic_expire() - bug in TSC deadline timer?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 24/05/16 13:51, Paolo Bonzini wrote:
On 23/05/2016 16:30, Alan Jenkins wrote:
https://github.com/torvalds/linux/compare/master...sourcejedi:kvm_lockup_fix?expand=1
Here the comparison (and the expired_advance_ns field) is only used to
issue the warning.
No, because expired_advance_ns is used as the limit for the busy-wait.

Could you change the patch to use __delay instead of
ndelay and
No, because the limit is in ns, not host TSC ticks. Also, we were passing _guest_ TSC ticks to __delay(), which looks like a second potential cause of lockups because guest TSC ticks are scaled.

  omit the warning?
Certainly, and I have a positive suggestion to make the code more agreeable if it doesn't need WARN_ON(). Thanks for reviewing this. I'll send a revised version of the patch after testing.

The field expired_advance_ns was an attempt to prevent warnings (and premature timer interrupts) in case lapic_timer_advance_ns is tuned downwards, while we're running. This was a third potential case I noticed, which could have caused a lockup.

The problem was I didn't want to make a user-triggerable WARN_ON. But if we don't want WARN_ON at all, then maybe it's ok to compare the module parameter racily, so we don't need the extra field. There's no existing documentation which I could update, to say that reducing lapic_timer_advance_ns is not supported, right? (Because even with checks, it means the guest deadline timer can fire when the TSC is showing a time prior to the deadline, so it could break guest assumptions).

I wanted to log _a_ warning because I'm writing another patch there (if you've seen the parent commit) which is supposed to prevent it ever happening. A better alternative would be to have the workaround first (and for -stable), without the warning. (I assume you still dislike WARN_ON with the other patch, but I would try to sell you on at least printk_once(KERN_ERROR :).

+	if (guest_tsc < tsc_deadline) {
+		unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz;
+		u64 delay_ns;
+
+		delay_ns = (tsc_deadline - guest_tsc) * 1000000ULL;
+		do_div(delay_ns, this_tsc_khz);
+
+		if (delay_ns > apic->lapic_timer.expired_advance_ns) {
+			vcpu_err(vcpu,
+			         "timer for tsc_deadline fired too far in advance: %lluns\n",
+			         delay_ns);
+			WARN_ON(1);
+
+			/* avoid lockup. emulated timer will fire early */
+			delay_ns = apic->lapic_timer.expired_advance_ns;
+		}
+
+		ndelay(delay_ns);
+	}

Thanks,

Paolo

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux