From patchwork Tue Jul 17 12:46:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 10529359 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 EF44860545 for ; Tue, 17 Jul 2018 12:46:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CF20628F40 for ; Tue, 17 Jul 2018 12:46:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C1DD028FF0; Tue, 17 Jul 2018 12:46:47 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4E90228FEE for ; Tue, 17 Jul 2018 12:46:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GTO1nuEeUuvghlyO1DoGhr4yvmap7u7jc+iKiO5XgIA=; b=qowYRCM8T4Hfm0 pc8D5F0ULLM0uwL8ow3zkFRzrmVS9fgx3AuzKaYWFVdIfx4A6jMlzx9POiAdC0HZYKnCcOwlG2AnE xom7i4mm9eHYJ+e/m3WnTs2jadY20J08EUXi2JWOZCkyfgFzT4zbXc7Y2utsPmHR5HOMa2ZbG8Z2A KTgaHD4BikwORAyFQr3JDwh7kCjdfkgayo01K1tyQsacE0CR7B40YROL1d/Zi1SvvB6jL0SMIslQy FK/FMm+VyZ4ChW4tNTyqdiKzMBxO+SxL2Kj7jGjayFdLFFF6SFMbSjXFz5rNBKzM4vaB4qAC1+iV1 gXRzbCP4QdbqrRIAvNlg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1ffPNM-0005ow-9n; Tue, 17 Jul 2018 12:46:44 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1ffPNJ-0005oD-Rd for linux-arm-kernel@lists.infradead.org; Tue, 17 Jul 2018 12:46:43 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5930218A; Tue, 17 Jul 2018 05:46:31 -0700 (PDT) Received: from localhost (e113682-lin.copenhagen.arm.com [10.32.144.41]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E0D513F5A0; Tue, 17 Jul 2018 05:46:30 -0700 (PDT) Date: Tue, 17 Jul 2018 14:46:29 +0200 From: Christoffer Dall To: Andre Przywara Subject: Re: [PATCH v2] kvm: arm/arm64: Fix emulated physical timer IRQ injection Message-ID: <20180717124629.GB30790@e113682-lin.lund.arm.com> References: <20180717095137.9620-1-andre.przywara@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20180717095137.9620-1-andre.przywara@arm.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180717_054641_907893_B11ECBFB X-CRM114-Status: GOOD ( 26.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Marc Zyngier , Stable , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP On Tue, Jul 17, 2018 at 10:51:37AM +0100, Andre Przywara wrote: > When KVM emulates a physical timer, we keep track of the interrupt > condition and try to inject an IRQ to the guest when needed. > This works if the timer expires when either the guest is running or KVM > does work on behalf of it (like handling a trap). > However when the guest's VCPU is not scheduled (for instance because > the guest issued a WFI instruction before), we miss injecting the interrupt > when the VCPU's state gets restored back in kvm_timer_vcpu_load(). > > Fix this by moving the interrupt injection check into the > phys_timer_emulate() function, so that all possible paths of execution > are covered. > > Cc: Stable # 4.15+ > Fixes: bbdd52cfcba29 ("KVM: arm/arm64: Avoid phys timer emulation in vcpu entry/exit") > Signed-off-by: Andre Przywara > --- > Changelog v1...v2: > - clear IRQ line *before* starting the soft timer > > virt/kvm/arm/arch_timer.c | 21 +++++++++++++-------- > 1 file changed, 13 insertions(+), 8 deletions(-) > > diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c > index bd3d57f40f1b..03a4ea776b85 100644 > --- a/virt/kvm/arm/arch_timer.c > +++ b/virt/kvm/arm/arch_timer.c > @@ -294,16 +294,25 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu) Please update the comment on this function as well. > struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; > struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); > > + /* If the timer cannot fire at all, then we don't need a soft timer. */ > + if (!kvm_timer_irq_can_fire(ptimer)) { > + soft_timer_cancel(&timer->phys_timer, NULL); > + kvm_timer_update_irq(vcpu, false, ptimer); > + return; > + } > + > /* > - * If the timer can fire now we have just raised the IRQ line and we > - * don't need to have a soft timer scheduled for the future. If the > - * timer cannot fire at all, then we also don't need a soft timer. > + * If the timer can fire now, we don't need to have a soft timer > + * scheduled for the future, as we also raise the IRQ line. > */ > - if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) { > + if (kvm_timer_should_fire(ptimer)) { > soft_timer_cancel(&timer->phys_timer, NULL); > + kvm_timer_update_irq(vcpu, true, ptimer); > + > return; > } > > + kvm_timer_update_irq(vcpu, false, ptimer); > soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer)); I find this overly complex. How about: > } > > @@ -316,7 +325,6 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu) > { > struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; > struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); > - struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); > bool level; > > if (unlikely(!timer->enabled)) > @@ -332,9 +340,6 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu) > level = kvm_timer_should_fire(vtimer); > kvm_timer_update_irq(vcpu, level, vtimer); > > - if (kvm_timer_should_fire(ptimer) != ptimer->irq.level) > - kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer); > - > phys_timer_emulate(vcpu); > } > Please also remove the comment in kvm_timer_vcpu_load() which indicates that the call to the function will only ever schedule a background timer. Thanks, -Christoffer diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index bd3d57f..b5dcfca 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -288,7 +288,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, } } -/* Schedule the background timer for the emulated timer. */ +/* Emulate the physical timer in software and update IRQ signal if needed */ static void phys_timer_emulate(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; @@ -299,12 +299,13 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu) * don't need to have a soft timer scheduled for the future. If the * timer cannot fire at all, then we also don't need a soft timer. */ - if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) { + if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) soft_timer_cancel(&timer->phys_timer, NULL); - return; - } + else + soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer)); - soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer)); + if (kvm_timer_should_fire(ptimer) != ptimer->irq.level) + kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer); } /*