From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org
Subject: [Qemu-devel] [PATCH v2 5/5] pl031: switch clock base to rtc_clock
Date: Mon, 5 Mar 2012 10:08:15 +0100 [thread overview]
Message-ID: <1330938495-30573-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1330938495-30573-1-git-send-email-pbonzini@redhat.com>
This lets the user specify the desired semantics. By default, the RTC
will follow adjustments from the host's NTP client, and will remain in
sync when the virtual machine is stopped. The previous behavior, which
provides determinism with both icount and qtest, remains available with
"-rtc clock=vm".
pl031 supports migration, so we need to convert the time base from
rtc_clock to vm_clock and back for backwards compatibility. (The
rtc_clock may not be synchronized on the two machines, especially with
savevm/loadvm, so the conversion is needed anyway. And since any time
base will do, why not pick the one base that is backwards compatible).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/pl031.c | 38 ++++++++++++++++++++++++++------------
1 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/hw/pl031.c b/hw/pl031.c
index 713f85d..9602664 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -13,6 +13,7 @@
#include "sysbus.h"
#include "qemu-timer.h"
+#include "sysemu.h"
//#define DEBUG_PL031
@@ -38,6 +39,11 @@ typedef struct {
QEMUTimer *timer;
qemu_irq irq;
+ /* Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+ uint32_t tick_offset_vmstate;
uint32_t tick_offset;
uint32_t mr;
@@ -68,27 +74,23 @@ static void pl031_interrupt(void * opaque)
static uint32_t pl031_get_count(pl031_state *s)
{
- /* This assumes qemu_get_clock_ns returns the time since the machine was
- created. */
- return s->tick_offset + qemu_get_clock_ns(vm_clock) / get_ticks_per_sec();
+ int64_t now = qemu_get_clock_ns(rtc_clock);
+ return s->tick_offset + now / get_ticks_per_sec();
}
static void pl031_set_alarm(pl031_state *s)
{
- int64_t now;
uint32_t ticks;
- now = qemu_get_clock_ns(vm_clock);
- ticks = s->tick_offset + now / get_ticks_per_sec();
-
/* The timer wraps around. This subtraction also wraps in the same way,
and gives correct results when alarm < now_ticks. */
- ticks = s->mr - ticks;
+ ticks = s->mr - pl031_get_count(s);
DPRINTF("Alarm set in %ud ticks\n", ticks);
if (ticks == 0) {
qemu_del_timer(s->timer);
pl031_interrupt(s);
} else {
+ int64_t now = qemu_get_clock_ns(rtc_clock);
qemu_mod_timer(s->timer, now + (int64_t)ticks * get_ticks_per_sec());
}
}
@@ -190,18 +192,29 @@ static int pl031_init(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
- /* ??? We assume vm_clock is zero at this point. */
qemu_get_timedate(&tm, 0);
- s->tick_offset = mktimegm(&tm);
+ s->tick_offset = mktimegm(&tm) - qemu_get_clock_ns(rtc_clock) / get_ticks_per_sec();
- s->timer = qemu_new_timer_ns(vm_clock, pl031_interrupt, s);
+ s->timer = qemu_new_timer_ns(rtc_clock, pl031_interrupt, s);
return 0;
}
+static void pl031_pre_save(void *opaque)
+{
+ pl031_state *s = opaque;
+
+ /* tick_offset is base_time - rtc_clock base time. Instead, we want to
+ * store the base time relative to the vm_clock for backwards-compatibility. */
+ int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+ s->tick_offset_vmstate = s->tick_offset + delta / get_ticks_per_sec();
+}
+
static int pl031_post_load(void *opaque, int version_id)
{
pl031_state *s = opaque;
+ int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+ s->tick_offset = s->tick_offset_vmstate - delta / get_ticks_per_sec();
pl031_set_alarm(s);
return 0;
}
@@ -210,9 +223,10 @@ static const VMStateDescription vmstate_pl031 = {
.name = "pl031",
.version_id = 1,
.minimum_version_id = 1,
+ .pre_save = pl031_pre_save,
.post_load = pl031_post_load,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(tick_offset, pl031_state),
+ VMSTATE_UINT32(tick_offset_vmstate, pl031_state),
VMSTATE_UINT32(mr, pl031_state),
VMSTATE_UINT32(lr, pl031_state),
VMSTATE_UINT32(cr, pl031_state),
--
1.7.7.6
next prev parent reply other threads:[~2012-03-05 9:09 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-05 9:08 [Qemu-devel] [PATCH v2 0/5] Make rt_clock usage configurable for ARM devices Paolo Bonzini
2012-03-05 9:08 ` [Qemu-devel] [PATCH v2 1/5] rtc: add -rtc clock=rt Paolo Bonzini
2012-03-05 9:08 ` [Qemu-devel] [PATCH v2 2/5] omap: switch omap_lpg to vm_clock Paolo Bonzini
2012-03-05 9:08 ` [Qemu-devel] [PATCH v2 3/5] arm: switch real-time clocks to rtc_clock Paolo Bonzini
2012-03-05 9:08 ` [Qemu-devel] [PATCH v2 4/5] pl031: rearm alarm timer upon load Paolo Bonzini
2012-03-05 9:08 ` Paolo Bonzini [this message]
2012-03-05 14:05 ` [Qemu-devel] [PATCH v2 0/5] Make rt_clock usage configurable for ARM devices Peter Maydell
2012-03-13 10:46 ` Paolo Bonzini
2012-03-27 17:07 ` Paolo Bonzini
2012-03-27 17:24 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1330938495-30573-6-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).