From patchwork Thu Mar 31 13:17:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhanghailiang X-Patchwork-Id: 8712941 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5C6B9C0553 for ; Thu, 31 Mar 2016 13:23:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4B99820221 for ; Thu, 31 Mar 2016 13:23:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E6CB820149 for ; Thu, 31 Mar 2016 13:23:24 +0000 (UTC) Received: from localhost ([::1]:60428 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1alcZI-0004m5-0N for patchwork-qemu-devel@patchwork.kernel.org; Thu, 31 Mar 2016 09:23:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33779) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1alcZ8-0004lv-8r for qemu-devel@nongnu.org; Thu, 31 Mar 2016 09:23:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1alcZ3-00049a-Kn for qemu-devel@nongnu.org; Thu, 31 Mar 2016 09:23:14 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:35709) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1alcZ2-00048J-Mw for qemu-devel@nongnu.org; Thu, 31 Mar 2016 09:23:09 -0400 Received: from 172.24.1.51 (EHLO szxeml431-hub.china.huawei.com) ([172.24.1.51]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BZB24531; Thu, 31 Mar 2016 21:22:51 +0800 (CST) Received: from [127.0.0.1] (10.177.24.212) by szxeml431-hub.china.huawei.com (10.82.67.208) with Microsoft SMTP Server id 14.3.235.1; Thu, 31 Mar 2016 21:22:44 +0800 To: , References: <56FA6DE5.6050901@huawei.com> From: Hailiang Zhang Message-ID: <56FD2358.8050801@huawei.com> Date: Thu, 31 Mar 2016 21:17:12 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: <56FA6DE5.6050901@huawei.com> X-Originating-IP: [10.177.24.212] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.56FD24AC.00B1, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 3ae41b9b2101214603ce1820b1ad3f31 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 119.145.14.66 Cc: peter.huangpeng@huawei.com, Xiexiangyou , "qemu-devel@nongnu.org" Subject: Re: [Qemu-devel] [Bug?] Windows 7's time drift obviously while RTC rate switching frequently between high and low timer rate 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ping... It seems that we can eliminate the drift by the following patch. (I tested it for two hours, and there is no drift, before, the timer in Windows 7 drifts about 2 seconds per minute.) I'm not sure if it is the right way to solve the problem. Any comments are welcomed. Thanks. From bd6acd577cbbc9d92d6376c770219470f184f7de Mon Sep 17 00:00:00 2001 From: zhanghailiang Date: Thu, 31 Mar 2016 16:36:15 -0400 Subject: [PATCH] timer/mc146818rtc: fix timer drift in Windows OS while RTC rate converting frequently Signed-off-by: zhanghailiang --- hw/timer/mc146818rtc.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 2ac0fd3..e39d2da 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -79,6 +79,7 @@ typedef struct RTCState { /* periodic timer */ QEMUTimer *periodic_timer; int64_t next_periodic_time; + uint64_t last_periodic_time; /* update-ended timer */ QEMUTimer *update_timer; uint64_t next_alarm_time; @@ -152,7 +153,8 @@ static void rtc_coalesced_timer(void *opaque) static void periodic_timer_update(RTCState *s, int64_t current_time) { int period_code, period; - int64_t cur_clock, next_irq_clock; + int64_t cur_clock, next_irq_clock, pre_irq_clock; + bool change = false; period_code = s->cmos_data[RTC_REG_A] & 0x0f; if (period_code != 0 @@ -165,14 +167,28 @@ static void periodic_timer_update(RTCState *s, int64_t current_time) if (period != s->period) { s->irq_coalesced = (s->irq_coalesced * s->period) / period; DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced); + if (s->period && period) { + change = true; + } } s->period = period; #endif /* compute 32 khz clock */ cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND); + if (change) { + int offset = 0; - next_irq_clock = (cur_clock & ~(period - 1)) + period; + pre_irq_clock = muldiv64(s->last_periodic_time, RTC_CLOCK_RATE, + NANOSECONDS_PER_SECOND); + if ((cur_clock - pre_irq_clock) > period) { + offset = (cur_clock - pre_irq_clock) / period; + } + s->irq_coalesced += offset; + next_irq_clock = pre_irq_clock + (offset + 1) * period; + } else { + next_irq_clock = (cur_clock & ~(period - 1)) + period; + } s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND, RTC_CLOCK_RATE) + 1; timer_mod(s->periodic_timer, s->next_periodic_time); @@ -187,7 +203,9 @@ static void periodic_timer_update(RTCState *s, int64_t current_time) static void rtc_periodic_timer(void *opaque) { RTCState *s = opaque; - + int64_t next_periodic_time; + + next_periodic_time = s->next_periodic_time; periodic_timer_update(s, s->next_periodic_time); s->cmos_data[RTC_REG_C] |= REG_C_PF; if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { @@ -204,6 +222,7 @@ static void rtc_periodic_timer(void *opaque) DPRINTF_C("cmos: coalesced irqs increased to %d\n", s->irq_coalesced); } + s->last_periodic_time = next_periodic_time; } else #endif qemu_irq_raise(s->irq);