[v4] vfio/cdx: add support for CDX bus
Commit Message
vfio-cdx driver enables IOCTLs for user space to query
MMIO regions for CDX devices and mmap them. This change
also adds support for reset of CDX devices.
This change adds the VFIO CDX driver and enables the following
ioctls for CDX devices:
- VFIO_DEVICE_GET_INFO:
- VFIO_DEVICE_GET_REGION_INFO
- VFIO_DEVICE_RESET
Signed-off-by: Nipun Gupta <nipun.gupta@amd.com>
Reviewed-by: Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
Tested-by: Nikhil Agarwal <nikhil.agarwal@amd.com>
---
Changes v3->v4:
- fix vfio info flags
Changes v2->v3:
- removed redundant init and release functions
- removed redundant dev and cdx_dev from vfio_cdx_device
- added support for iommufd
- added VFIO_DEVICE_FLAGS_CDX
- removed unrequried WARN_ON
- removed unused ioaddr
Changes v1->v2:
- Updated file2alias to support vfio_cdx
- removed some un-necessary checks in mmap
- removed vfio reset wrapper API
- converted complex macros to static APIs
- used pgprot_device and io_remap_pfn_range
MAINTAINERS | 7 +
drivers/vfio/Kconfig | 1 +
drivers/vfio/Makefile | 1 +
drivers/vfio/cdx/Kconfig | 17 ++
drivers/vfio/cdx/Makefile | 8 +
drivers/vfio/cdx/vfio_cdx.c | 271 ++++++++++++++++++++++++++++
drivers/vfio/cdx/vfio_cdx_private.h | 28 +++
include/linux/cdx/cdx_bus.h | 1 -
include/linux/mod_devicetable.h | 6 +
include/uapi/linux/vfio.h | 1 +
scripts/mod/devicetable-offsets.c | 1 +
scripts/mod/file2alias.c | 17 +-
12 files changed, 357 insertions(+), 2 deletions(-)
create mode 100644 drivers/vfio/cdx/Kconfig
create mode 100644 drivers/vfio/cdx/Makefile
create mode 100644 drivers/vfio/cdx/vfio_cdx.c
create mode 100644 drivers/vfio/cdx/vfio_cdx_private.h
Comments
On Tue, Apr 18, 2023 at 05:06:55PM +0530, Nipun Gupta wrote:
> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> index 89e06c981e43..aba36f5be4ec 100644
> --- a/drivers/vfio/Kconfig
> +++ b/drivers/vfio/Kconfig
> @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
> source "drivers/vfio/platform/Kconfig"
> source "drivers/vfio/mdev/Kconfig"
> source "drivers/vfio/fsl-mc/Kconfig"
> +source "drivers/vfio/cdx/Kconfig"
keep sorted
> endif
>
> source "virt/lib/Kconfig"
> diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
> index 70e7dcb302ef..1a27b2516612 100644
> --- a/drivers/vfio/Makefile
> +++ b/drivers/vfio/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_VFIO_PCI) += pci/
> obj-$(CONFIG_VFIO_PLATFORM) += platform/
> obj-$(CONFIG_VFIO_MDEV) += mdev/
> obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
> +obj-$(CONFIG_VFIO_CDX) += cdx/
keep sorted
> diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile
> new file mode 100644
> index 000000000000..82e4ef412c0f
> --- /dev/null
> +++ b/drivers/vfio/cdx/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
> +#
> +
> +obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
> +
> +vfio-cdx-objs := vfio_cdx.o
Linus has asked about "suttering" filenames before, suggest to call
this
"vfio/cdx/main.c"
> +static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
> + unsigned int cmd, unsigned long arg)
> +{
> + struct vfio_cdx_device *vdev =
> + container_of(core_vdev, struct vfio_cdx_device, vdev);
> + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
> + unsigned long minsz;
> +
> + switch (cmd) {
> + case VFIO_DEVICE_GET_INFO:
> + {
> + struct vfio_device_info info;
> +
> + minsz = offsetofend(struct vfio_device_info, num_irqs);
> +
> + if (copy_from_user(&info, (void __user *)arg, minsz))
> + return -EFAULT;
> +
> + if (info.argsz < minsz)
> + return -EINVAL;
> +
> + info.flags = VFIO_DEVICE_FLAGS_CDX;
> + info.flags |= VFIO_DEVICE_FLAGS_RESET;
> +
> + info.num_regions = cdx_dev->res_count;
> + info.num_irqs = 0;
> +
> + return copy_to_user((void __user *)arg, &info, minsz) ?
> + -EFAULT : 0;
> + }
> + case VFIO_DEVICE_GET_REGION_INFO:
> + {
> + struct vfio_region_info info;
> +
> + minsz = offsetofend(struct vfio_region_info, offset);
> +
> + if (copy_from_user(&info, (void __user *)arg, minsz))
> + return -EFAULT;
> +
> + if (info.argsz < minsz)
> + return -EINVAL;
> +
> + if (info.index >= cdx_dev->res_count)
> + return -EINVAL;
> +
> + /* map offset to the physical address */
> + info.offset = vfio_cdx_index_to_offset(info.index);
> + info.size = vdev->regions[info.index].size;
> + info.flags = vdev->regions[info.index].flags;
> +
> + if (copy_to_user((void __user *)arg, &info, minsz))
> + return -EFAULT;
> + return 0;
> + }
> + case VFIO_DEVICE_RESET:
> + {
> + return cdx_dev_reset(core_vdev->dev);
> + }
> + default:
> + return -ENOTTY;
> + }
> +}
Please split this into functions, eg look at PCI
Jason
> -----Original Message-----
> From: Jason Gunthorpe <jgg@ziepe.ca>
> Sent: Tuesday, April 18, 2023 5:40 PM
> To: Gupta, Nipun <Nipun.Gupta@amd.com>
> Cc: alex.williamson@redhat.com; linux-kernel@vger.kernel.org;
> kvm@vger.kernel.org; masahiroy@kernel.org; nathan@kernel.org;
> ndesaulniers@google.com; nicolas@fjasle.eu; git (AMD-Xilinx) <git@amd.com>;
> Anand, Harpreet <harpreet.anand@amd.com>; Jansen Van Vuuren, Pieter
> <pieter.jansen-van-vuuren@amd.com>; Agarwal, Nikhil
> <nikhil.agarwal@amd.com>; Simek, Michal <michal.simek@amd.com>
> Subject: Re: [PATCH v4] vfio/cdx: add support for CDX bus
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Tue, Apr 18, 2023 at 05:06:55PM +0530, Nipun Gupta wrote:
>
> > diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> > index 89e06c981e43..aba36f5be4ec 100644
> > --- a/drivers/vfio/Kconfig
> > +++ b/drivers/vfio/Kconfig
> > @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
> > source "drivers/vfio/platform/Kconfig"
> > source "drivers/vfio/mdev/Kconfig"
> > source "drivers/vfio/fsl-mc/Kconfig"
> > +source "drivers/vfio/cdx/Kconfig"
>
> keep sorted
Since it is not sorted as of now, should a separate patch to be created for
sorting, before adding vfio-cdx?
>
> > endif
> >
> > source "virt/lib/Kconfig"
> > diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
> > index 70e7dcb302ef..1a27b2516612 100644
> > --- a/drivers/vfio/Makefile
> > +++ b/drivers/vfio/Makefile
> > @@ -14,3 +14,4 @@ obj-$(CONFIG_VFIO_PCI) += pci/
> > obj-$(CONFIG_VFIO_PLATFORM) += platform/
> > obj-$(CONFIG_VFIO_MDEV) += mdev/
> > obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
> > +obj-$(CONFIG_VFIO_CDX) += cdx/
>
> keep sorted
Is there Linux guideline here on how objects and folders in Makefile are sorted,
as there are mix and match of files and folders in "drivers/vfio/Makefile".
I could not find any reference for sorting in other Makefiles as well.
>
> > diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile
> > new file mode 100644
> > index 000000000000..82e4ef412c0f
> > --- /dev/null
> > +++ b/drivers/vfio/cdx/Makefile
> > @@ -0,0 +1,8 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +#
> > +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
> > +#
> > +
> > +obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
> > +
> > +vfio-cdx-objs := vfio_cdx.o
>
> Linus has asked about "suttering" filenames before, suggest to call
> this
>
> "vfio/cdx/main.c"
Okay, I do not any strong affiliation towards the name.
Alex, your thoughts on this please?
>
> > +static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
> > + unsigned int cmd, unsigned long arg)
> > +{
> > + struct vfio_cdx_device *vdev =
> > + container_of(core_vdev, struct vfio_cdx_device, vdev);
> > + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
> > + unsigned long minsz;
> > +
> > + switch (cmd) {
> > + case VFIO_DEVICE_GET_INFO:
> > + {
> > + struct vfio_device_info info;
> > +
> > + minsz = offsetofend(struct vfio_device_info, num_irqs);
> > +
> > + if (copy_from_user(&info, (void __user *)arg, minsz))
> > + return -EFAULT;
> > +
> > + if (info.argsz < minsz)
> > + return -EINVAL;
> > +
> > + info.flags = VFIO_DEVICE_FLAGS_CDX;
> > + info.flags |= VFIO_DEVICE_FLAGS_RESET;
> > +
> > + info.num_regions = cdx_dev->res_count;
> > + info.num_irqs = 0;
> > +
> > + return copy_to_user((void __user *)arg, &info, minsz) ?
> > + -EFAULT : 0;
> > + }
> > + case VFIO_DEVICE_GET_REGION_INFO:
> > + {
> > + struct vfio_region_info info;
> > +
> > + minsz = offsetofend(struct vfio_region_info, offset);
> > +
> > + if (copy_from_user(&info, (void __user *)arg, minsz))
> > + return -EFAULT;
> > +
> > + if (info.argsz < minsz)
> > + return -EINVAL;
> > +
> > + if (info.index >= cdx_dev->res_count)
> > + return -EINVAL;
> > +
> > + /* map offset to the physical address */
> > + info.offset = vfio_cdx_index_to_offset(info.index);
> > + info.size = vdev->regions[info.index].size;
> > + info.flags = vdev->regions[info.index].flags;
> > +
> > + if (copy_to_user((void __user *)arg, &info, minsz))
> > + return -EFAULT;
> > + return 0;
> > + }
> > + case VFIO_DEVICE_RESET:
> > + {
> > + return cdx_dev_reset(core_vdev->dev);
> > + }
> > + default:
> > + return -ENOTTY;
> > + }
> > +}
>
> Please split this into functions, eg look at PCI
Sure, will split this into functions.
Regards,
Nipun
>
> Jason
On Tue, 18 Apr 2023 12:50:13 +0000
"Gupta, Nipun" <Nipun.Gupta@amd.com> wrote:
> > -----Original Message-----
> > From: Jason Gunthorpe <jgg@ziepe.ca>
> > Sent: Tuesday, April 18, 2023 5:40 PM
> > To: Gupta, Nipun <Nipun.Gupta@amd.com>
> > Cc: alex.williamson@redhat.com; linux-kernel@vger.kernel.org;
> > kvm@vger.kernel.org; masahiroy@kernel.org; nathan@kernel.org;
> > ndesaulniers@google.com; nicolas@fjasle.eu; git (AMD-Xilinx) <git@amd.com>;
> > Anand, Harpreet <harpreet.anand@amd.com>; Jansen Van Vuuren, Pieter
> > <pieter.jansen-van-vuuren@amd.com>; Agarwal, Nikhil
> > <nikhil.agarwal@amd.com>; Simek, Michal <michal.simek@amd.com>
> > Subject: Re: [PATCH v4] vfio/cdx: add support for CDX bus
> >
> > Caution: This message originated from an External Source. Use proper caution
> > when opening attachments, clicking links, or responding.
> >
> >
> > On Tue, Apr 18, 2023 at 05:06:55PM +0530, Nipun Gupta wrote:
> >
> > > diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> > > index 89e06c981e43..aba36f5be4ec 100644
> > > --- a/drivers/vfio/Kconfig
> > > +++ b/drivers/vfio/Kconfig
> > > @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
> > > source "drivers/vfio/platform/Kconfig"
> > > source "drivers/vfio/mdev/Kconfig"
> > > source "drivers/vfio/fsl-mc/Kconfig"
> > > +source "drivers/vfio/cdx/Kconfig"
> >
> > keep sorted
>
> Since it is not sorted as of now, should a separate patch to be created for
> sorting, before adding vfio-cdx?
These are essentially in chronological order rather than alphabetical,
so I don't really understand this request from Jason. Perhaps if it
was already alphabetical the request would be justified, but I don't
see any obligation here.
> > > endif
> > >
> > > source "virt/lib/Kconfig"
> > > diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
> > > index 70e7dcb302ef..1a27b2516612 100644
> > > --- a/drivers/vfio/Makefile
> > > +++ b/drivers/vfio/Makefile
> > > @@ -14,3 +14,4 @@ obj-$(CONFIG_VFIO_PCI) += pci/
> > > obj-$(CONFIG_VFIO_PLATFORM) += platform/
> > > obj-$(CONFIG_VFIO_MDEV) += mdev/
> > > obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
> > > +obj-$(CONFIG_VFIO_CDX) += cdx/
> >
> > keep sorted
>
> Is there Linux guideline here on how objects and folders in Makefile are sorted,
> as there are mix and match of files and folders in "drivers/vfio/Makefile".
> I could not find any reference for sorting in other Makefiles as well.
Same here, and I also don't know of a best practices reference that
suggests an alphabetical ordering policy.
> > > diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile
> > > new file mode 100644
> > > index 000000000000..82e4ef412c0f
> > > --- /dev/null
> > > +++ b/drivers/vfio/cdx/Makefile
> > > @@ -0,0 +1,8 @@
> > > +# SPDX-License-Identifier: GPL-2.0
> > > +#
> > > +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
> > > +#
> > > +
> > > +obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
> > > +
> > > +vfio-cdx-objs := vfio_cdx.o
> >
> > Linus has asked about "suttering" filenames before, suggest to call
> > this
> >
> > "vfio/cdx/main.c"
>
> Okay, I do not any strong affiliation towards the name.
> Alex, your thoughts on this please?
I think Jason means "stuttering" file paths, or essentially self
redundancy, ex. vfio/cdx/vfio_cdx.c. Yes, Linus has scolded us for
vfio/pci/vfio_pci_* naming in the past, so in the spirit of not being
further scolded I'd agree with the suggestion here. Thanks,
Alex
On Tue, Apr 18, 2023 at 02:40:20PM -0600, Alex Williamson wrote:
> On Tue, 18 Apr 2023 12:50:13 +0000
> "Gupta, Nipun" <Nipun.Gupta@amd.com> wrote:
>
> > > -----Original Message-----
> > > From: Jason Gunthorpe <jgg@ziepe.ca>
> > > Sent: Tuesday, April 18, 2023 5:40 PM
> > > To: Gupta, Nipun <Nipun.Gupta@amd.com>
> > > Cc: alex.williamson@redhat.com; linux-kernel@vger.kernel.org;
> > > kvm@vger.kernel.org; masahiroy@kernel.org; nathan@kernel.org;
> > > ndesaulniers@google.com; nicolas@fjasle.eu; git (AMD-Xilinx) <git@amd.com>;
> > > Anand, Harpreet <harpreet.anand@amd.com>; Jansen Van Vuuren, Pieter
> > > <pieter.jansen-van-vuuren@amd.com>; Agarwal, Nikhil
> > > <nikhil.agarwal@amd.com>; Simek, Michal <michal.simek@amd.com>
> > > Subject: Re: [PATCH v4] vfio/cdx: add support for CDX bus
> > >
> > > Caution: This message originated from an External Source. Use proper caution
> > > when opening attachments, clicking links, or responding.
> > >
> > >
> > > On Tue, Apr 18, 2023 at 05:06:55PM +0530, Nipun Gupta wrote:
> > >
> > > > diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> > > > index 89e06c981e43..aba36f5be4ec 100644
> > > > --- a/drivers/vfio/Kconfig
> > > > +++ b/drivers/vfio/Kconfig
> > > > @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
> > > > source "drivers/vfio/platform/Kconfig"
> > > > source "drivers/vfio/mdev/Kconfig"
> > > > source "drivers/vfio/fsl-mc/Kconfig"
> > > > +source "drivers/vfio/cdx/Kconfig"
> > >
> > > keep sorted
> >
> > Since it is not sorted as of now, should a separate patch to be created for
> > sorting, before adding vfio-cdx?
>
> These are essentially in chronological order rather than alphabetical,
> so I don't really understand this request from Jason. Perhaps if it
> was already alphabetical the request would be justified, but I don't
> see any obligation here.
Ah, well knee jerk, I keep sorting these things, guess I haven't go
here yet.
Best practice is to sort lists like this.
Jason
@@ -22064,6 +22064,13 @@ F: Documentation/filesystems/vfat.rst
F: fs/fat/
F: tools/testing/selftests/filesystems/fat/
+VFIO CDX DRIVER
+M: Nipun Gupta <nipun.gupta@amd.com>
+M: Nikhil Agarwal <nikhil.agarwal@amd.com>
+L: kvm@vger.kernel.org
+S: Maintained
+F: drivers/vfio/cdx/*
+
VFIO DRIVER
M: Alex Williamson <alex.williamson@redhat.com>
L: kvm@vger.kernel.org
@@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
source "drivers/vfio/mdev/Kconfig"
source "drivers/vfio/fsl-mc/Kconfig"
+source "drivers/vfio/cdx/Kconfig"
endif
source "virt/lib/Kconfig"
@@ -14,3 +14,4 @@ obj-$(CONFIG_VFIO_PCI) += pci/
obj-$(CONFIG_VFIO_PLATFORM) += platform/
obj-$(CONFIG_VFIO_MDEV) += mdev/
obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
+obj-$(CONFIG_VFIO_CDX) += cdx/
new file mode 100644
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# VFIO CDX configuration
+#
+# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+#
+
+config VFIO_CDX
+ tristate "VFIO support for CDX bus devices"
+ depends on CDX_BUS
+ select EVENTFD
+ help
+ Driver to enable VFIO support for the devices on CDX bus.
+ This is required to make use of CDX devices present in
+ the system using the VFIO framework.
+
+ If you don't know what to do here, say N.
new file mode 100644
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+#
+
+obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
+
+vfio-cdx-objs := vfio_cdx.o
new file mode 100644
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/vfio.h>
+#include <linux/cdx/cdx_bus.h>
+
+#include "vfio_cdx_private.h"
+
+static struct cdx_driver vfio_cdx_driver;
+
+/**
+ * CDX_DRIVER_OVERRIDE_DEVICE_VFIO - macro used to describe a VFIO
+ * "driver_override" CDX device.
+ * @vend: the 16 bit CDX Vendor ID
+ * @dev: the 16 bit CDX Device ID
+ *
+ * This macro is used to create a struct cdx_device_id that matches a
+ * specific device. driver_override will be set to
+ * CDX_ID_F_VFIO_DRIVER_OVERRIDE.
+ */
+#define CDX_DRIVER_OVERRIDE_DEVICE_VFIO(vend, dev) \
+ CDX_DEVICE_DRIVER_OVERRIDE(vend, dev, CDX_ID_F_VFIO_DRIVER_OVERRIDE)
+
+static int vfio_cdx_open_device(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ int count = cdx_dev->res_count;
+ int i;
+
+ vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region),
+ GFP_KERNEL);
+ if (!vdev->regions)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ struct resource *res = &cdx_dev->res[i];
+
+ vdev->regions[i].addr = res->start;
+ vdev->regions[i].size = resource_size(res);
+ vdev->regions[i].type = res->flags;
+ /*
+ * Only regions addressed with PAGE granularity may be
+ * MMAP'ed securely.
+ */
+ if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+ !(vdev->regions[i].size & ~PAGE_MASK))
+ vdev->regions[i].flags |=
+ VFIO_REGION_INFO_FLAG_MMAP;
+ vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+ if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
+ vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
+ }
+
+ return 0;
+}
+
+static void vfio_cdx_regions_cleanup(struct vfio_cdx_device *vdev)
+{
+ kfree(vdev->regions);
+}
+
+static void vfio_cdx_close_device(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ int ret;
+
+ vfio_cdx_regions_cleanup(vdev);
+
+ /* reset the device before cleaning up the interrupts */
+ ret = cdx_dev_reset(core_vdev->dev);
+ if (ret)
+ dev_warn(core_vdev->dev,
+ "VFIO_CDX: reset device has failed (%d)\n", ret);
+}
+
+static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ unsigned long minsz;
+
+ switch (cmd) {
+ case VFIO_DEVICE_GET_INFO:
+ {
+ struct vfio_device_info info;
+
+ minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ info.flags = VFIO_DEVICE_FLAGS_CDX;
+ info.flags |= VFIO_DEVICE_FLAGS_RESET;
+
+ info.num_regions = cdx_dev->res_count;
+ info.num_irqs = 0;
+
+ return copy_to_user((void __user *)arg, &info, minsz) ?
+ -EFAULT : 0;
+ }
+ case VFIO_DEVICE_GET_REGION_INFO:
+ {
+ struct vfio_region_info info;
+
+ minsz = offsetofend(struct vfio_region_info, offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ if (info.index >= cdx_dev->res_count)
+ return -EINVAL;
+
+ /* map offset to the physical address */
+ info.offset = vfio_cdx_index_to_offset(info.index);
+ info.size = vdev->regions[info.index].size;
+ info.flags = vdev->regions[info.index].flags;
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+ return 0;
+ }
+ case VFIO_DEVICE_RESET:
+ {
+ return cdx_dev_reset(core_vdev->dev);
+ }
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region,
+ struct vm_area_struct *vma)
+{
+ u64 size = vma->vm_end - vma->vm_start;
+ u64 pgoff, base;
+
+ pgoff = vma->vm_pgoff &
+ ((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+ base = pgoff << PAGE_SHIFT;
+
+ if (region.size < PAGE_SIZE || base + size > region.size)
+ return -EINVAL;
+
+ vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+ vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
+
+ return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ size, vma->vm_page_prot);
+}
+
+static int vfio_cdx_mmap(struct vfio_device *core_vdev,
+ struct vm_area_struct *vma)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ unsigned int index;
+
+ index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT);
+
+ if (index >= cdx_dev->res_count)
+ return -EINVAL;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+ return -EINVAL;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) &&
+ (vma->vm_flags & VM_READ))
+ return -EINVAL;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) &&
+ (vma->vm_flags & VM_WRITE))
+ return -EINVAL;
+
+ return vfio_cdx_mmap_mmio(vdev->regions[index], vma);
+}
+
+static const struct vfio_device_ops vfio_cdx_ops = {
+ .name = "vfio-cdx",
+ .open_device = vfio_cdx_open_device,
+ .close_device = vfio_cdx_close_device,
+ .ioctl = vfio_cdx_ioctl,
+ .mmap = vfio_cdx_mmap,
+ .bind_iommufd = vfio_iommufd_physical_bind,
+ .unbind_iommufd = vfio_iommufd_physical_unbind,
+ .attach_ioas = vfio_iommufd_physical_attach_ioas,
+};
+
+static int vfio_cdx_probe(struct cdx_device *cdx_dev)
+{
+ struct vfio_cdx_device *vdev = NULL;
+ struct device *dev = &cdx_dev->dev;
+ int ret;
+
+ vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev,
+ &vfio_cdx_ops);
+ if (IS_ERR(vdev))
+ return PTR_ERR(vdev);
+
+ ret = vfio_register_group_dev(&vdev->vdev);
+ if (ret) {
+ dev_err(dev, "VFIO_CDX: Failed to add to vfio group\n");
+ goto out_uninit;
+ }
+
+ dev_set_drvdata(dev, vdev);
+ return 0;
+
+out_uninit:
+ vfio_put_device(&vdev->vdev);
+ return ret;
+}
+
+static int vfio_cdx_remove(struct cdx_device *cdx_dev)
+{
+ struct device *dev = &cdx_dev->dev;
+ struct vfio_cdx_device *vdev;
+
+ vdev = dev_get_drvdata(dev);
+ vfio_unregister_group_dev(&vdev->vdev);
+ vfio_put_device(&vdev->vdev);
+
+ return 0;
+}
+
+static const struct cdx_device_id vfio_cdx_table[] = {
+ { CDX_DRIVER_OVERRIDE_DEVICE_VFIO(CDX_ANY_ID, CDX_ANY_ID) }, /* match all by default */
+ {}
+};
+
+MODULE_DEVICE_TABLE(cdx, vfio_cdx_table);
+
+static struct cdx_driver vfio_cdx_driver = {
+ .probe = vfio_cdx_probe,
+ .remove = vfio_cdx_remove,
+ .match_id_table = vfio_cdx_table,
+ .driver = {
+ .name = "vfio-cdx",
+ .owner = THIS_MODULE,
+ },
+ .driver_managed_dma = true,
+};
+
+static int __init vfio_cdx_driver_init(void)
+{
+ return cdx_driver_register(&vfio_cdx_driver);
+}
+
+static void __exit vfio_cdx_driver_exit(void)
+{
+ cdx_driver_unregister(&vfio_cdx_driver);
+}
+
+module_init(vfio_cdx_driver_init);
+module_exit(vfio_cdx_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
new file mode 100644
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#ifndef VFIO_CDX_PRIVATE_H
+#define VFIO_CDX_PRIVATE_H
+
+#define VFIO_CDX_OFFSET_SHIFT 40
+
+static inline u64 vfio_cdx_index_to_offset(u32 index)
+{
+ return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT);
+}
+
+struct vfio_cdx_region {
+ u32 flags;
+ u32 type;
+ u64 addr;
+ resource_size_t size;
+};
+
+struct vfio_cdx_device {
+ struct vfio_device vdev;
+ struct vfio_cdx_region *regions;
+};
+
+#endif /* VFIO_CDX_PRIVATE_H */
@@ -14,7 +14,6 @@
#include <linux/mod_devicetable.h>
#define MAX_CDX_DEV_RESOURCES 4
-#define CDX_ANY_ID (0xFFFF)
#define CDX_CONTROLLER_ID_SHIFT 4
#define CDX_BUS_NUM_MASK 0xF
@@ -912,6 +912,12 @@ struct ishtp_device_id {
kernel_ulong_t driver_data;
};
+#define CDX_ANY_ID (0xFFFF)
+
+enum {
+ CDX_ID_F_VFIO_DRIVER_OVERRIDE = 1,
+};
+
/**
* struct cdx_device_id - CDX device identifier
* @vendor: Vendor ID
@@ -213,6 +213,7 @@ struct vfio_device_info {
#define VFIO_DEVICE_FLAGS_AP (1 << 5) /* vfio-ap device */
#define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6) /* vfio-fsl-mc device */
#define VFIO_DEVICE_FLAGS_CAPS (1 << 7) /* Info supports caps */
+#define VFIO_DEVICE_FLAGS_CDX (1 << 8) /* vfio-cdx device */
__u32 num_regions; /* Max region index + 1 */
__u32 num_irqs; /* Max IRQ index + 1 */
__u32 cap_offset; /* Offset within info struct of first cap */
@@ -265,6 +265,7 @@ int main(void)
DEVID(cdx_device_id);
DEVID_FIELD(cdx_device_id, vendor);
DEVID_FIELD(cdx_device_id, device);
+ DEVID_FIELD(cdx_device_id, override_only);
return 0;
}
@@ -1458,8 +1458,23 @@ static int do_cdx_entry(const char *filename, void *symval,
{
DEF_FIELD(symval, cdx_device_id, vendor);
DEF_FIELD(symval, cdx_device_id, device);
+ DEF_FIELD(symval, cdx_device_id, override_only);
- sprintf(alias, "cdx:v%08Xd%08Xd", vendor, device);
+ switch (override_only) {
+ case 0:
+ strcpy(alias, "cdx:");
+ break;
+ case CDX_ID_F_VFIO_DRIVER_OVERRIDE:
+ strcpy(alias, "vfio_cdx:");
+ break;
+ default:
+ warn("Unknown CDX driver_override alias %08X\n",
+ override_only);
+ return 0;
+ }
+
+ ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
+ ADD(alias, "d", device != CDX_ANY_ID, device);
return 1;
}