All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@redhat.com>
To: Feng Wu <feng.wu@intel.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	pbonzini@redhat.com, mtosatti@redhat.com, eric.auger@linaro.org
Subject: Re: [v4 12/16] KVM: kvm-vfio: implement the VFIO skeleton for VT-d Posted-Interrupts
Date: Thu, 11 Jun 2015 11:15:07 -0600	[thread overview]
Message-ID: <1434042907.4927.194.camel@redhat.com> (raw)
In-Reply-To: <1434019912-15423-13-git-send-email-feng.wu@intel.com>

On Thu, 2015-06-11 at 18:51 +0800, Feng Wu wrote:
> This patch adds the kvm-vfio interface for VT-d Posted-Interrupts.
> When guests update MSI/MSI-x information for an assigned-device,
> QEMU will use KVM_DEV_VFIO_DEVICE_POST_IRQ attribute to setup
> IRTE for VT-d PI. Userspace program can also use
> KVM_DEV_VFIO_DEVICE_UNPOST_IRQ to change back to irq remapping mode.
> This patch implements these IRQ attributes.
> 
> Signed-off-by: Feng Wu <feng.wu@intel.com>
> ---
>  include/linux/kvm_host.h |  22 +++++++++
>  virt/kvm/vfio.c          | 126 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 148 insertions(+)
> 
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index f591f7c..69f8711 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1073,6 +1073,28 @@ extern struct kvm_device_ops kvm_xics_ops;
>  extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
>  extern struct kvm_device_ops kvm_arm_vgic_v3_ops;
>  
> +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POST
> +/*
> + * 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
> + * @set: set or unset PI
> + * 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, bool set);
> +#else
> +static inline int kvm_arch_vfio_update_pi_irte(struct kvm *kvm,
> +					       unsigned int host_irq,
> +					       uint32_t guest_irq,
> +					       bool set)
> +{
> +	return 0;
> +}

The code below can't get to this function without
__KVM_HAVE_ARCH_KVM_VFIO_POST, but this seems like it should return an
error if not implemented.

> +#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 80a45e4..547fc51 100644
> --- a/virt/kvm/vfio.c
> +++ b/virt/kvm/vfio.c
> @@ -18,6 +18,7 @@
>  #include <linux/slab.h>
>  #include <linux/uaccess.h>
>  #include <linux/vfio.h>
> +#include <asm/irq_remapping.h>

This only exists on x86.   Are we also getting lucky with some of the
include chains that give us the PCI related defines?  It looks like
we're implicitly assuming CONFIG_PCI

>  #include "vfio.h"
>  
>  struct kvm_vfio_group {
> @@ -276,12 +277,128 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
>  	return -ENXIO;
>  }
>  
> +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_control_pi(struct kvm_device *kdev,
> +			       int32_t __user *argp, bool set)
> +{
> +	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;

Could we also abort on pi_info.count == 0?

> +
> +	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(u32) ||
> +	    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(u32));
> +	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) {

Should we be able to get here for INTx?

> +			if (entry->msi_attrib.entry_nr != pi_info.start+i)
> +				continue;
> +
> +			ret = kvm_arch_vfio_update_pi_irte(kdev->kvm,
> +							   entry->irq,
> +							   gsi[i],
> +							   set);
> +			if (ret)
> +				goto free_gsi;
> +		}
> +	}
> +#endif
> +
> +	ret = 0;

So if we didn't do anything, return success?  That seems strange.
Should we also be doing some unwind on failure?  Thanks,

Alex

> +
> +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;
> +	int ret;
> +
> +	switch (attr) {
> +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POST
> +	case KVM_DEV_VFIO_DEVICE_POST_IRQ:
> +		ret = kvm_vfio_control_pi(kdev, argp, 1);
> +		break;
> +	case KVM_DEV_VFIO_DEVICE_UNPOST_IRQ:
> +		ret = kvm_vfio_control_pi(kdev, argp, 0);
> +		break;
> +#endif
> +	default:
> +		ret = -ENXIO;
> +	}
> +	return ret;
> +}
> +
>  static int kvm_vfio_set_attr(struct kvm_device *dev,
>  			     struct kvm_device_attr *attr)
>  {
>  	switch (attr->group) {
>  	case KVM_DEV_VFIO_GROUP:
>  		return kvm_vfio_set_group(dev, attr->attr, attr->addr);
> +	case KVM_DEV_VFIO_DEVICE:
> +		return kvm_vfio_set_device(dev, attr->attr, attr->addr);
>  	}
>  
>  	return -ENXIO;
> @@ -299,6 +416,15 @@ static int kvm_vfio_has_attr(struct kvm_device *dev,
>  		}
>  
>  		break;
> +	case KVM_DEV_VFIO_DEVICE:
> +		switch (attr->attr) {
> +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POST
> +		case KVM_DEV_VFIO_DEVICE_POST_IRQ:
> +		case KVM_DEV_VFIO_DEVICE_UNPOST_IRQ:
> +			return irq_remapping_cap(IRQ_POSTING_CAP) ? 0 : -ENXIO;
> +#endif
> +		}
> +		break;
>  	}
>  
>  	return -ENXIO;

  reply	other threads:[~2015-06-11 17:15 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-11 10:51 [v4 00/16] Add VT-d Posted-Interrupts support Feng Wu
2015-06-11 10:51 ` [v4 01/16] KVM: Extend struct pi_desc for VT-d Posted-Interrupts Feng Wu
2015-06-23 15:49   ` Paolo Bonzini
2015-06-24  5:42     ` Wu, Feng
2015-06-24  8:46       ` Paolo Bonzini
2015-06-11 10:51 ` [v4 02/16] KVM: Add some helper functions for Posted-Interrupts Feng Wu
2015-06-11 10:51 ` [v4 03/16] KVM: Define a new interface kvm_intr_is_single_vcpu() Feng Wu
2015-06-11 10:51 ` [v4 04/16] KVM: Get Posted-Interrupts descriptor address from struct kvm_vcpu Feng Wu
2015-06-11 10:51 ` [v4 05/16] KVM: Add interfaces to control PI outside vmx Feng Wu
2015-06-11 10:51 ` [v4 06/16] KVM: Make struct kvm_irq_routing_table accessible Feng Wu
2015-06-11 10:51 ` [v4 07/16] KVM: make kvm_set_msi_irq() public Feng Wu
2015-06-11 10:51 ` [v4 08/16] KVM: kvm-vfio: User API for IRQ forwarding Feng Wu
2015-06-11 13:37   ` Eric Auger
2015-06-12  0:20     ` Wu, Feng
2015-06-11 19:59   ` Avi Kivity
2015-06-12  0:23     ` Wu, Feng
2015-06-12 15:41       ` Alex Williamson
2015-06-12 18:48         ` Avi Kivity
2015-06-12 19:03           ` Alex Williamson
2015-06-15  6:42             ` Wu, Feng
2015-06-15  6:42               ` Wu, Feng
2015-06-15 16:17             ` Eric Auger
2015-06-15 16:45               ` Alex Williamson
2015-06-18  9:16                 ` Wu, Feng
2015-06-18  9:16                   ` Wu, Feng
2015-06-18 20:04                   ` Alex Williamson
2015-06-24 15:46                     ` Joerg Roedel
2015-06-25  1:54                       ` Wu, Feng
2015-06-25  9:37                       ` Wu, Feng
2015-06-25 15:11                         ` Alex Williamson
2015-06-29  9:06                           ` Joerg Roedel
2015-06-29  9:14                             ` Wu, Feng
2015-06-29  9:22                               ` Joerg Roedel
2015-06-29 13:01                                 ` Wu, Feng
2015-06-29 13:27                     ` Wu, Feng
2015-06-29 13:27                       ` Wu, Feng
2015-06-29 15:18                       ` Alex Williamson
2015-06-24 15:50               ` Joerg Roedel
2015-06-24 16:25                 ` Eric Auger
2015-06-24 19:49                   ` Alex Williamson
2015-06-25  1:57                     ` Wu, Feng
2015-06-25  1:57                       ` Wu, Feng
2015-06-11 10:51 ` [v4 09/16] VFIO: external user API for interaction Feng Wu
2015-06-11 10:51 ` [v4 10/16] KVM: kvm-vfio: wrappers to VFIO external API device helpers Feng Wu
2015-06-11 10:51 ` [v4 11/16] KVM: kvm-vfio: User API for VT-d Posted-Interrupts Feng Wu
2015-06-11 10:51 ` [v4 12/16] KVM: kvm-vfio: implement the VFIO skeleton " Feng Wu
2015-06-11 17:15   ` Alex Williamson [this message]
2015-06-12  4:54     ` Wu, Feng
2015-06-12  4:54       ` Wu, Feng
2015-06-12 14:51       ` Alex Williamson
2015-06-23 16:00         ` Paolo Bonzini
2015-06-11 10:51 ` [v4 13/16] KVM: x86: kvm-vfio: VT-d posted-interrupts setup Feng Wu
2015-06-11 17:16   ` Alex Williamson
2015-06-12  4:58     ` Wu, Feng
2015-06-12  4:58       ` Wu, Feng
2015-06-11 10:51 ` [v4 14/16] KVM: Update Posted-Interrupts Descriptor when vCPU is preempted Feng Wu
2015-06-11 10:51 ` [v4 15/16] KVM: Update Posted-Interrupts Descriptor when vCPU is blocked Feng Wu
2015-06-23 16:05   ` Paolo Bonzini
2015-06-11 10:51 ` [v4 16/16] KVM: Warn if 'SN' is set during posting interrupts by software Feng Wu

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=1434042907.4927.194.camel@redhat.com \
    --to=alex.williamson@redhat.com \
    --cc=eric.auger@linaro.org \
    --cc=feng.wu@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=pbonzini@redhat.com \
    /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: link
Be 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.