qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 0/4] RTC: New logic to emulate RTC


From: Zhang, Yang Z
Subject: Re: [Qemu-devel] [PATCH v2 0/4] RTC: New logic to emulate RTC
Date: Thu, 23 Feb 2012 01:49:59 +0000

> -----Original Message-----
> From: Paolo Bonzini [mailto:address@hidden
> Sent: Wednesday, February 22, 2012 7:19 PM
> 
> 0) My alarm tests failed quite badly. :(  I attach a patch for kvm-unit-tests
> (repository at git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git).
> The tests can be compiled simply with "make" and run with "qemu-kvm -kernel
> /path/to/x86/rtc.flat -serial stdio -display none".  Upstream QEMU fails some 
> of
> the tests.  My branch rtc-cleanup at git://github.com/bonzini/qemu.git passes
> them.  The tests should take 30-40 seconds to run.
You are right. There are something wrong with alarm setting. I have fixed it in 
next version.

> Currently they hang very early because UF is not set.  I attempted to fix 
> that,
> but ran into other problems.  UIP seems not to be really in sync with the 
> update
> interrupt, because the 500 ms update tests pass when testing UIP, but not when
> testing UF.  (Another reason why I wanted to have the 500 ms
> rule: it improves reliability of tests!)
The current logic is not correct: It check the UIP with rtc clock and use a 
timer to set UF bit. Since the delay of the timer, those two do not in sync in 
some cases. Now, I separate UF logic from update interrupt. And base it on UIP. 
With this changed, it works.

> 1) Alarm must also be handled like update.  That is, the timer must be enabled
> when AF=0 rather than when AIE=1.  Again, this is not enough to fix the
> problems.
This is same as UF. The timer only for AIE not for AF. Also separate if from 
alarm logic and based it on UIP.

> 2) Instead of using gettimeofday, you should use qemu_get_clock_ns(rtc_clock).
> If host_clock == rtc_clock it is the same, see get_clock_realtime() in
> qemu-timer.h.  It also has the advantage that you can do all math in
> nanoseconds and remove the get_ticks_per_sec() / USEC_PER_SEC factors.
> 
> For example
> 
>     gettimeofday(&tv_now, NULL);
>     host_usec = tv_now.tv_sec * USEC_PER_SEC + tv_now.tv_usec;
> 
> should be simply:
> 
>     host_nsec = qemu_get_clock_ns(rtc_clock);
Good point!

> 3) Please move the very complicated alarm logic to a separate function.
Maybe I can add more annotate to explain it.

> Ideally, the timer update functions should be as simple as this:
> static void update_ended_timer_update(RTCState *s) {
>     if ((s->cmos_data[RTC_REG_C] & REG_C_UF) == 0 &&
>             !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
>         qemu_mod_timer(s->update_timer, rtc_update_time(s));
>     } else {
>         qemu_del_timer(s->update_timer);
>     }
> }
> 
> /* handle alarm timer */
> static void alarm_timer_update(RTCState *s) {
>     uint64_t next_update_time;
>     uint64_t expire_time;
> 
>     if ((s->cmos_data[RTC_REG_C] & REG_C_AF) == 0 &&
>             !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
>         next_update_time = rtc_update_time(s);
>         expire_time = (rtc_alarm_sec(s) - 1) * NSEC_PER_SEC +
> next_update_time;
>         qemu_mod_timer(s->alarm_timer, expire_time);
>     } else {
>         qemu_del_timer(s->alarm_timer);
>     }
> }
> 
> 
> 4) Related to this, my GCC reports a uninitialized variable at the += 1 here:
> 
>             } else if (cur_min == alarm_min) {
>                 if ((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0) {
>                     next_alarm_sec += 1;
>                 } else if (cur_sec < alarm_sec) {
>                     next_alarm_sec = alarm_sec - cur_sec;
>                 } else {
>                     min = alarm_min + MIN_PER_HOUR - cur_min;
>                     next_alarm_sec =
>                             alarm_sec + min * SEC_PER_MIN - cur_sec;
>                 }
> 
> I think it should be an "= 1" instead?
Yes, it should be "=1".
 
> 5) As a further cleanup, perhaps you can create hours_from_bcd and
> hours_to_bcd functions to abstract the 12/24 setting.
Good point!

> 6) Setting the clock after 500 ms happens not on every set, but only when 
> moving
> out of divider reset (register A bits 5-7 moving from 110 or 111 to 010).  As 
> far as
> I can read, SET prevents the registers from changing value, but keeps the 
> internal
> sub-second counters running.
Do we really need this logic? It sounds like senseless. 

best regards
yang



reply via email to

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