qemu-arm
[Top][All Lists]
Advanced

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

[PATCH] hw/rtc/pl031: Send RTC_CHANGE QMP event


From: Eric Auger
Subject: [PATCH] hw/rtc/pl031: Send RTC_CHANGE QMP event
Date: Thu, 9 Sep 2021 14:24:02 +0200

The PL031 currently is not able to report guest RTC change to the QMP
monitor as opposed to mc146818 or spapr RTCs. This patch adds the call
to qapi_event_send_rtc_change() when the Load Register is written. The
value that is reported corresponds to the difference between the new
RTC value and the RTC value elapsed since the base.

For instance adding 20s to the guest RTC value will report 20:
{'timestamp': {'seconds': 1631189494, 'microseconds': 16932},
'event': 'RTC_CHANGE', 'data': {'offset': 20}}

Adding another extra 20s to the guest RTC value will report 40:
{'timestamp': {'seconds': 1631189498, 'microseconds': 9708},
'event': 'RTC_CHANGE', 'data': {'offset': 40}}

To compute the offset we need to track the origin tick_offset (the one
computed at init time). So we need to migrate that field, which is done
in a dedicated subsection. The migration of this subsection is disabled
for machine types less or equal than 6.1.

After migration, adding an extra 20s on the destination returns 60:
{'timestamp': {'seconds': 1631189522, 'microseconds': 13081},
'event': 'RTC_CHANGE', 'data': {'offset': 60}}

Signed-off-by: Eric Auger <eric.auger@redhat.com>

---

Tested with the following script run on guest:

  #!/bin/sh
  old=$(hwclock --show | cut -f1-7 -d' ')
  oldabs=$(date +%s -d "$old")
  newabs=$(expr $oldabs + $1)
  new=$(date -d @"$newabs")
  echo Old: $oldabs $old
  echo New: $newabs $new
  hwclock --set --date "$new"

This was tested with both -rtc base=2010-12-03T01:02:00 and base=utc
qemu options. As far as I can see the reported value match what
is observed on x86 (except on x86 the values are not exactly the one
used on guest, ie. 18 for instance instead of 20).

Without migrating the original tick_offset (ie. original_tick_offset
taking the destination init tick_offset value), a delta is observed. I
don't know whether it is a bug. At firt glance I had the
impression it worked without the migration scheme but this delta
urged me to migrate the original_offset too.
---
 hw/core/machine.c      |  4 +++-
 hw/rtc/meson.build     |  2 +-
 hw/rtc/pl031.c         | 25 +++++++++++++++++++++++++
 include/hw/rtc/pl031.h |  2 ++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 067f42b528f..e93cc4ab39d 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -37,7 +37,9 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-pci.h"
 
-GlobalProperty hw_compat_6_1[] = {};
+GlobalProperty hw_compat_6_1[] = {
+    { "pl031", "migrate-original-tick-offset", "false" },
+};
 const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1);
 
 GlobalProperty hw_compat_6_0[] = {
diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build
index 7cecdee5ddb..8fd8d8f9a71 100644
--- a/hw/rtc/meson.build
+++ b/hw/rtc/meson.build
@@ -2,7 +2,7 @@
 softmmu_ss.add(when: 'CONFIG_DS1338', if_true: files('ds1338.c'))
 softmmu_ss.add(when: 'CONFIG_M41T80', if_true: files('m41t80.c'))
 softmmu_ss.add(when: 'CONFIG_M48T59', if_true: files('m48t59.c'))
-softmmu_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c'))
+specific_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c'))
 softmmu_ss.add(when: 'CONFIG_TWL92230', if_true: files('twl92230.c'))
 softmmu_ss.add(when: ['CONFIG_ISA_BUS', 'CONFIG_M48T59'], if_true: 
files('m48t59-isa.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-rtc.c'))
diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c
index 2bbb2062ac8..51dc14559c5 100644
--- a/hw/rtc/pl031.c
+++ b/hw/rtc/pl031.c
@@ -24,6 +24,8 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qemu/timer.h"
+#include "qapi/qapi-events-misc-target.h"
 
 #define RTC_DR      0x00    /* Data read register */
 #define RTC_MR      0x04    /* Match register */
@@ -138,6 +140,7 @@ static void pl031_write(void * opaque, hwaddr offset,
     switch (offset) {
     case RTC_LR:
         s->tick_offset += value - pl031_get_count(s);
+        qapi_event_send_rtc_change(s->tick_offset - s->original_tick_offset);
         pl031_set_alarm(s);
         break;
     case RTC_MR:
@@ -190,6 +193,7 @@ static void pl031_init(Object *obj)
     qemu_get_timedate(&tm, 0);
     s->tick_offset = mktimegm(&tm) -
         qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
+    s->original_tick_offset = s->tick_offset;
 
     s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
 }
@@ -287,6 +291,24 @@ static const VMStateDescription vmstate_pl031_tick_offset 
= {
     }
 };
 
+static bool pl031_original_tick_offset_needed(void *opaque)
+{
+    PL031State *s = opaque;
+
+    return s->migrate_original_tick_offset;
+}
+
+static const VMStateDescription vmstate_pl031_original_tick_offset = {
+    .name = "pl031/original-tick-offset",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pl031_original_tick_offset_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(original_tick_offset, PL031State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_pl031 = {
     .name = "pl031",
     .version_id = 1,
@@ -305,6 +327,7 @@ static const VMStateDescription vmstate_pl031 = {
     },
     .subsections = (const VMStateDescription*[]) {
         &vmstate_pl031_tick_offset,
+        &vmstate_pl031_original_tick_offset,
         NULL
     }
 };
@@ -320,6 +343,8 @@ static Property pl031_properties[] = {
      */
     DEFINE_PROP_BOOL("migrate-tick-offset",
                      PL031State, migrate_tick_offset, true),
+    DEFINE_PROP_BOOL("migrate-original-tick-offset",
+                     PL031State, migrate_original_tick_offset, true),
     DEFINE_PROP_END_OF_LIST()
 };
 
diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h
index 9fd4be1abba..e1a12753d7d 100644
--- a/include/hw/rtc/pl031.h
+++ b/include/hw/rtc/pl031.h
@@ -37,6 +37,8 @@ struct PL031State {
     uint32_t tick_offset;
     bool tick_offset_migrated;
     bool migrate_tick_offset;
+    uint32_t original_tick_offset;
+    bool migrate_original_tick_offset;
 
     uint32_t mr;
     uint32_t lr;
-- 
2.26.3




reply via email to

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