Re: [PATCH v3 24/30] vfio-pci/zdev: wire up group notifier

From: Alex Williamson
Date: Tue Feb 08 2022 - 12:43:31 EST


On Fri, 4 Feb 2022 16:15:30 -0500
Matthew Rosato <mjrosato@xxxxxxxxxxxxx> wrote:

> KVM zPCI passthrough device logic will need a reference to the associated
> kvm guest that has access to the device. Let's register a group notifier
> for VFIO_GROUP_NOTIFY_SET_KVM to catch this information in order to create
> an association between a kvm guest and the host zdev.
>
> Signed-off-by: Matthew Rosato <mjrosato@xxxxxxxxxxxxx>
> ---
> arch/s390/include/asm/kvm_pci.h | 2 ++
> drivers/vfio/pci/vfio_pci_core.c | 2 ++
> drivers/vfio/pci/vfio_pci_zdev.c | 46 ++++++++++++++++++++++++++++++++
> include/linux/vfio_pci_core.h | 10 +++++++
> 4 files changed, 60 insertions(+)
>
> diff --git a/arch/s390/include/asm/kvm_pci.h b/arch/s390/include/asm/kvm_pci.h
> index e4696f5592e1..16290b4cf2a6 100644
> --- a/arch/s390/include/asm/kvm_pci.h
> +++ b/arch/s390/include/asm/kvm_pci.h
> @@ -16,6 +16,7 @@
> #include <linux/kvm.h>
> #include <linux/pci.h>
> #include <linux/mutex.h>
> +#include <linux/notifier.h>
> #include <asm/pci_insn.h>
> #include <asm/pci_dma.h>
>
> @@ -32,6 +33,7 @@ struct kvm_zdev {
> u64 rpcit_count;
> struct kvm_zdev_ioat ioat;
> struct zpci_fib fib;
> + struct notifier_block nb;
> };
>
> int kvm_s390_pci_dev_open(struct zpci_dev *zdev);
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index f948e6cd2993..fc57d4d0abbe 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -452,6 +452,7 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev)
>
> vfio_pci_vf_token_user_add(vdev, -1);
> vfio_spapr_pci_eeh_release(vdev->pdev);
> + vfio_pci_zdev_release(vdev);
> vfio_pci_core_disable(vdev);
>
> mutex_lock(&vdev->igate);
> @@ -470,6 +471,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_close_device);
> void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
> {
> vfio_pci_probe_mmaps(vdev);
> + vfio_pci_zdev_open(vdev);
> vfio_spapr_pci_eeh_open(vdev->pdev);
> vfio_pci_vf_token_user_add(vdev, 1);
> }

If this handling were for a specific device, I think we'd be suggesting
this is the point at which we cross over to a vendor variant making use
of vfio-pci-core rather than hooking directly into the core code. But
this is meant to extend vfio-pci proper for the whole arch. Is there a
compromise in using #ifdefs in vfio_pci_ops to call into zpci specific
code that implements these arch specific hooks and the core for
everything else? SPAPR code could probably converted similarly, it
exists here for legacy reasons. [Cc Jason]

Also, please note the DEVICE_FEATURE generalizations in the latest
series from NVIDIA for mlx5 migration support:

https://lore.kernel.org/all/20220207172216.206415-8-yishaih@xxxxxxxxxx/

If this series were to go in via the s390 tree, I'd request a branch so
that we can continue to work on this in vfio code as well. Thanks,

Alex

> diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c
> index ea4c0d2b0663..9f8284499111 100644
> --- a/drivers/vfio/pci/vfio_pci_zdev.c
> +++ b/drivers/vfio/pci/vfio_pci_zdev.c
> @@ -13,6 +13,7 @@
> #include <linux/vfio_zdev.h>
> #include <asm/pci_clp.h>
> #include <asm/pci_io.h>
> +#include <asm/kvm_pci.h>
>
> #include <linux/vfio_pci_core.h>
>
> @@ -136,3 +137,48 @@ int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
>
> return ret;
> }
> +
> +static int vfio_pci_zdev_group_notifier(struct notifier_block *nb,
> + unsigned long action, void *data)
> +{
> + struct kvm_zdev *kzdev = container_of(nb, struct kvm_zdev, nb);
> +
> + if (action == VFIO_GROUP_NOTIFY_SET_KVM) {
> + if (!data || !kzdev->zdev)
> + return NOTIFY_DONE;
> + kzdev->kvm = data;
> + }
> +
> + return NOTIFY_OK;
> +}
> +
> +void vfio_pci_zdev_open(struct vfio_pci_core_device *vdev)
> +{
> + unsigned long events = VFIO_GROUP_NOTIFY_SET_KVM;
> + struct zpci_dev *zdev = to_zpci(vdev->pdev);
> +
> + if (!zdev)
> + return;
> +
> + if (kvm_s390_pci_dev_open(zdev))
> + return;
> +
> + zdev->kzdev->nb.notifier_call = vfio_pci_zdev_group_notifier;
> +
> + if (vfio_register_notifier(vdev->vdev.dev, VFIO_GROUP_NOTIFY,
> + &events, &zdev->kzdev->nb))
> + kvm_s390_pci_dev_release(zdev);
> +}
> +
> +void vfio_pci_zdev_release(struct vfio_pci_core_device *vdev)
> +{
> + struct zpci_dev *zdev = to_zpci(vdev->pdev);
> +
> + if (!zdev || !zdev->kzdev)
> + return;
> +
> + vfio_unregister_notifier(vdev->vdev.dev, VFIO_GROUP_NOTIFY,
> + &zdev->kzdev->nb);
> +
> + kvm_s390_pci_dev_release(zdev);
> +}
> diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
> index 5e2bca3b89db..05287f8ac855 100644
> --- a/include/linux/vfio_pci_core.h
> +++ b/include/linux/vfio_pci_core.h
> @@ -198,12 +198,22 @@ static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
> #ifdef CONFIG_VFIO_PCI_ZDEV
> extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
> struct vfio_info_cap *caps);
> +void vfio_pci_zdev_open(struct vfio_pci_core_device *vdev);
> +void vfio_pci_zdev_release(struct vfio_pci_core_device *vdev);
> #else
> static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
> struct vfio_info_cap *caps)
> {
> return -ENODEV;
> }
> +
> +static inline void vfio_pci_zdev_open(struct vfio_pci_core_device *vdev)
> +{
> +}
> +
> +static inline void vfio_pci_zdev_release(struct vfio_pci_core_device *vdev)
> +{
> +}
> #endif
>
> /* Will be exported for vfio pci drivers usage */