From patchwork Mon Mar 5 09:08:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 144631 X-Patchwork-Delegate: peter.maydell@linaro.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3358EB6F9F for ; Mon, 5 Mar 2012 20:09:20 +1100 (EST) Received: from localhost ([::1]:47274 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4Tuv-0004tq-QA for incoming@patchwork.ozlabs.org; Mon, 05 Mar 2012 04:09:17 -0500 Received: from eggs.gnu.org ([208.118.235.92]:45082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4TuY-0004UI-Vh for qemu-devel@nongnu.org; Mon, 05 Mar 2012 04:09:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4TuO-0002fP-7E for qemu-devel@nongnu.org; Mon, 05 Mar 2012 04:08:54 -0500 Received: from mail-pw0-f45.google.com ([209.85.160.45]:35032) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4TuN-0002ZD-Uz for qemu-devel@nongnu.org; Mon, 05 Mar 2012 04:08:44 -0500 Received: by mail-pw0-f45.google.com with SMTP id uo5so4074065pbc.4 for ; Mon, 05 Mar 2012 01:08:43 -0800 (PST) Received-SPF: pass (google.com: domain of paolo.bonzini@gmail.com designates 10.68.203.73 as permitted sender) client-ip=10.68.203.73; Authentication-Results: mr.google.com; spf=pass (google.com: domain of paolo.bonzini@gmail.com designates 10.68.203.73 as permitted sender) smtp.mail=paolo.bonzini@gmail.com; dkim=pass header.i=paolo.bonzini@gmail.com Received: from mr.google.com ([10.68.203.73]) by 10.68.203.73 with SMTP id ko9mr46306353pbc.130.1330938523214 (num_hops = 1); Mon, 05 Mar 2012 01:08:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=7U/J2+hb1CbCBsz4LZdZesVjgGHDSFkcKd30VyVuTk8=; b=paUMvVGhea8Gs/suh+CzMla/uqkVK8+/icX2LQ8hqbUdkXj5QpddZSKHKBRNbVkFLb vBew9ILYZhgMngPU7flmrLFGCD4YYBNvhjhqCq1RTGWVX21bQyxJZfvwjbjEsyYzNtWC 7TnCDt5KhuMboOvXx5myOIrAdJe1gz5pfP0F/oUEeZ5b3i60e57qxaNsOdyTU5UxQGm6 4prws5FZhJbFh5D0FPaXeSQtgipRVzO3b/wB1z61TZAeWRPW1PpOPI0FjXVPk/VKKT1i Y92Sv28NtCLzoI4o0NeORd9kgl2VBdD1kOWKD3QxzPkxaLssKXQmhh8/ovORXbeb2ct9 5/lQ== Received: by 10.68.203.73 with SMTP id ko9mr39581113pbc.130.1330938523168; Mon, 05 Mar 2012 01:08:43 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id l8sm12838857pbi.0.2012.03.05.01.08.40 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 05 Mar 2012 01:08:42 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Mon, 5 Mar 2012 10:08:15 +0100 Message-Id: <1330938495-30573-6-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1330938495-30573-1-git-send-email-pbonzini@redhat.com> References: <1330938495-30573-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.45 Cc: peter.maydell@linaro.org Subject: [Qemu-devel] [PATCH v2 5/5] pl031: switch clock base to rtc_clock X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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),