From 8af16b9722f5bdeacf3a30c21490846e24b989b2 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 4 Dec 2019 15:21:08 +0100 Subject: [PATCH 2/3] Revert "mc146818rtc: fix timer interrupt reinjection" RH-Author: Marcelo Tosatti Message-id: <20191204152436.753293175@amt.cnet> Patchwork-id: 92888 O-Subject: [RHEL-7.8 qemu-kvm-rhev PATCH 2/3] Revert "mc146818rtc: fix timer interrupt reinjection" Bugzilla: 1639098 RH-Acked-by: Laszlo Ersek RH-Acked-by: Paolo Bonzini RH-Acked-by: Vitaly Kuznetsov BZ: 1639098 Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=24854309 BRANCH: rhv7/master-2.12.0 Upstream: 3ae32adff17226bc6a5f3fd7bb9804e6779e0660 of pbonzini's for-upstream tree. This reverts commit b429de730174b388ea5760e3debb0d542ea3c261, except that the reversal of the outer "if (period)" is left in. Signed-off-by: Paolo Bonzini Signed-off-by: Marcelo Tosatti Signed-off-by: Miroslav Rezanina --- hw/timer/mc146818rtc.c | 67 +++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 296d974..d848911 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -196,7 +196,6 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period) int64_t cur_clock, next_irq_clock, lost_clock = 0; period = rtc_periodic_clock_ticks(s); - if (!period) { s->irq_coalesced = 0; timer_del(s->periodic_timer); @@ -219,42 +218,42 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period) last_periodic_clock = next_periodic_clock - old_period; lost_clock = cur_clock - last_periodic_clock; assert(lost_clock >= 0); + } + /* + * s->irq_coalesced can change for two reasons: + * + * a) if one or more periodic timer interrupts have been lost, + * lost_clock will be more that a period. + * + * b) when the period may be reconfigured, we expect the OS to + * treat delayed tick as the new period. So, when switching + * from a shorter to a longer period, scale down the missing, + * because the OS will treat past delayed ticks as longer + * (leftovers are put back into lost_clock). When switching + * to a shorter period, scale up the missing ticks since the + * OS handler will treat past delayed ticks as shorter. + */ + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + uint32_t old_irq_coalesced = s->irq_coalesced; + + s->period = period; + lost_clock += old_irq_coalesced * old_period; + s->irq_coalesced = lost_clock / s->period; + lost_clock %= s->period; + if (old_irq_coalesced != s->irq_coalesced || + old_period != s->period) { + DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, " + "period scaled from %d to %d\n", old_irq_coalesced, + s->irq_coalesced, old_period, s->period); + rtc_coalesced_timer_update(s); + } + } else { /* - * s->irq_coalesced can change for two reasons: - * - * a) if one or more periodic timer interrupts have been lost, - * lost_clock will be more that a period. - * - * b) when the period may be reconfigured, we expect the OS to - * treat delayed tick as the new period. So, when switching - * from a shorter to a longer period, scale down the missing, - * because the OS will treat past delayed ticks as longer - * (leftovers are put back into lost_clock). When switching - * to a shorter period, scale up the missing ticks since the - * OS handler will treat past delayed ticks as shorter. + * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW + * is not used, we should make the time progress anyway. */ - if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { - uint32_t old_irq_coalesced = s->irq_coalesced; - - s->period = period; - lost_clock += old_irq_coalesced * old_period; - s->irq_coalesced = lost_clock / s->period; - lost_clock %= s->period; - if (old_irq_coalesced != s->irq_coalesced || - old_period != s->period) { - DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, " - "period scaled from %d to %d\n", old_irq_coalesced, - s->irq_coalesced, old_period, s->period); - rtc_coalesced_timer_update(s); - } - } else { - /* - * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW - * is not used, we should make the time progress anyway. - */ - lost_clock = MIN(lost_clock, period); - } + lost_clock = MIN(lost_clock, period); } assert(lost_clock >= 0 && lost_clock <= period); -- 1.8.3.1