Subject: Re: [PATCH v6 15/25] iommufd/selftest: Make the mock iommu driver into a real driver

From: Jason Gunthorpe <[email-masked]>
Date: Mon, 14 Aug 2023 20:16:33 -0300

On Wed, Aug 02, 2023 at 09:08:02PM -0300, Jason Gunthorpe wrote:
> I've avoided doing this because there is no way to make this happen
> without an intrusion into the core code. Up till now this has avoided
> needing the core code's probe path with some hackery - but now that
> default domains are becoming mandatory it is unavoidable. The core probe
> path must be run to set the default_domain, only it can do it. Without
> a default domain iommufd can't use the group.
> 
> Make it so that iommufd selftest can create a real iommu driver and bind
> it only to is own private bus. Add iommu_device_register_bus() as a core
> code helper to make this possible. It simply sets the right pointers and
> registers the notifier block. The mock driver then works like any normal
> driver should, with probe triggered by the bus ops
> 
> When the bus->iommu_ops stuff is fully unwound we can probably do better
> here and remove this special case.
> 
> Remove set_platform_dma_ops from selftest and make it use a BLOCKED
> default domain.
> 
> Signed-off-by: Jason Gunthorpe <[email-masked]>
> ---
>  drivers/iommu/iommu-priv.h              |  16 +++
>  drivers/iommu/iommu.c                   |  43 +++++++
>  drivers/iommu/iommufd/iommufd_private.h |   5 +-
>  drivers/iommu/iommufd/main.c            |   8 +-
>  drivers/iommu/iommufd/selftest.c        | 149 +++++++++++++-----------
>  5 files changed, 152 insertions(+), 69 deletions(-)
>  create mode 100644 drivers/iommu/iommu-priv.h

Since this series will miss this kernel again I've taken this patch
into the iommufd tree to fix the broken selftest.

It needed two edits to make it work out of the context of this series

The core code still requires empty free functions:

    +@@ drivers/iommu/iommufd/selftest.c: static struct iommu_domain *mock_domain_alloc(unsigned int iommu_domain_type)
    +   if (iommu_domain_type == IOMMU_DOMAIN_BLOCKED)
    +           return &mock_blocking_domain;
      
    --static void mock_domain_blocking_free(struct iommu_domain *domain)
    --{
    --}
    --
    - static int mock_domain_nop_attach(struct iommu_domain *domain,
    -                             struct device *dev)
    - {
    +@@ drivers/iommu/iommufd/selftest.c: static void mock_domain_set_plaform_dma_ops(struct device *dev)
    +    */
      }
      
    - static const struct iommu_domain_ops mock_blocking_ops = {
    --  .free = mock_domain_blocking_free,
    -   .attach_dev = mock_domain_nop_attach,
    - };
    - 

And we can't use default_domain so rely on a NULL default domain and set_platform_dma_ops:

    -@@ drivers/iommu/iommufd/selftest.c: static int mock_domain_nop_attach(struct iommu_domain *domain,
    +-  if (WARN_ON(iommu_domain_type != IOMMU_DOMAIN_UNMANAGED))
    ++  if (iommu_domain_type != IOMMU_DOMAIN_UNMANAGED)
    +           return NULL;
    + 
    +   mock = kzalloc(sizeof(*mock), GFP_KERNEL);
    -@@ drivers/iommu/iommufd/selftest.c: static bool mock_domain_capable(struct device *dev, enum iommu_cap cap)
    -   return cap == IOMMU_CAP_CACHE_COHERENCY;
    - }
    - 
    --static void mock_domain_set_plaform_dma_ops(struct device *dev)
     +static struct iommu_device mock_iommu_device = {
     +};
     +
     +static struct iommu_device *mock_probe_device(struct device *dev)
    - {
    --  /*
    --   * mock doesn't setup default domains because we can't hook into the
    --   * normal probe path
    --   */
    ++{
     +  return &mock_iommu_device;
    - }
    - 
    ++}
    ++
      static const struct iommu_ops mock_ops = {
    -+  /*
    -+   * IOMMU_DOMAIN_BLOCKED cannot be returned from def_domain_type()
    -+   * because it is zero.
    -+   */
    -+  .default_domain = &mock_blocking_domain,
        .owner = THIS_MODULE,
        .pgsize_bitmap = MOCK_IO_PAGE_SIZE,
        .domain_alloc = mock_domain_alloc,
        .capable = mock_domain_capable,
    --  .set_platform_dma_ops = mock_domain_set_plaform_dma_ops,
    +   .set_platform_dma_ops = mock_domain_set_plaform_dma_ops,
     +  .device_group = generic_device_group,
     +  .probe_device = mock_probe_device,
        .default_domain_ops =

Otherwise it works the same and solves the same problem. There is a
small merge conflict with the fixes in Joerg's tree around the
bus_iommu_probe

Thanks,
Jason