From patchwork Thu Dec 14 12:23:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gonglei (Arei)" X-Patchwork-Id: 10111947 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 7334D60327 for ; Thu, 14 Dec 2017 12:24:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 62F3529C0F for ; Thu, 14 Dec 2017 12:24:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 57FB729C2B; Thu, 14 Dec 2017 12:24:11 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 0E24729C0F for ; Thu, 14 Dec 2017 12:24:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751917AbdLNMX5 (ORCPT ); Thu, 14 Dec 2017 07:23:57 -0500 Received: from szxga06-in.huawei.com ([45.249.212.32]:35993 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1751719AbdLNMX5 (ORCPT ); Thu, 14 Dec 2017 07:23:57 -0500 Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 438A566042036; Thu, 14 Dec 2017 20:23:43 +0800 (CST) Received: from localhost (10.177.18.62) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.361.1; Thu, 14 Dec 2017 20:23:37 +0800 From: Gonglei To: , CC: , , , Gonglei Subject: [PATCH] KVM: x86: ioapic: Clear IRR for rtc bit when rtc EOI gotten Date: Thu, 14 Dec 2017 20:23:26 +0800 Message-ID: <1513254206-25344-1-git-send-email-arei.gonglei@huawei.com> X-Mailer: git-send-email 2.8.2.windows.1 MIME-Version: 1.0 X-Originating-IP: [10.177.18.62] X-CFilter-Loop: Reflected Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We hit a bug in our test while run PCMark 10 in a windows 7 VM, The VM got stuck and the wallclock was hang after several minutes running PCMark 10 in it. It is quite easily to reproduce the bug with the upstream KVM and Qemu. We found that KVM can not inject any RTC irq to VM after it was hang, it fails to Deliver irq in ioapic_set_irq() because RTC irq is still pending in ioapic->irr. static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq, int irq_level, bool line_status) { ... if (!irq_level) { ioapic->irr &= ~mask; ret = 1; goto out; } ... if ((edge && old_irr == ioapic->irr) || (!edge && entry.fields.remote_irr)) { ret = 0; goto out; } According to RTC spec, after RTC injects a High level irq, OS will read CMOS's register C to to clear the irq flag, and pull down the irq electric pin. For Qemu, we will emulate the reading operation in cmos_ioport_read(), but Guest OS will fire a write operation before to tell which register will be read after this write, where we use s->cmos_index to record the following register to read. But in our test, we found that there is a possible situation that Vcpu fails to read RTC_REG_C to clear irq, This could happens while two VCpus are writing/reading registers at the same time, for example, vcpu 0 is trying to read RTC_REG_C, so it write RTC_REG_C first, where the s->cmos_index will be RTC_REG_C, but before it tries to read register C, another vcpu1 is going to read RTC_YEAR, it changes s->cmos_index to RTC_YEAR by a writing action. The next operation of vcpu0 will be lead to read RTC_YEAR, In this case, we will miss calling qemu_irq_lower(s->irq) to clear the irq. After this, kvm will never inject RTC irq, and Windows VM will hang. Let's clear IRR of rtc when corresponding EOI is gotten to avoid the issue. Suggested-by: Paolo Bonzini Signed-off-by: Gonglei --- Thanks to Paolo provides a good solution. :) arch/x86/kvm/ioapic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 4e822ad..5022d63 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -160,6 +160,7 @@ static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu) { if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map)) { + ioapic->irr &= ~(1 << RTC_GSI); --ioapic->rtc_status.pending_eoi; rtc_status_pending_eoi_check_valid(ioapic); }