RE: [PATCH v2 0/4] RTC: New logic to emulate RTC

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

 



> -----Original Message-----
> From: Paolo Bonzini [mailto:pbonzini@xxxxxxxxxx]
> 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
--
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