From: Feng Wu <feng.wu@intel.com> To: tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com, x86@kernel.org, gleb@kernel.org, pbonzini@redhat.com, dwmw2@infradead.org, joro@8bytes.org, alex.williamson@redhat.com, jiang.liu@linux.intel.com Cc: linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, kvm@vger.kernel.org, Feng Wu <feng.wu@intel.com> Subject: [v2 18/25] KVM: kvm-vfio: implement the VFIO skeleton for VT-d Posted-Interrupts Date: Wed, 3 Dec 2014 15:39:47 +0800 [thread overview] Message-ID: <1417592394-24343-19-git-send-email-feng.wu@intel.com> (raw) In-Reply-To: <1417592394-24343-1-git-send-email-feng.wu@intel.com> This patch adds the kvm-vfio interface for VT-d Posted-Interrrupts. When guests updates MSI/MSI-x information for an assigned-device, QEMU will use KVM_DEV_VFIO_DEVICE_POSTING_IRQ attribute to setup IRTE for VT-d PI. This patch implement this IRQ attribute. Signed-off-by: Feng Wu <feng.wu@intel.com> --- include/linux/kvm_host.h | 19 ++++++++ virt/kvm/vfio.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 0 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5cd4420..8d06678 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1134,6 +1134,25 @@ static inline int kvm_arch_vfio_set_forward(struct kvm_fwd_irq *fwd_irq, } #endif +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING +/* + * kvm_arch_vfio_update_pi_irte - set IRTE for Posted-Interrupts + * + * @kvm: kvm + * @host_irq: host irq of the interrupt + * @guest_irq: gsi of the interrupt + * returns 0 on success, < 0 on failure + */ +int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq); +#else +static int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq) +{ + return 0; +} +#endif + #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 6bc7001..5e5515f 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -446,6 +446,99 @@ out: return ret; } +static int kvm_vfio_pci_get_irq_count(struct pci_dev *pdev, int irq_type) +{ + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { + u8 pin; + + pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (pin) + return 1; + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) + return pci_msi_vec_count(pdev); + else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) + return pci_msix_vec_count(pdev); + + return 0; +} + +static int kvm_vfio_set_pi(struct kvm_device *kdev, int32_t __user *argp) +{ + struct kvm_vfio_dev_irq pi_info; + uint32_t *gsi; + unsigned long minsz; + struct vfio_device *vdev; + struct msi_desc *entry; + struct device *dev; + struct pci_dev *pdev; + int i, max, ret; + + minsz = offsetofend(struct kvm_vfio_dev_irq, count); + + if (copy_from_user(&pi_info, (void __user *)argp, minsz)) + return -EFAULT; + + if (pi_info.argsz < minsz || pi_info.index >= VFIO_PCI_NUM_IRQS) + return -EINVAL; + + vdev = kvm_vfio_get_vfio_device(pi_info.fd); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + dev = kvm_vfio_external_base_device(vdev); + if (!dev || !dev_is_pci(dev)) { + ret = -EFAULT; + goto put_vfio_device; + } + + pdev = to_pci_dev(dev); + + max = kvm_vfio_pci_get_irq_count(pdev, pi_info.index); + if (max <= 0) { + ret = -EFAULT; + goto put_vfio_device; + } + + if (pi_info.argsz - minsz < pi_info.count * sizeof(int) || + pi_info.start >= max || pi_info.start + pi_info.count > max) { + ret = -EINVAL; + goto put_vfio_device; + } + + gsi = memdup_user((void __user *)((unsigned long)argp + minsz), + pi_info.count * sizeof(int)); + if (IS_ERR(gsi)) { + ret = PTR_ERR(gsi); + goto put_vfio_device; + } + +#ifdef CONFIG_PCI_MSI + for (i = 0; i < pi_info.count; i++) { + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->msi_attrib.entry_nr != pi_info.start+i) + continue; + + ret = kvm_arch_vfio_update_pi_irte(kdev->kvm, + entry->irq, + gsi[i]); + if (ret) { + ret = -EFAULT; + goto free_gsi; + } + } + } +#endif + + ret = 0; + +free_gsi: + kfree(gsi); + +put_vfio_device: + kvm_vfio_put_vfio_device(vdev); + return ret; +} + static int kvm_vfio_set_device(struct kvm_device *kdev, long attr, u64 arg) { int32_t __user *argp = (int32_t __user *)(unsigned long)arg; @@ -456,6 +549,11 @@ static int kvm_vfio_set_device(struct kvm_device *kdev, long attr, u64 arg) case KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ: ret = kvm_vfio_control_irq_forward(kdev, attr, argp); break; +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING + case KVM_DEV_VFIO_DEVICE_POSTING_IRQ: + ret = kvm_vfio_set_pi(kdev, argp); + break; +#endif default: ret = -ENXIO; } @@ -511,6 +609,11 @@ static int kvm_vfio_has_attr(struct kvm_device *dev, case KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ: return 0; #endif +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING + case KVM_DEV_VFIO_DEVICE_POSTING_IRQ: + return 0; +#endif + } break; } -- 1.7.1
WARNING: multiple messages have this Message-ID (diff)
From: Feng Wu <feng.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> To: tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org, mingo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org, x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, gleb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, pbonzini-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org, joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org, alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Subject: [v2 18/25] KVM: kvm-vfio: implement the VFIO skeleton for VT-d Posted-Interrupts Date: Wed, 3 Dec 2014 15:39:47 +0800 [thread overview] Message-ID: <1417592394-24343-19-git-send-email-feng.wu@intel.com> (raw) In-Reply-To: <1417592394-24343-1-git-send-email-feng.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> This patch adds the kvm-vfio interface for VT-d Posted-Interrrupts. When guests updates MSI/MSI-x information for an assigned-device, QEMU will use KVM_DEV_VFIO_DEVICE_POSTING_IRQ attribute to setup IRTE for VT-d PI. This patch implement this IRQ attribute. Signed-off-by: Feng Wu <feng.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> --- include/linux/kvm_host.h | 19 ++++++++ virt/kvm/vfio.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 0 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5cd4420..8d06678 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1134,6 +1134,25 @@ static inline int kvm_arch_vfio_set_forward(struct kvm_fwd_irq *fwd_irq, } #endif +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING +/* + * kvm_arch_vfio_update_pi_irte - set IRTE for Posted-Interrupts + * + * @kvm: kvm + * @host_irq: host irq of the interrupt + * @guest_irq: gsi of the interrupt + * returns 0 on success, < 0 on failure + */ +int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq); +#else +static int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq) +{ + return 0; +} +#endif + #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 6bc7001..5e5515f 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -446,6 +446,99 @@ out: return ret; } +static int kvm_vfio_pci_get_irq_count(struct pci_dev *pdev, int irq_type) +{ + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { + u8 pin; + + pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (pin) + return 1; + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) + return pci_msi_vec_count(pdev); + else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) + return pci_msix_vec_count(pdev); + + return 0; +} + +static int kvm_vfio_set_pi(struct kvm_device *kdev, int32_t __user *argp) +{ + struct kvm_vfio_dev_irq pi_info; + uint32_t *gsi; + unsigned long minsz; + struct vfio_device *vdev; + struct msi_desc *entry; + struct device *dev; + struct pci_dev *pdev; + int i, max, ret; + + minsz = offsetofend(struct kvm_vfio_dev_irq, count); + + if (copy_from_user(&pi_info, (void __user *)argp, minsz)) + return -EFAULT; + + if (pi_info.argsz < minsz || pi_info.index >= VFIO_PCI_NUM_IRQS) + return -EINVAL; + + vdev = kvm_vfio_get_vfio_device(pi_info.fd); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + dev = kvm_vfio_external_base_device(vdev); + if (!dev || !dev_is_pci(dev)) { + ret = -EFAULT; + goto put_vfio_device; + } + + pdev = to_pci_dev(dev); + + max = kvm_vfio_pci_get_irq_count(pdev, pi_info.index); + if (max <= 0) { + ret = -EFAULT; + goto put_vfio_device; + } + + if (pi_info.argsz - minsz < pi_info.count * sizeof(int) || + pi_info.start >= max || pi_info.start + pi_info.count > max) { + ret = -EINVAL; + goto put_vfio_device; + } + + gsi = memdup_user((void __user *)((unsigned long)argp + minsz), + pi_info.count * sizeof(int)); + if (IS_ERR(gsi)) { + ret = PTR_ERR(gsi); + goto put_vfio_device; + } + +#ifdef CONFIG_PCI_MSI + for (i = 0; i < pi_info.count; i++) { + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->msi_attrib.entry_nr != pi_info.start+i) + continue; + + ret = kvm_arch_vfio_update_pi_irte(kdev->kvm, + entry->irq, + gsi[i]); + if (ret) { + ret = -EFAULT; + goto free_gsi; + } + } + } +#endif + + ret = 0; + +free_gsi: + kfree(gsi); + +put_vfio_device: + kvm_vfio_put_vfio_device(vdev); + return ret; +} + static int kvm_vfio_set_device(struct kvm_device *kdev, long attr, u64 arg) { int32_t __user *argp = (int32_t __user *)(unsigned long)arg; @@ -456,6 +549,11 @@ static int kvm_vfio_set_device(struct kvm_device *kdev, long attr, u64 arg) case KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ: ret = kvm_vfio_control_irq_forward(kdev, attr, argp); break; +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING + case KVM_DEV_VFIO_DEVICE_POSTING_IRQ: + ret = kvm_vfio_set_pi(kdev, argp); + break; +#endif default: ret = -ENXIO; } @@ -511,6 +609,11 @@ static int kvm_vfio_has_attr(struct kvm_device *dev, case KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ: return 0; #endif +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING + case KVM_DEV_VFIO_DEVICE_POSTING_IRQ: + return 0; +#endif + } break; } -- 1.7.1
next prev parent reply other threads:[~2014-12-03 7:50 UTC|newest] Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top 2014-12-03 7:39 [v2 00/25] Add VT-d Posted-Interrupts support Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 01/25] genirq: Introduce irq_set_vcpu_affinity() to target an interrupt to a VCPU Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 02/25] iommu: Add new member capability to struct irq_remap_ops Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 03/25] iommu, x86: Define new irte structure for VT-d Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 04/25] iommu, x86: Implement irq_set_vcpu_affinity for intel_ir_chip Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 05/25] x86, irq: Implement irq_set_vcpu_affinity for pci_msi_ir_controller Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 06/25] iommu, x86: No need to migrating irq for VT-d Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 07/25] iommu, x86: Add cap_pi_support() to detect VT-d PI capability Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 08/25] iommu, x86: Add intel_irq_remapping_capability() for Intel Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 09/25] iommu, x86: define irq_remapping_cap() Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 10/25] KVM: change struct pi_desc for VT-d Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 11/25] KVM: Add some helper functions for Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 12/25] KVM: Initialize VT-d Posted-Interrupts Descriptor Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 13/25] KVM: Define a new interface kvm_find_dest_vcpu() for VT-d PI Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 14/25] KVM: Get Posted-Interrupts descriptor address from struct kvm_vcpu Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 15/25] KVM: Make struct kvm_irq_routing_table accessible Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 16/25] KVM: make kvm_set_msi_irq() public Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 17/25] KVM: kvm-vfio: User API for VT-d Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-04 14:04 ` Eric Auger 2014-12-04 14:04 ` Eric Auger 2014-12-08 4:58 ` Wu, Feng 2014-12-08 4:58 ` Wu, Feng 2014-12-08 5:21 ` Alex Williamson 2014-12-08 5:21 ` Alex Williamson 2014-12-09 11:38 ` Wu, Feng 2014-12-09 11:38 ` Wu, Feng 2014-12-11 5:55 ` Wu, Feng 2014-12-11 5:55 ` Wu, Feng 2014-12-11 15:45 ` Alex Williamson 2014-12-11 15:45 ` Alex Williamson 2014-12-03 7:39 ` Feng Wu [this message] 2014-12-03 7:39 ` [v2 18/25] KVM: kvm-vfio: implement the VFIO skeleton " Feng Wu 2014-12-04 15:35 ` Eric Auger 2014-12-04 15:35 ` Eric Auger 2014-12-08 4:58 ` Wu, Feng 2014-12-08 4:58 ` Wu, Feng 2014-12-08 5:12 ` Alex Williamson 2014-12-08 5:12 ` Alex Williamson 2014-12-08 10:15 ` Eric Auger 2014-12-08 10:15 ` Eric Auger 2014-12-09 11:51 ` Wu, Feng 2014-12-09 11:51 ` Wu, Feng 2014-12-03 7:39 ` [v2 19/25] KVM: x86: kvm-vfio: VT-d posted-interrupts setup Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 20/25] x86, irq: Define a global vector for VT-d Posted-Interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 21/25] KVM: Update Posted-Interrupts descriptor during vCPU scheduling Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 22/25] KVM: Change NDST field after " Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 23/25] KVM: Add the handler for Wake-up Vector Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 24/25] KVM: Suppress posted-interrupt when 'SN' is set Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-03 7:39 ` [v2 25/25] iommu/vt-d: Add a command line parameter for VT-d posted-interrupts Feng Wu 2014-12-03 7:39 ` Feng Wu 2014-12-08 13:36 ` [v2 00/25] Add VT-d Posted-Interrupts support Wu, Feng 2014-12-08 13:36 ` Wu, Feng
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1417592394-24343-19-git-send-email-feng.wu@intel.com \ --to=feng.wu@intel.com \ --cc=alex.williamson@redhat.com \ --cc=dwmw2@infradead.org \ --cc=gleb@kernel.org \ --cc=hpa@zytor.com \ --cc=iommu@lists.linux-foundation.org \ --cc=jiang.liu@linux.intel.com \ --cc=joro@8bytes.org \ --cc=kvm@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mingo@redhat.com \ --cc=pbonzini@redhat.com \ --cc=tglx@linutronix.de \ --cc=x86@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.