* [Qemu-devel] [PATCH 0/2] qemu-timer/mc146818rtc: fix timer issues related to clock changes @ 2015-06-12 14:05 Paul Donohue 2015-06-12 14:08 ` [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps Paul Donohue 2015-06-12 14:10 ` [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load Paul Donohue 0 siblings, 2 replies; 8+ messages in thread From: Paul Donohue @ 2015-06-12 14:05 UTC (permalink / raw) To: qemu-devel; +Cc: Paolo Bonzini If the host clock jumps forward or backward without resetting the mc146818rtc's periodic timer, the periodic timer interrupts will either fire rapidly (consuming host CPU and blocking operation of the VM) until the timer catches up to the new host clock, or will stall until the host clock catches up with the prior date used by the periodic timer. A "reset notifier" mechanism was introduced a while back that resets the mc146818rtc's periodic timer if the host clock jumps backward while the VM is running. However, the timer is not reset if the host clock jumps forward while the VM is running, or if the clock jumps either forward or backward when loading a snapshot or migration. In one test case, when loading a 3 week old snapshot, the timer loop consumed CPU and blocked the VM for nearly 90 seconds. The following patches fix this issue by resetting the timer in these cases. Paul Donohue (2): qemu-timer: Call clock reset notifiers on large forward jumps mc146818rtc: Reset the periodic timer on resume from snapshot hw/timer/mc146818rtc.c | 6 ++++++ include/qemu/timer.h | 9 +++++++++ qemu-timer.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps 2015-06-12 14:05 [Qemu-devel] [PATCH 0/2] qemu-timer/mc146818rtc: fix timer issues related to clock changes Paul Donohue @ 2015-06-12 14:08 ` Paul Donohue 2015-06-17 14:00 ` Paolo Bonzini 2015-06-12 14:10 ` [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load Paul Donohue 1 sibling, 1 reply; 8+ messages in thread From: Paul Donohue @ 2015-06-12 14:08 UTC (permalink / raw) To: qemu-devel; +Cc: Paolo Bonzini Commit 691a0c9c introduced a mechanism by which QEMU_CLOCK_HOST can notify other parts of the emulator when the host clock has jumped backward. This is used to avoid stalling timers that were scheduled based on the host clock. However, if the host clock jumps forward, then timers that were scheduled based on the host clock may fire rapidly and cause other problems. For example, the mc146818rtc periodic timer will block execution of the VM and consume host CPU while firing every interrupt for the time period that was skipped by the host clock. To correct that problem, this commit fires the reset notification if the host clock jumps forward by more than a hard-coded limit. The limit is currently set to a value of 60 seconds, which should be small enough to prevent excessive timer loops, but large enough to avoid frequent resets in idle VMs. Signed-off-by: Paul Donohue <qemu-git@PaulSD.com> --- include/qemu/timer.h | 9 +++++++++ qemu-timer.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index e5bd494..0193036 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -787,6 +787,14 @@ static inline int64_t get_ticks_per_sec(void) return 1000000000LL; } +static inline int64_t get_max_clock_jump(void) +{ + // This should be small enough to prevent excessive interrupts from being + // generated by the RTC on clock jumps, but large enough to avoid frequent + // unnecessary resets in idle VMs. + return 60 * get_ticks_per_sec(); +} + /* * * Low level clock functions * */ diff --git a/qemu-timer.c b/qemu-timer.c index 5741f0d..d27be3d 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -573,7 +573,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type) now = get_clock_realtime(); last = clock->last; clock->last = now; - if (now < last) { + if (now < last || now > (last + get_max_clock_jump())) { notifier_list_notify(&clock->reset_notifiers, &now); } return now; -- 2.1.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps 2015-06-12 14:08 ` [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps Paul Donohue @ 2015-06-17 14:00 ` Paolo Bonzini 2015-06-18 12:58 ` Paul Donohue 0 siblings, 1 reply; 8+ messages in thread From: Paolo Bonzini @ 2015-06-17 14:00 UTC (permalink / raw) To: Paul Donohue, qemu-devel On 12/06/2015 16:08, Paul Donohue wrote: > +static inline int64_t get_max_clock_jump(void) > +{ > + // This should be small enough to prevent excessive interrupts from being > + // generated by the RTC on clock jumps, but large enough to avoid frequent > + // unnecessary resets in idle VMs. This is not how comments are layed out in QEMU... > + return 60 * get_ticks_per_sec(); > +} > + > /* > * * Low level clock functions > * */ ... and it also looks like your editor has mangled this patch. Nevertheless, I've applied it to my local branch and will send it out for inclusion after some more testing. Paolo > diff --git a/qemu-timer.c b/qemu-timer.c > index 5741f0d..d27be3d 100644 > --- a/qemu-timer.c > +++ b/qemu-timer.c ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps 2015-06-17 14:00 ` Paolo Bonzini @ 2015-06-18 12:58 ` Paul Donohue 2015-06-18 13:17 ` Paolo Bonzini 0 siblings, 1 reply; 8+ messages in thread From: Paul Donohue @ 2015-06-18 12:58 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel On Wed, Jun 17, 2015 at 04:00:06PM +0200, Paolo Bonzini wrote: > On 12/06/2015 16:08, Paul Donohue wrote: > > +static inline int64_t get_max_clock_jump(void) > > +{ > > + // This should be small enough to prevent excessive interrupts from being > > + // generated by the RTC on clock jumps, but large enough to avoid frequent > > + // unnecessary resets in idle VMs. > This is not how comments are layed out in QEMU... Oops. Sorry, I'm not sure how I missed that. Force of habit from other projects, I guess... > > + return 60 * get_ticks_per_sec(); > > +} > > + > > /* > > * * Low level clock functions > > * */ > ... and it also looks like your editor has mangled this patch. Ugh, yes. I do remember noticing that, and I thought I fixed it, but apparently not. I will correct and send an updated patch. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps 2015-06-18 12:58 ` Paul Donohue @ 2015-06-18 13:17 ` Paolo Bonzini 0 siblings, 0 replies; 8+ messages in thread From: Paolo Bonzini @ 2015-06-18 13:17 UTC (permalink / raw) To: Paul Donohue; +Cc: qemu-devel On 18/06/2015 14:58, Paul Donohue wrote: > On Wed, Jun 17, 2015 at 04:00:06PM +0200, Paolo Bonzini wrote: >> On 12/06/2015 16:08, Paul Donohue wrote: >>> +static inline int64_t get_max_clock_jump(void) >>> +{ >>> + // This should be small enough to prevent excessive interrupts from being >>> + // generated by the RTC on clock jumps, but large enough to avoid frequent >>> + // unnecessary resets in idle VMs. >> This is not how comments are layed out in QEMU... > Oops. Sorry, I'm not sure how I missed that. Force of habit from > other projects, I guess... > >>> + return 60 * get_ticks_per_sec(); >>> +} >>> + >>> /* >>> * * Low level clock functions >>> * */ >> ... and it also looks like your editor has mangled this patch. > Ugh, yes. I do remember noticing that, and I thought I fixed it, but > apparently not. > > I will correct and send an updated patch. No problem, I fixed this already. Paolo ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load 2015-06-12 14:05 [Qemu-devel] [PATCH 0/2] qemu-timer/mc146818rtc: fix timer issues related to clock changes Paul Donohue 2015-06-12 14:08 ` [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps Paul Donohue @ 2015-06-12 14:10 ` Paul Donohue 2015-06-17 14:01 ` Paolo Bonzini 1 sibling, 1 reply; 8+ messages in thread From: Paul Donohue @ 2015-06-12 14:10 UTC (permalink / raw) To: qemu-devel; +Cc: Paolo Bonzini When loading a VM from a snapshot or migration, clock changes can cause the periodic timer to stall or loop rapidly. qemu-timer has a reset notifier mechanism that is used to avoid timer stalls or loops if the host clock changes while the VM is running when using QEMU_CLOCK_HOST. However, when loading a snapshot or migration, qemu-timer is initialized and fires the reset notifier before mc146818rtc is initialized and has registered its reset handler. In addition, this mechanism isn't used when using QEMU_CLOCK_REALTIME, which might also change when loading a snapshot or migration. To correct that problem, this commit resets the periodic timer after loading from a snapshot or migration if the clock has either jumped backward or has jumped forward by more than the clock jump limit that is used by the reset notifier code in qemu-timer. Signed-off-by: Paul Donohue <qemu-git@PaulSD.com> --- hw/timer/mc146818rtc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index f2b77fa..68cf1f0 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -723,6 +723,12 @@ static int rtc_post_load(void *opaque, int version_id) check_update_timer(s); } + uint64_t now = qemu_clock_get_ns(rtc_clock); + if (now < (s->next_periodic_time - get_ticks_per_sec()) || + now > (s->next_periodic_time + get_max_clock_jump())) { + periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + } + #ifdef TARGET_I386 if (version_id >= 2) { if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { -- 2.1.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load 2015-06-12 14:10 ` [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load Paul Donohue @ 2015-06-17 14:01 ` Paolo Bonzini 2015-06-18 14:36 ` Paul Donohue 0 siblings, 1 reply; 8+ messages in thread From: Paolo Bonzini @ 2015-06-17 14:01 UTC (permalink / raw) To: Paul Donohue, qemu-devel On 12/06/2015 16:10, Paul Donohue wrote: > To correct that problem, this commit resets the periodic timer after > loading from a snapshot or migration if the clock has either jumped > backward or has jumped forward by more than the clock jump limit that > is used by the reset notifier code in qemu-timer. > > Signed-off-by: Paul Donohue <qemu-git@PaulSD.com> > --- > hw/timer/mc146818rtc.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c > index f2b77fa..68cf1f0 100644 > --- a/hw/timer/mc146818rtc.c > +++ b/hw/timer/mc146818rtc.c > @@ -723,6 +723,12 @@ static int rtc_post_load(void *opaque, int version_id) > check_update_timer(s); > } > > + uint64_t now = qemu_clock_get_ns(rtc_clock); > + if (now < (s->next_periodic_time - get_ticks_per_sec()) || What is the reason for the "- get_ticks_per_sec()" adjustment? Can I just remove it? Paolo > + now > (s->next_periodic_time + get_max_clock_jump())) { ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load 2015-06-17 14:01 ` Paolo Bonzini @ 2015-06-18 14:36 ` Paul Donohue 0 siblings, 0 replies; 8+ messages in thread From: Paul Donohue @ 2015-06-18 14:36 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel On Wed, Jun 17, 2015 at 04:01:33PM +0200, Paolo Bonzini wrote: > On 12/06/2015 16:10, Paul Donohue wrote: > > To correct that problem, this commit resets the periodic timer after > > loading from a snapshot or migration if the clock has either jumped > > backward or has jumped forward by more than the clock jump limit that > > is used by the reset notifier code in qemu-timer. > > > > diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c > > @@ -723,6 +723,12 @@ static int rtc_post_load(void *opaque, int version_id) > > check_update_timer(s); > > } > > > > + uint64_t now = qemu_clock_get_ns(rtc_clock); > > + if (now < (s->next_periodic_time - get_ticks_per_sec()) || > > What is the reason for the "- get_ticks_per_sec()" adjustment? Can I > just remove it? Short answer: Yes, you can remove it. Long answer: In the other (qemu-timer) patch, I thought it was a good idea to try to avoid calling the clock reset notifiers in cases where the clock "jumped" because the VM was idle, and err on the side of not calling the notifiers for real but small host clock changes. At that layer of the abstraction, it is not clear how any particular RTC implementation might use the reset notification, so I didn't want to assume it was safe to trigger the notification too frequently. That thought process carried over when I patched mc146818rtc.c, and I was trying to avoid calling periodic_timer_update() in any cases where it wasn't strictly needed. At the time when a snapshot is taken, "now" should generally be less than "next_periodic_time" by up to one period worth of time. In the case where the snapshot is loaded when "now" is still less than "next_periodic_time", "now < s->next_periodic_time" would not necessarily indicate that the clock has jumped backward. Calculating the period so we could evaluate "now < s->next_periodic_time - period" would involve duplicating a lot of the code from periodic_timer_update(), which I thought was a bad idea. So, I simply assumed that the period would always be less than 1 second, and used "- get_ticks_per_sec()" to err on the side of skipping the call to periodic_timer_update(). However, now that I'm looking at it again, calling periodic_timer_update() when "now" is less than "next_periodic_time" by less than one period would have no effect anyway, so the "- get_ticks_per_sec()" adjustment is unnecessary, and it was silly for me to try to avoid a call to to periodic_timer_update() in that case. Thanks! ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-06-18 14:36 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-06-12 14:05 [Qemu-devel] [PATCH 0/2] qemu-timer/mc146818rtc: fix timer issues related to clock changes Paul Donohue 2015-06-12 14:08 ` [Qemu-devel] [PATCH 1/2] qemu-timer: Call clock reset notifiers on forward jumps Paul Donohue 2015-06-17 14:00 ` Paolo Bonzini 2015-06-18 12:58 ` Paul Donohue 2015-06-18 13:17 ` Paolo Bonzini 2015-06-12 14:10 ` [Qemu-devel] [PATCH 2/2] mc146818rtc: Reset the periodic timer on load Paul Donohue 2015-06-17 14:01 ` Paolo Bonzini 2015-06-18 14:36 ` Paul Donohue
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.