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: 9676921 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BF11760382 for ; Wed, 12 Apr 2017 09:52:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AFE502855A for ; Wed, 12 Apr 2017 09:52:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A2B4E285D3; Wed, 12 Apr 2017 09:52:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AA742855A for ; Wed, 12 Apr 2017 09:52:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752319AbdDLJwB (ORCPT ); Wed, 12 Apr 2017 05:52:01 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:34823 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752772AbdDLJv5 (ORCPT ); Wed, 12 Apr 2017 05:51:57 -0400 Received: by mail-pg0-f65.google.com with SMTP id g2so4225576pge.2 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=DVkonGLzYmd9313WnCI+qortno3MlIhs11xTu/FPVhtAQimG7MPPS0FhoxD+RUHyEn wPxcLPuWC/TluFY1jIBSmYjLZeLhG05HVrFlLew1DKTigMLl4ghUCJ1YzY8Nd6DucDhN WAS8mGP1kHgRTyY4pKo4BHonFhMqgTnNV1rST/XUBEMAPwDScdP3ENLT6cnD+N+nKR87 RQVUgMVx2kSMynRFhP7ZpKAzj8FTN/ndpcoeaE7s8uDwzq7f9Ms3szVl7/OFo6WOBSeT kQtkCFyUSw3ECF3gzzNAB34hbliY5S8FBHrtynYmTYzBkIaGW7voA+m0vrG6gh3NBxot 3VNA== X-Gm-Message-State: AN3rC/6oOjfZfB7+9y904K38/h5E4Ivs59SWpKVb0XAV2a7qTPCiZc3wllPfpZ7t3Or1HA== 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 Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, yunfangtai@tencent.com, Xiao Guangrong Subject: [PATCH 2/5] mc146818rtc: fix clock lost after scaling coalesced irq 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> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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);