From patchwork Sun Jul 5 13:46:48 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 34137 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n65DktCC006055 for ; Sun, 5 Jul 2009 13:46:55 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752905AbZGENqs (ORCPT ); Sun, 5 Jul 2009 09:46:48 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752780AbZGENqs (ORCPT ); Sun, 5 Jul 2009 09:46:48 -0400 Received: from mx2.redhat.com ([66.187.237.31]:50885 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752542AbZGENqr (ORCPT ); Sun, 5 Jul 2009 09:46:47 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n65DkpRx005037 for ; Sun, 5 Jul 2009 09:46:51 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n65DkoK2023055; Sun, 5 Jul 2009 09:46:50 -0400 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n65Dkn3F023709; Sun, 5 Jul 2009 09:46:49 -0400 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id A054E18D479; Sun, 5 Jul 2009 16:46:48 +0300 (IDT) Date: Sun, 5 Jul 2009 16:46:48 +0300 From: Gleb Natapov To: avi@redhat.com Cc: kvm@vger.kernel.org Subject: [PATCH] avoid redeliver of edge interrupt before next edge Message-ID: <20090705134648.GI881@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The check for an edge is broken in current ioapic code. ioapic->irr is cleared on each edge interrupt by ioapic_service() and this makes old_irr != ioapic->irr condition in kvm_ioapic_set_irq() to be always true. The patch fixes the code to properly recognise edge. Signed-off-by: Gleb Natapov --- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 124ecf7..74c4b5f 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -95,8 +95,6 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) pent->fields.remote_irr = 1; } - if (!pent->fields.trig_mode) - ioapic->irr &= ~(1 << idx); return injected; } @@ -118,28 +116,34 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) case IOAPIC_REG_ARB_ID: break; - default: + default: { + union kvm_ioapic_redirect_entry *e; + index = (ioapic->ioregsel - 0x10) >> 1; ioapic_debug("change redir index %x val %x\n", index, val); if (index >= IOAPIC_NUM_PINS) return; - mask_before = ioapic->redirtbl[index].fields.mask; + + e = &ioapic->redirtbl[index]; + mask_before = e->fields.mask; if (ioapic->ioregsel & 1) { - ioapic->redirtbl[index].bits &= 0xffffffff; - ioapic->redirtbl[index].bits |= (u64) val << 32; + e->bits &= 0xffffffff; + e->bits |= (u64) val << 32; } else { - ioapic->redirtbl[index].bits &= ~0xffffffffULL; - ioapic->redirtbl[index].bits |= (u32) val; - ioapic->redirtbl[index].fields.remote_irr = 0; + e->bits &= ~0xffffffffULL; + e->bits |= (u32) val; + e->fields.remote_irr = 0; } - mask_after = ioapic->redirtbl[index].fields.mask; + mask_after = e->fields.mask; if (mask_before != mask_after) kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); - if (ioapic->irr & (1 << index)) + if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG && + (ioapic->irr & (1 << index))) ioapic_service(ioapic, index); break; } + } } static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) @@ -186,9 +190,10 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) if (!level) ioapic->irr &= ~mask; else { + int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG); ioapic->irr |= mask; - if ((!entry.fields.trig_mode && old_irr != ioapic->irr) - || !entry.fields.remote_irr) + if ((edge && old_irr != ioapic->irr) || + (!edge && !entry.fields.remote_irr)) ret = ioapic_service(ioapic, irq); } }