From patchwork Thu Jan 8 10:45:33 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sheng Yang X-Patchwork-Id: 1341 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 n08AgA1O019956 for ; Thu, 8 Jan 2009 02:42:12 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753494AbZAHKpp (ORCPT ); Thu, 8 Jan 2009 05:45:45 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754417AbZAHKpp (ORCPT ); Thu, 8 Jan 2009 05:45:45 -0500 Received: from mga09.intel.com ([134.134.136.24]:21680 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753494AbZAHKpj (ORCPT ); Thu, 8 Jan 2009 05:45:39 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 08 Jan 2009 02:37:37 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.37,233,1231142400"; d="scan'208";a="376685466" Received: from syang10-desktop.sh.intel.com (HELO syang10-desktop) ([10.239.13.176]) by orsmga002.jf.intel.com with ESMTP; 08 Jan 2009 02:44:05 -0800 Received: from yasker by syang10-desktop with local (Exim 4.69) (envelope-from ) id 1LKsON-0000eH-LB; Thu, 08 Jan 2009 18:45:35 +0800 From: Sheng Yang To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Sheng Yang Subject: [PATCH 5/7] KVM: Merge MSI handling to kvm_set_irq Date: Thu, 8 Jan 2009 18:45:33 +0800 Message-Id: <1231411535-2461-6-git-send-email-sheng@linux.intel.com> X-Mailer: git-send-email 1.5.6.3 In-Reply-To: <1231411535-2461-1-git-send-email-sheng@linux.intel.com> References: <1231411535-2461-1-git-send-email-sheng@linux.intel.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Using kvm_set_irq to handle all interrupt injection. Signed-off-by: Sheng Yang --- include/linux/kvm_host.h | 2 +- virt/kvm/irq_comm.c | 79 +++++++++++++++++++++++++++++++++++++++++++-- virt/kvm/kvm_main.c | 79 +++------------------------------------------- 3 files changed, 81 insertions(+), 79 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index eab9588..bfdaab9 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -351,7 +351,7 @@ struct kvm_gsi_route_entry { struct hlist_node link; }; -void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); +void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level); void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); void kvm_register_irq_ack_notifier(struct kvm *kvm, struct kvm_irq_ack_notifier *kian); diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index f8b22a1..e6ce472 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -24,10 +24,81 @@ #include "ioapic.h" +#ifdef CONFIG_X86 +#include +#endif + +static void gsi_dispatch(struct kvm *kvm, u32 gsi) +{ + int vcpu_id; + struct kvm_vcpu *vcpu; + struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); + struct kvm_gsi_route_entry *gsi_entry; + int dest_id, vector, dest_mode, trig_mode, delivery_mode; + u32 deliver_bitmask; + + BUG_ON(!ioapic); + + gsi_entry = kvm_find_gsi_route_entry(kvm, gsi); + if (!gsi_entry) { + printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n"); + return; + } + +#ifdef CONFIG_X86 + if (gsi_entry->type & KVM_GSI_ROUTE_MSI) { + dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK) + >> MSI_ADDR_DEST_ID_SHIFT; + vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK) + >> MSI_DATA_VECTOR_SHIFT; + dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, + (unsigned long *)&gsi_entry->msi.address_lo); + trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, + (unsigned long *)&gsi_entry->msi.data); + delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT, + (unsigned long *)&gsi_entry->msi.data); + deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, + dest_id, dest_mode); + /* IOAPIC delivery mode value is the same as MSI here */ + switch (delivery_mode) { + case IOAPIC_LOWEST_PRIORITY: + vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, + deliver_bitmask); + if (vcpu != NULL) + kvm_apic_set_irq(vcpu, vector, trig_mode); + else + printk(KERN_INFO + "kvm: null lowest priority vcpu!\n"); + break; + case IOAPIC_FIXED: + for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { + if (!(deliver_bitmask & (1 << vcpu_id))) + continue; + deliver_bitmask &= ~(1 << vcpu_id); + vcpu = ioapic->kvm->vcpus[vcpu_id]; + if (vcpu) + kvm_apic_set_irq(vcpu, vector, + trig_mode); + } + break; + default: + break; + } + } +#endif /* CONFIG_X86 */ +} + /* This should be called with the kvm->lock mutex held */ -void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) +void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level) { - unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; + unsigned long *irq_state; + + if (gsi & KVM_GSI_ROUTE_MASK) { + gsi_dispatch(kvm, gsi); + return; + } + + irq_state = (unsigned long *)&kvm->arch.irq_states[gsi]; /* Logical OR for level trig interrupt */ if (level) @@ -39,9 +110,9 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) * IOAPIC. So set the bit in both. The guest will ignore * writes to the unused one. */ - kvm_ioapic_set_irq(ioapic_irqchip(kvm), irq, !!(*irq_state)); + kvm_ioapic_set_irq(ioapic_irqchip(kvm), gsi, !!(*irq_state)); #ifdef CONFIG_X86 - kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state)); + kvm_pic_set_irq(pic_irqchip(kvm), gsi, !!(*irq_state)); #endif } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fb2d639..d293714 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -47,10 +47,6 @@ #include #include -#ifdef CONFIG_X86 -#include -#endif - #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET #include "coalesced_mmio.h" #endif @@ -85,69 +81,6 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, static bool kvm_rebooting; #ifdef KVM_CAP_DEVICE_ASSIGNMENT - -#ifdef CONFIG_X86 -static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) -{ - int vcpu_id; - struct kvm_vcpu *vcpu; - struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm); - struct kvm_gsi_route_entry *gsi_entry; - int dest_id, vector, dest_mode, trig_mode, delivery_mode; - u32 deliver_bitmask; - - BUG_ON(!ioapic); - - gsi_entry = kvm_find_gsi_route_entry(dev->kvm, gsi); - if (!gsi_entry) { - printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n"); - return; - } - - if (gsi_entry->type & KVM_GSI_ROUTE_MSI) { - dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK) - >> MSI_ADDR_DEST_ID_SHIFT; - vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK) - >> MSI_DATA_VECTOR_SHIFT; - dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, - (unsigned long *)&gsi_entry->msi.address_lo); - trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, - (unsigned long *)&gsi_entry->msi.data); - delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT, - (unsigned long *)&gsi_entry->msi.data); - deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, - dest_id, dest_mode); - /* IOAPIC delivery mode value is the same as MSI here */ - switch (delivery_mode) { - case IOAPIC_LOWEST_PRIORITY: - vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, - deliver_bitmask); - if (vcpu != NULL) - kvm_apic_set_irq(vcpu, vector, trig_mode); - else - printk(KERN_INFO - "kvm: null lowest priority vcpu!\n"); - break; - case IOAPIC_FIXED: - for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { - if (!(deliver_bitmask & (1 << vcpu_id))) - continue; - deliver_bitmask &= ~(1 << vcpu_id); - vcpu = ioapic->kvm->vcpus[vcpu_id]; - if (vcpu) - kvm_apic_set_irq(vcpu, vector, - trig_mode); - } - break; - default: - break; - } - } -} -#else -static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) {} -#endif - static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, int assigned_dev_id) { @@ -174,13 +107,11 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) * finer-grained lock, update this */ mutex_lock(&assigned_dev->kvm->lock); - if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_INTX) - kvm_set_irq(assigned_dev->kvm, - assigned_dev->irq_source_id, - assigned_dev->guest_irq, 1); - else if (assigned_dev->irq_requested_type & - KVM_ASSIGNED_DEV_GUEST_MSI) { - assigned_device_msi_dispatch(assigned_dev, assigned_dev->guest_irq); + + kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id, + assigned_dev->guest_irq, 1); + + if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_MSI) { enable_irq(assigned_dev->host_irq); assigned_dev->host_irq_disabled = false; }