From patchwork Wed Apr 12 09:51:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiao Guangrong X-Patchwork-Id: 749907 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3w2znb3CLcz9rxm for ; Wed, 12 Apr 2017 19:55:47 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gViUsf2w"; dkim-atps=neutral Received: from localhost ([::1]:43246 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cyF04-00081V-VL for incoming@patchwork.ozlabs.org; Wed, 12 Apr 2017 05:55:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51327) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cyEwQ-0005VI-KO for qemu-devel@nongnu.org; Wed, 12 Apr 2017 05:51:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cyEwP-0004ml-PM for qemu-devel@nongnu.org; Wed, 12 Apr 2017 05:51:58 -0400 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:36274) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cyEwP-0004mI-Ir for qemu-devel@nongnu.org; Wed, 12 Apr 2017 05:51:57 -0400 Received: by mail-pg0-x242.google.com with SMTP id 34so1371576pgx.3 for ; Wed, 12 Apr 2017 02:51:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zjIOylt3BTVARZNDEomO5jE6fTM+VBcKcS1uMPoF3c0=; b=gViUsf2w7YgyylISlnqSvdcNTI6iGR1nG6gSISmvLZwxA21yquchYmfmsOWPcqiTjR 4HD9AC+ufYzhdlQ3G4hZ/jzpQeNI22T3ihCw2nkJxLwL1oV9bBjM37dUkWGAF4+LXtCT yRlR9VUC6xj7OU4JCi1XQBRekOe7+WRIQbMgrqjfYAoBJ3ZCPFAzJBWUJZyprkvn8ro9 VmNAfK3n3xk5tshWfiEsPLrf9jhKO0lFcK0mdvKn28pfGInCjtEcE8TQMd2vTtcbmDLU rud/wr4hI5wOLDP9GTbWH0RxLVsmRA3SiTbtCAMhlQz7KPyKpUlZdRWdUC7Z0p9Vb+AN uIVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zjIOylt3BTVARZNDEomO5jE6fTM+VBcKcS1uMPoF3c0=; b=NcI7kn9jvvxCuUVDReQn6CCIdSq99t3Q+jVpMX6ixNsT739rMUdULosy8DSU5GLPEr FnoX9BCm9AIpiRomOH1r7sMwvafzdPMWwxc0RFd3KR7aCiGc8TNMQorwMLOy3qeR67ZS 6M13GM4Bg/YQC3piAW9bu3/DRRNX5BqY8uJdiwz1Y7oCt7Jg31k3RyiEPPP34P4yFOjT WwQrIVqiue+tUJe4JpDJHLkGL4ZHg4VCX3O29+FWrZ9h2vX+xZOcfZwGF+de7TDDv6XT TbglqNTvYK6rcGgm0ohvx4hInyqLl+jSRFZHKj1E+uSlgy1GCjBIt7QO3V70bv5eFdMl H7pQ== X-Gm-Message-State: AN3rC/5B/Y5LkEUPnl8/IRZtoGZswRTyNgxFjco7r5fIIvk5JQgJs7djLcZTSUQNXZxt8w== X-Received: by 10.84.222.140 with SMTP id x12mr34786216pls.36.1491990716635; Wed, 12 Apr 2017 02:51:56 -0700 (PDT) Received: from eric.tencent.com ([103.7.29.8]) by smtp.gmail.com with ESMTPSA id 4sm35445749pff.17.2017.04.12.02.51.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Apr 2017 02:51:56 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Wed, 12 Apr 2017 17:51:08 +0800 Message-Id: <20170412095111.11728-3-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170412095111.11728-1-xiaoguangrong@tencent.com> References: <20170412095111.11728-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PATCH 2/5] mc146818rtc: fix clock lost after scaling coalesced irq X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Xiao Guangrong , yunfangtai@tencent.com, qemu-devel@nongnu.org, kvm@vger.kernel.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Xiao Guangrong If the period is changed by re-configuring RegA, the coalesced irq will be scaled to reflect the new period, however, it calculates the new interrupt number like this: s->irq_coalesced = (s->irq_coalesced * s->period) / period; There are some clocks will be lost if they are not enough to be squeezed to a single new period that will cause the VM clock slower In order to fix the issue, we calculate the interrupt window based on the precise clock rather than period, then the clocks lost during period is scaled can be compensated properly Signed-off-by: Xiao Guangrong --- hw/timer/mc146818rtc.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 749e206..649678c 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -146,23 +146,46 @@ static void rtc_coalesced_timer(void *opaque) } #endif +static int period_code_to_clock(int period_code) +{ + /* periodic timer is disabled. */ + if (!period_code) { + return 0; + } + + if (period_code <= 2) { + period_code += 7; + } + + /* period in 32 Khz cycles */ + return 1 << (period_code - 1); +} + /* handle periodic timer */ 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, lost_clock = 0; period_code = s->cmos_data[RTC_REG_A] & 0x0f; if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) { - if (period_code <= 2) - period_code += 7; - /* period in 32 Khz cycles */ - period = 1 << (period_code - 1); + period = period_code_to_clock(period_code); #ifdef TARGET_I386 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); + int current_irq_coalesced = s->irq_coalesced; + + s->irq_coalesced = (current_irq_coalesced * s->period) / period; + + /* + * calculate the lost clock after it is scaled which should be + * compensated in the next interrupt. + */ + lost_clock += current_irq_coalesced * s->period - + s->irq_coalesced * period; + DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, %ld clocks " + "are compensated.\n", + current_irq_coalesced, s->irq_coalesced, lost_clock); } s->period = period; #endif @@ -170,7 +193,7 @@ static void periodic_timer_update(RTCState *s, int64_t current_time) cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND); - next_irq_clock = (cur_clock & ~(period - 1)) + period; + next_irq_clock = cur_clock + period - lost_clock; s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND, RTC_CLOCK_RATE) + 1; timer_mod(s->periodic_timer, s->next_periodic_time);