[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <YVQGaL8RHIw8q/Sq@yekko>
Date: Wed, 29 Sep 2021 16:23:36 +1000
From: David Gibson <david@...son.dropbear.id.au>
To: Liu Yi L <yi.l.liu@...el.com>
Cc: alex.williamson@...hat.com, jgg@...dia.com, hch@....de,
jasowang@...hat.com, joro@...tes.org, jean-philippe@...aro.org,
kevin.tian@...el.com, parav@...lanox.com, lkml@...ux.net,
pbonzini@...hat.com, lushenming@...wei.com, eric.auger@...hat.com,
corbet@....net, ashok.raj@...el.com, yi.l.liu@...ux.intel.com,
jun.j.tian@...el.com, hao.wu@...el.com, dave.jiang@...el.com,
jacob.jun.pan@...ux.intel.com, kwankhede@...dia.com,
robin.murphy@....com, kvm@...r.kernel.org,
iommu@...ts.linux-foundation.org, dwmw2@...radead.org,
linux-kernel@...r.kernel.org, baolu.lu@...ux.intel.com,
nicolinc@...dia.com
Subject: Re: [RFC 10/20] iommu/iommufd: Add IOMMU_DEVICE_GET_INFO
On Sun, Sep 19, 2021 at 02:38:38PM +0800, Liu Yi L wrote:
> After a device is bound to the iommufd, userspace can use this interface
> to query the underlying iommu capability and format info for this device.
> Based on this information the user then creates I/O address space in a
> compatible format with the to-be-attached devices.
>
> Device cookie which is registered at binding time is used to mark the
> device which is being queried here.
>
> Signed-off-by: Liu Yi L <yi.l.liu@...el.com>
> ---
> drivers/iommu/iommufd/iommufd.c | 68 +++++++++++++++++++++++++++++++++
> include/uapi/linux/iommu.h | 49 ++++++++++++++++++++++++
> 2 files changed, 117 insertions(+)
>
> diff --git a/drivers/iommu/iommufd/iommufd.c b/drivers/iommu/iommufd/iommufd.c
> index e16ca21e4534..641f199f2d41 100644
> --- a/drivers/iommu/iommufd/iommufd.c
> +++ b/drivers/iommu/iommufd/iommufd.c
> @@ -117,6 +117,71 @@ static int iommufd_fops_release(struct inode *inode, struct file *filep)
> return 0;
> }
>
> +static struct device *
> +iommu_find_device_from_cookie(struct iommufd_ctx *ictx, u64 dev_cookie)
> +{
> + struct iommufd_device *idev;
> + struct device *dev = NULL;
> + unsigned long index;
> +
> + mutex_lock(&ictx->lock);
> + xa_for_each(&ictx->device_xa, index, idev) {
> + if (idev->dev_cookie == dev_cookie) {
> + dev = idev->dev;
> + break;
> + }
> + }
> + mutex_unlock(&ictx->lock);
> +
> + return dev;
> +}
> +
> +static void iommu_device_build_info(struct device *dev,
> + struct iommu_device_info *info)
> +{
> + bool snoop;
> + u64 awidth, pgsizes;
> +
> + if (!iommu_device_get_info(dev, IOMMU_DEV_INFO_FORCE_SNOOP, &snoop))
> + info->flags |= snoop ? IOMMU_DEVICE_INFO_ENFORCE_SNOOP : 0;
> +
> + if (!iommu_device_get_info(dev, IOMMU_DEV_INFO_PAGE_SIZE, &pgsizes)) {
> + info->pgsize_bitmap = pgsizes;
> + info->flags |= IOMMU_DEVICE_INFO_PGSIZES;
> + }
> +
> + if (!iommu_device_get_info(dev, IOMMU_DEV_INFO_ADDR_WIDTH, &awidth)) {
> + info->addr_width = awidth;
> + info->flags |= IOMMU_DEVICE_INFO_ADDR_WIDTH;
> + }
> +}
> +
> +static int iommufd_get_device_info(struct iommufd_ctx *ictx,
> + unsigned long arg)
> +{
> + struct iommu_device_info info;
> + unsigned long minsz;
> + struct device *dev;
> +
> + minsz = offsetofend(struct iommu_device_info, addr_width);
> +
> + if (copy_from_user(&info, (void __user *)arg, minsz))
> + return -EFAULT;
> +
> + if (info.argsz < minsz)
> + return -EINVAL;
> +
> + info.flags = 0;
> +
> + dev = iommu_find_device_from_cookie(ictx, info.dev_cookie);
> + if (!dev)
> + return -EINVAL;
> +
> + iommu_device_build_info(dev, &info);
> +
> + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
> +}
> +
> static long iommufd_fops_unl_ioctl(struct file *filep,
> unsigned int cmd, unsigned long arg)
> {
> @@ -127,6 +192,9 @@ static long iommufd_fops_unl_ioctl(struct file *filep,
> return ret;
>
> switch (cmd) {
> + case IOMMU_DEVICE_GET_INFO:
> + ret = iommufd_get_device_info(ictx, arg);
> + break;
> default:
> pr_err_ratelimited("unsupported cmd %u\n", cmd);
> break;
> diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
> index 59178fc229ca..76b71f9d6b34 100644
> --- a/include/uapi/linux/iommu.h
> +++ b/include/uapi/linux/iommu.h
> @@ -7,6 +7,55 @@
> #define _UAPI_IOMMU_H
>
> #include <linux/types.h>
> +#include <linux/ioctl.h>
> +
> +/* -------- IOCTLs for IOMMU file descriptor (/dev/iommu) -------- */
> +
> +#define IOMMU_TYPE (';')
> +#define IOMMU_BASE 100
> +
> +/*
> + * IOMMU_DEVICE_GET_INFO - _IOR(IOMMU_TYPE, IOMMU_BASE + 1,
> + * struct iommu_device_info)
> + *
> + * Check IOMMU capabilities and format information on a bound device.
> + *
> + * The device is identified by device cookie (registered when binding
> + * this device).
> + *
> + * @argsz: user filled size of this data.
> + * @flags: tells userspace which capability info is available
> + * @dev_cookie: user assinged cookie.
> + * @pgsize_bitmap: Bitmap of supported page sizes. 1-setting of the
> + * bit in pgsize_bitmap[63:12] indicates a supported
> + * page size. Details as below table:
> + *
> + * +===============+============+
> + * | Bit[index] | Page Size |
> + * +---------------+------------+
> + * | 12 | 4 KB |
> + * +---------------+------------+
> + * | 13 | 8 KB |
> + * +---------------+------------+
> + * | 14 | 16 KB |
> + * +---------------+------------+
> + * ...
> + * @addr_width: the address width of supported I/O address spaces.
> + *
> + * Availability: after device is bound to iommufd
> + */
> +struct iommu_device_info {
> + __u32 argsz;
> + __u32 flags;
> +#define IOMMU_DEVICE_INFO_ENFORCE_SNOOP (1 << 0) /* IOMMU enforced snoop */
> +#define IOMMU_DEVICE_INFO_PGSIZES (1 << 1) /* supported page sizes */
> +#define IOMMU_DEVICE_INFO_ADDR_WIDTH (1 << 2) /* addr_wdith field valid */
> + __u64 dev_cookie;
> + __u64 pgsize_bitmap;
> + __u32 addr_width;
I think this is where you should be reporting available IOVA windows,
rather than just an address width. I know that for ppc a real
situation will be to have two different windows of different sizes:
that is the effective address width depends on which IOVA window
you're mapping into.
> +};
> +
> +#define IOMMU_DEVICE_GET_INFO _IO(IOMMU_TYPE, IOMMU_BASE + 1)
>
> #define IOMMU_FAULT_PERM_READ (1 << 0) /* read */
> #define IOMMU_FAULT_PERM_WRITE (1 << 1) /* write */
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)
Powered by blists - more mailing lists