From patchwork Fri May 22 08:57:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Luis Henriques X-Patchwork-Id: 475432 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 94A851402B9; Fri, 22 May 2015 19:03:40 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1Yviri-0008Ln-3d; Fri, 22 May 2015 09:03:38 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1Yvinw-0005xv-BF for kernel-team@lists.ubuntu.com; Fri, 22 May 2015 08:59:44 +0000 Received: from [10.172.192.212] (helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1Yvinw-0004IE-5u; Fri, 22 May 2015 08:59:44 +0000 From: Luis Henriques To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Subject: [PATCH 3.16.y-ckt 071/129] arm/arm64: KVM: Keep elrsr/aisr in sync with software model Date: Fri, 22 May 2015 09:57:36 +0100 Message-Id: <1432285114-9254-72-git-send-email-luis.henriques@canonical.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1432285114-9254-1-git-send-email-luis.henriques@canonical.com> References: <1432285114-9254-1-git-send-email-luis.henriques@canonical.com> MIME-Version: 1.0 X-Extended-Stable: 3.16 Cc: Marc Zyngier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Shannon Zhao , Christoffer Dall X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com 3.16.7-ckt12 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Christoffer Dall commit ae705930fca6322600690df9dc1c7d0516145a93 upstream. There is an interesting bug in the vgic code, which manifests itself when the KVM run loop has a signal pending or needs a vmid generation rollover after having disabled interrupts but before actually switching to the guest. In this case, we flush the vgic as usual, but we sync back the vgic state and exit to userspace before entering the guest. The consequence is that we will be syncing the list registers back to the software model using the GICH_ELRSR and GICH_EISR from the last execution of the guest, potentially overwriting a list register containing an interrupt. This showed up during migration testing where we would capture a state where the VM has masked the arch timer but there were no interrupts, resulting in a hung test. Cc: Marc Zyngier Reported-by: Alex Bennee Signed-off-by: Christoffer Dall Signed-off-by: Alex Bennée Acked-by: Marc Zyngier Signed-off-by: Christoffer Dall Signed-off-by: Shannon Zhao [ luis: backported to 3.16: used shannon's backport to 3.14 ] Signed-off-by: Luis Henriques --- virt/kvm/arm/vgic.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 7f59965d4164..24ac123f4ad8 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -1042,6 +1042,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) lr, irq, vgic_cpu->vgic_lr[lr]); BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; + __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); return true; } @@ -1055,6 +1056,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq); vgic_cpu->vgic_irq_lr_map[irq] = lr; set_bit(lr, vgic_cpu->lr_used); + __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); if (!vgic_irq_is_edge(vcpu, irq)) vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; @@ -1209,6 +1211,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) if (vgic_cpu->vgic_misr & GICH_MISR_U) vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE; + /* + * In the next iterations of the vcpu loop, if we sync the vgic state + * after flushing it, but before entering the guest (this happens for + * pending signals and vmid rollovers), then make sure we don't pick + * up any old maintenance interrupts here. + */ + memset(vgic_cpu->vgic_eisr, 0, sizeof(vgic_cpu->vgic_eisr[0]) * 2); + return level_pending; }