On Thu, 16 Sept 2021 at 18:19, Eric Auger <eric.au...@redhat.com> wrote:
>
> Hi Peter,
> On 9/16/21 3:32 PM, Peter Maydell wrote:
> > None of the other users of qapi_event_send_rtc_change()
> > seem to have to track the baseline time like this. Shouldn't
> > this be doing something involving using qemu_ref_timedate()
> > as the baseline that it uses to figure out the change value ?
> > (The other users do this via qemu_timedate_diff() but since we
> > start with a value-in-seconds we might want to expose some other
> > API in softmmu/rtc.c.)
>
> I struggled understanding the various kinds of clocks modeled in qemu
> and the PL031 implementation. Both devices calling
> qapi_event_send_rtc_change() seem to store the base rtc in their state
> (mc146818rtc.c cmos data or spapr_rtc tas_ld(args, )) and then
> effectivelly call qemu_timedate_diff() on this base rtc value. I did not
> figure to do the equivalent with the pl031. I will further investigate
> how I can mimic their implementation though.

mc146818rtc.c calls qapi_event_send_rtc_change() in rtc_set_time().
It looks to me like that is just "when the guest writes to an
RTC register such that the guest RTC time has changed, use
qemu_timedate_diff() to find out the delta between that and what
the softmmu/rtc.c clock has as its baseline time, and then pass
that delta in seconds to qapi_event_send_rtc_change()".
This RTC has a lot of separate day/month/year registers, so the
implementation's idea of "current guest RTC setting" is a
complicated thing that it fills in into a struct tm, and which
qemu_timedate_diff() then parses back out into a "seconds" value.

spapr_rtc() is a hypercall implementation, so the guest passes it
a complete set of year/month/day/etc values all at once to set the time.

pl031 is a lot simpler as it is essentially just a count of
time in seconds, which we set up as "seconds since the Unix epoch".
But the basic principle is the same: the device contains the state
that tells you what it thinks the guest RTC value is now, and the
value we want to pass qapi_event_send_rtc_change() is the
difference between that and the reference time kept in
softmmu/rtc.c.

I think what you want is probably:

    struct tm tm;

    qemu_get_timedate(&tm, s->tick_offset);
    qapi_event_send_rtc_change(qemu_timedate_diff(&tm));

But I'm not 100% sure. I also feel like this is doing a
roundtrip from seconds to struct tm to seconds again, which
seems a bit silly (but it might matter if the rtc is configured
to 'localtime'? At any rate it's not completely clear that
it's always a no-op roundtrip).

I've cc'd Paolo who might be a bit more familiar with the rtc code
than I am.

-- PMM

Reply via email to