qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 4/5] mc146818rtc: move x86 specific code out of


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH 4/5] mc146818rtc: move x86 specific code out of periodic_timer_update
Date: Wed, 3 May 2017 17:39:48 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0


On 12/04/2017 11:51, address@hidden wrote:
> From: Xiao Guangrong <address@hidden>
> 
> Move the x86 specific code in periodic_timer_update() to a common place,
> the actual logic is not changed
> 
> Signed-off-by: Xiao Guangrong <address@hidden>
> ---
>  hw/timer/mc146818rtc.c | 112 
> +++++++++++++++++++++++++++++--------------------
>  1 file changed, 66 insertions(+), 46 deletions(-)
> 
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index 3bf559d..d7b7c56 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -144,6 +144,63 @@ static void rtc_coalesced_timer(void *opaque)
>  
>      rtc_coalesced_timer_update(s);
>  }
> +
> +static int64_t
> +arch_periodic_timer_update(RTCState *s, int period, int64_t lost_clock)
> +{
> +    if (period != s->period) {
> +        int64_t scale_lost_clock;
> +        int current_irq_coalesced = s->irq_coalesced;
> +
> +        s->irq_coalesced = (current_irq_coalesced * s->period) / period;
> +
> +        /*
> +         * calculate the lost clock after it is scaled which should be
> +         * compensated in the next interrupt.
> +         */
> +        scale_lost_clock = current_irq_coalesced * s->period -
> +                            s->irq_coalesced * period;
> +        DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, %ld clocks "
> +                  "are compensated.\n", current_irq_coalesced,
> +                  s->irq_coalesced, scale_lost_clock);
> +        lost_clock += scale_lost_clock;
> +        s->period = period;

This should be moved up to the caller.

Also, if s->lost_tick_policy is not SLEW, s->irq_coalesced on input is
zero.  So I *think* what you get is equivalent to

   if (s->lost_tick_policy != LOST_TICK_POLICY_SLEW) {
       return;
   }

   /* ... comment ... */
   lost_interrupt = (s->irq_coalesced * s->period) / period;
   lost_clock += (s->irq_coalesced * s->period) % period;
   lost_interrupt += lost_clock / period;
   lost_clock %= period;

   s->irq_coalesced = load_interrupt;
   rtc_coalesced_timer_update(s);

or equivalently:

   lost_clock += s->irq_coalesced * s->period;

   s->irq_coalesced = lost_clock / period;
   lost_clock %= period;
   rtc_coalesced_timer_update(s);

I think you should probably merge these three patches and document the
resulting logic, because it's simpler than building it a patch at a time.

Thanks,

Paolo

> +    }
> +
> +    /*
> +     * if more than period clocks were passed, i.e, the timer interrupt
> +     * has been lost, we should catch up the time.
> +     */
> +    if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW &&
> +       (lost_clock / period)) {
> +        int lost_interrupt = lost_clock / period;
> +
> +        s->irq_coalesced += lost_interrupt;
> +        lost_clock -= lost_interrupt * period;
> +        if (lost_interrupt) {
> +            DPRINTF_C("cmos: compensate %d interrupts, coalesced irqs "
> +                      "increased to %d\n", lost_interrupt, s->irq_coalesced);
> +            rtc_coalesced_timer_update(s);
> +        }
> +    }
> +
> +    return lost_clock;
> +}
> +
> +static void arch_periodic_timer_disable(RTCState *s)
> +{
> +    s->irq_coalesced = 0;
> +}
> +#else
> +static int64_t
> +arch_periodic_timer_update(RTCState *s, int period, int64_t lost_clock)
> +{
> +    return lost_clock;
> +}
> +
> +static void arch_periodic_timer_disable(RTCState *s)
> +{
> +}
>  #endif
>  
>  static int period_code_to_clock(int period_code)
> @@ -175,24 +232,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, 
> int old_period)
>      if (period_code != 0
>          && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
>          period = period_code_to_clock(period_code);
> -#ifdef TARGET_I386
> -        if (period != s->period) {
> -            int current_irq_coalesced = s->irq_coalesced;
> -
> -            s->irq_coalesced = (current_irq_coalesced * s->period) / period;
>  
> -            /*
> -             * calculate the lost clock after it is scaled which should be
> -             * compensated in the next interrupt.
> -             */
> -            lost_clock += current_irq_coalesced * s->period -
> -                            s->irq_coalesced * period;
> -            DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, %ld clocks 
> "
> -                      "are compensated.\n",
> -                      current_irq_coalesced, s->irq_coalesced, lost_clock);
> -        }
> -        s->period = period;
> -#endif
>          /* compute 32 khz clock */
>          cur_clock =
>              muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
> @@ -219,42 +259,22 @@ periodic_timer_update(RTCState *s, int64_t 
> current_time, int old_period)
>  
>              /* calculate the clock since last interrupt. */
>              lost_clock += cur_clock - last_periodic_clock;
> -
> -#ifdef TARGET_I386
> -            /*
> -             * if more than period clocks were passed, i.e, the timer 
> interrupt
> -             * has been lost, we should catch up the time.
> -             */
> -            if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW &&
> -                (lost_clock / period)) {
> -                int lost_interrupt = lost_clock / period;
> -
> -                s->irq_coalesced += lost_interrupt;
> -                lost_clock -= lost_interrupt * period;
> -                if (lost_interrupt) {
> -                    DPRINTF_C("cmos: compensate %d interrupts, coalesced 
> irqs "
> -                              "increased to %d\n", lost_interrupt,
> -                              s->irq_coalesced);
> -                    rtc_coalesced_timer_update(s);
> -                }
> -            } else
> -#endif
> -            /*
> -             * 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);
> -            assert(lost_clock >= 0);
>          }
>  
> +        lost_clock = arch_periodic_timer_update(s, period, lost_clock);
> +
> +        /*
> +         * we should make the time progress anyway.
> +         */
> +        lost_clock = MIN(lost_clock, period);
> +        assert(lost_clock >= 0);
> +
>          next_irq_clock = cur_clock + period - lost_clock;
>          s->next_periodic_time = muldiv64(next_irq_clock, 
> NANOSECONDS_PER_SECOND,
>                                           RTC_CLOCK_RATE) + 1;
>          timer_mod(s->periodic_timer, s->next_periodic_time);
>      } else {
> -#ifdef TARGET_I386
> -        s->irq_coalesced = 0;
> -#endif
> +        arch_periodic_timer_disable(s);
>          timer_del(s->periodic_timer);
>      }
>  }
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]