Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-25 Thread Baolu Lu

On 2024/3/23 1:06, Jason Gunthorpe wrote:

On Fri, Mar 15, 2024 at 09:16:43AM +0800, Baolu Lu wrote:

On 3/9/24 3:05 AM, Jason Gunthorpe wrote:

On Mon, Jan 22, 2024 at 03:39:00PM +0800, Lu Baolu wrote:


@@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
* @__reserved: Must be 0
* @data_type: One of enum iommu_hwpt_data_type
* @data_len: Length of the type specific data
+ * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
+ *IOMMU_HWPT_FAULT_ID_VALID is set.
* @data_uptr: User pointer to the type specific data
*
* Explicitly allocate a hardware page table object. This is the same object
@@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
__u32 __reserved;
__u32 data_type;
__u32 data_len;
+   __u32 fault_id;
__aligned_u64 data_uptr;
   };


?? We can't add fault_id in the middle of the struct??


Yes. I should add the new field at the end.

By the way, with a __u32 added, this data structure is not 64-byte-
aligned anymore. Do we need to add another unused u32 entry, or just let
the compiler handle it?


Yes, add a reserved u32 to ensure the structs is always without
implicit padding.


Sure.






+   if (cmd->flags & IOMMU_HWPT_FAULT_ID_VALID) {
+   struct iommufd_fault *fault;
+
+   fault = iommufd_get_fault(ucmd, cmd->fault_id);
+   if (IS_ERR(fault)) {
+   rc = PTR_ERR(fault);
+   goto out_hwpt;
+   }
+   hwpt->fault = fault;
+   hwpt->domain->iopf_handler = iommufd_fault_iopf_handler;
+   hwpt->domain->fault_data = hwpt;
+   hwpt->fault_capable = true;


I wonder if there should be an iommu API to make a domain fault
capable?


The iommu core identifies a fault-capable domain by checking its
domain->iopf_handler. Anyway, what's the difference between a fault or
non-fault capable domain from iommu core's point of view?


 From the core? Nothing. I'm just wondering from an API perspective if
we should have a little inline to indicate it.


I have no objection if there's a consumer for it.

Best regards,
baolu




Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-22 Thread Jason Gunthorpe
On Fri, Mar 15, 2024 at 09:16:43AM +0800, Baolu Lu wrote:
> On 3/9/24 3:05 AM, Jason Gunthorpe wrote:
> > On Mon, Jan 22, 2024 at 03:39:00PM +0800, Lu Baolu wrote:
> > 
> > > @@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
> > >* @__reserved: Must be 0
> > >* @data_type: One of enum iommu_hwpt_data_type
> > >* @data_len: Length of the type specific data
> > > + * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field 
> > > of
> > > + *IOMMU_HWPT_FAULT_ID_VALID is set.
> > >* @data_uptr: User pointer to the type specific data
> > >*
> > >* Explicitly allocate a hardware page table object. This is the same 
> > > object
> > > @@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
> > >   __u32 __reserved;
> > >   __u32 data_type;
> > >   __u32 data_len;
> > > + __u32 fault_id;
> > >   __aligned_u64 data_uptr;
> > >   };
> > 
> > ?? We can't add fault_id in the middle of the struct??
> 
> Yes. I should add the new field at the end.
> 
> By the way, with a __u32 added, this data structure is not 64-byte-
> aligned anymore. Do we need to add another unused u32 entry, or just let
> the compiler handle it?

Yes, add a reserved u32 to ensure the structs is always without
implicit padding.

> > 
> > > + if (cmd->flags & IOMMU_HWPT_FAULT_ID_VALID) {
> > > + struct iommufd_fault *fault;
> > > +
> > > + fault = iommufd_get_fault(ucmd, cmd->fault_id);
> > > + if (IS_ERR(fault)) {
> > > + rc = PTR_ERR(fault);
> > > + goto out_hwpt;
> > > + }
> > > + hwpt->fault = fault;
> > > + hwpt->domain->iopf_handler = iommufd_fault_iopf_handler;
> > > + hwpt->domain->fault_data = hwpt;
> > > + hwpt->fault_capable = true;
> > 
> > I wonder if there should be an iommu API to make a domain fault
> > capable?
> 
> The iommu core identifies a fault-capable domain by checking its
> domain->iopf_handler. Anyway, what's the difference between a fault or
> non-fault capable domain from iommu core's point of view?

>From the core? Nothing. I'm just wondering from an API perspective if
we should have a little inline to indicate it.

Jason



Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-14 Thread Baolu Lu

On 3/9/24 3:05 AM, Jason Gunthorpe wrote:

On Mon, Jan 22, 2024 at 03:39:00PM +0800, Lu Baolu wrote:


@@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
   * @__reserved: Must be 0
   * @data_type: One of enum iommu_hwpt_data_type
   * @data_len: Length of the type specific data
+ * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
+ *IOMMU_HWPT_FAULT_ID_VALID is set.
   * @data_uptr: User pointer to the type specific data
   *
   * Explicitly allocate a hardware page table object. This is the same object
@@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
__u32 __reserved;
__u32 data_type;
__u32 data_len;
+   __u32 fault_id;
__aligned_u64 data_uptr;
  };


?? We can't add fault_id in the middle of the struct??


Yes. I should add the new field at the end.

By the way, with a __u32 added, this data structure is not 64-byte-
aligned anymore. Do we need to add another unused u32 entry, or just let
the compiler handle it?




+   if (cmd->flags & IOMMU_HWPT_FAULT_ID_VALID) {
+   struct iommufd_fault *fault;
+
+   fault = iommufd_get_fault(ucmd, cmd->fault_id);
+   if (IS_ERR(fault)) {
+   rc = PTR_ERR(fault);
+   goto out_hwpt;
+   }
+   hwpt->fault = fault;
+   hwpt->domain->iopf_handler = iommufd_fault_iopf_handler;
+   hwpt->domain->fault_data = hwpt;
+   hwpt->fault_capable = true;


I wonder if there should be an iommu API to make a domain fault
capable?


The iommu core identifies a fault-capable domain by checking its
domain->iopf_handler. Anyway, what's the difference between a fault or
non-fault capable domain from iommu core's point of view?

Best regards,
baolu



Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-08 Thread Jason Gunthorpe
On Mon, Jan 22, 2024 at 03:39:00PM +0800, Lu Baolu wrote:

> @@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
>   * @__reserved: Must be 0
>   * @data_type: One of enum iommu_hwpt_data_type
>   * @data_len: Length of the type specific data
> + * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
> + *IOMMU_HWPT_FAULT_ID_VALID is set.
>   * @data_uptr: User pointer to the type specific data
>   *
>   * Explicitly allocate a hardware page table object. This is the same object
> @@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
>   __u32 __reserved;
>   __u32 data_type;
>   __u32 data_len;
> + __u32 fault_id;
>   __aligned_u64 data_uptr;
>  };

?? We can't add fault_id in the middle of the struct??

> + if (cmd->flags & IOMMU_HWPT_FAULT_ID_VALID) {
> + struct iommufd_fault *fault;
> +
> + fault = iommufd_get_fault(ucmd, cmd->fault_id);
> + if (IS_ERR(fault)) {
> + rc = PTR_ERR(fault);
> + goto out_hwpt;
> + }
> + hwpt->fault = fault;
> + hwpt->domain->iopf_handler = iommufd_fault_iopf_handler;
> + hwpt->domain->fault_data = hwpt;
> + hwpt->fault_capable = true;

I wonder if there should be an iommu API to make a domain fault
capable?

Jason



Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-06 Thread Baolu Lu

On 2024/3/7 0:01, Jason Gunthorpe wrote:

On Wed, Mar 06, 2024 at 11:15:50PM +0800, Zhangfei Gao wrote:

Double checked, this does not send flags, 0 is OK,
Only domain_alloc_user in iommufd_hwpt_paging_alloc requires flags.

In my debug, I need this patch, otherwise NULL pointer errors happen
since SVA is not set.

This is some driver bug, we need to get rid of these
iommu_dev_enable_feature() requirements.


Yes. Especially iopf should be independent of SVA.

The problem in the arm smmu v3 driver is that enabling iopf is actually
done in the enabling SVA path, while the enabling iopf path does nothing
except for some checks. It doesn't matter if iopf is tied with SVA, but
when it comes to delivering iopf to user space, we need to decouple it.

Best regards,
baolu



Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-06 Thread Jason Gunthorpe
On Wed, Mar 06, 2024 at 11:15:50PM +0800, Zhangfei Gao wrote:
> 
> Double checked, this does not send flags, 0 is OK,
> Only domain_alloc_user in iommufd_hwpt_paging_alloc requires flags.
> 
> In my debug, I need this patch, otherwise NULL pointer errors happen
> since SVA is not set.

This is some driver bug, we need to get rid of these
iommu_dev_enable_feature() requirements.

Attaching domains with properties should be entirely sufficient.

Jason



Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-06 Thread Zhangfei Gao
Hi, Baolu

On Sat, 2 Mar 2024 at 10:36, Zhangfei Gao  wrote:
>
> On Mon, 22 Jan 2024 at 15:46, Lu Baolu  wrote:
> >
> > When allocating a user iommufd_hw_pagetable, the user space is allowed to
> > associate a fault object with the hw_pagetable by specifying the fault
> > object ID in the page table allocation data and setting the
> > IOMMU_HWPT_FAULT_ID_VALID flag bit.
> >
> > On a successful return of hwpt allocation, the user can retrieve and
> > respond to page faults by reading and writing the file interface of the
> > fault object.
> >
> > Once a fault object has been associated with a hwpt, the hwpt is
> > iopf-capable, indicated by fault_capable set to true. Attaching,
> > detaching, or replacing an iopf-capable hwpt to an RID or PASID will
> > differ from those that are not iopf-capable. The implementation of these
> > will be introduced in the next patch.
> >
> > Signed-off-by: Lu Baolu 
> > ---
> >  drivers/iommu/iommufd/iommufd_private.h | 11 
> >  include/uapi/linux/iommufd.h|  6 +
> >  drivers/iommu/iommufd/fault.c   | 14 ++
> >  drivers/iommu/iommufd/hw_pagetable.c| 36 +++--
> >  4 files changed, 59 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/iommu/iommufd/iommufd_private.h 
> > b/drivers/iommu/iommufd/iommufd_private.h
> > index 52d83e888bd0..2780bed0c6b1 100644
> > --- a/drivers/iommu/iommufd/iommufd_private.h
> > +++ b/drivers/iommu/iommufd/iommufd_private.h
> > @@ -293,6 +293,8 @@ int iommufd_check_iova_range(struct io_pagetable *iopt,
> >  struct iommufd_hw_pagetable {
> > struct iommufd_object obj;
> > struct iommu_domain *domain;
> > +   struct iommufd_fault *fault;
> > +   bool fault_capable : 1;
> >  };
> >
> >  struct iommufd_hwpt_paging {
> > @@ -446,8 +448,17 @@ struct iommufd_fault {
> > struct wait_queue_head wait_queue;
> >  };
> >
> > +static inline struct iommufd_fault *
> > +iommufd_get_fault(struct iommufd_ucmd *ucmd, u32 id)
> > +{
> > +   return container_of(iommufd_get_object(ucmd->ictx, id,
> > +  IOMMUFD_OBJ_FAULT),
> > +   struct iommufd_fault, obj);
> > +}
> > +
> >  int iommufd_fault_alloc(struct iommufd_ucmd *ucmd);
> >  void iommufd_fault_destroy(struct iommufd_object *obj);
> > +int iommufd_fault_iopf_handler(struct iopf_group *group);
> >
> >  #ifdef CONFIG_IOMMUFD_TEST
> >  int iommufd_test(struct iommufd_ucmd *ucmd);
> > diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
> > index c32d62b02306..7481cdd57027 100644
> > --- a/include/uapi/linux/iommufd.h
> > +++ b/include/uapi/linux/iommufd.h
> > @@ -357,10 +357,13 @@ struct iommu_vfio_ioas {
> >   *the parent HWPT in a nesting 
> > configuration.
> >   * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device 
> > IOMMU is
> >   *   enforced on device attachment
> > + * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data 
> > is
> > + * valid.
> >   */
> >  enum iommufd_hwpt_alloc_flags {
> > IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
> > IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
> > +   IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
> >  };
> >
> >  /**
> > @@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
> >   * @__reserved: Must be 0
> >   * @data_type: One of enum iommu_hwpt_data_type
> >   * @data_len: Length of the type specific data
> > + * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
> > + *IOMMU_HWPT_FAULT_ID_VALID is set.
> >   * @data_uptr: User pointer to the type specific data
> >   *
> >   * Explicitly allocate a hardware page table object. This is the same 
> > object
> > @@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
> > __u32 __reserved;
> > __u32 data_type;
> > __u32 data_len;
> > +   __u32 fault_id;
> > __aligned_u64 data_uptr;
> >  };
> >  #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
> > diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
> > index 9844a85feeb2..e752d1c49dde 100644
> > --- a/drivers/iommu/iommufd/fault.c
> > +++ b/drivers/iommu/iommufd/fault.c
> > @@ -253,3 +253,17 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
> >
> > return rc;
> >  }
> > +
> > +int iommufd_fault_iopf_handler(struct iopf_group *group)
> > +{
> > +   struct iommufd_hw_pagetable *hwpt = 
> > group->cookie->domain->fault_data;
> > +   struct iommufd_fault *fault = hwpt->fault;
> > +
> > +   mutex_lock(>mutex);
> > +   list_add_tail(>node, >deliver);
> > +   mutex_unlock(>mutex);
> > +
> > +   wake_up_interruptible(>wait_queue);
> > +
> > +   return 0;
> > +}
> > diff --git a/drivers/iommu/iommufd/hw_pagetable.c 
> > b/drivers/iommu/iommufd/hw_pagetable.c
> > index 3f3f1fa1a0a9..2703d5aea4f5 100644
> > --- 

Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-03-01 Thread Zhangfei Gao
On Mon, 22 Jan 2024 at 15:46, Lu Baolu  wrote:
>
> When allocating a user iommufd_hw_pagetable, the user space is allowed to
> associate a fault object with the hw_pagetable by specifying the fault
> object ID in the page table allocation data and setting the
> IOMMU_HWPT_FAULT_ID_VALID flag bit.
>
> On a successful return of hwpt allocation, the user can retrieve and
> respond to page faults by reading and writing the file interface of the
> fault object.
>
> Once a fault object has been associated with a hwpt, the hwpt is
> iopf-capable, indicated by fault_capable set to true. Attaching,
> detaching, or replacing an iopf-capable hwpt to an RID or PASID will
> differ from those that are not iopf-capable. The implementation of these
> will be introduced in the next patch.
>
> Signed-off-by: Lu Baolu 
> ---
>  drivers/iommu/iommufd/iommufd_private.h | 11 
>  include/uapi/linux/iommufd.h|  6 +
>  drivers/iommu/iommufd/fault.c   | 14 ++
>  drivers/iommu/iommufd/hw_pagetable.c| 36 +++--
>  4 files changed, 59 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iommu/iommufd/iommufd_private.h 
> b/drivers/iommu/iommufd/iommufd_private.h
> index 52d83e888bd0..2780bed0c6b1 100644
> --- a/drivers/iommu/iommufd/iommufd_private.h
> +++ b/drivers/iommu/iommufd/iommufd_private.h
> @@ -293,6 +293,8 @@ int iommufd_check_iova_range(struct io_pagetable *iopt,
>  struct iommufd_hw_pagetable {
> struct iommufd_object obj;
> struct iommu_domain *domain;
> +   struct iommufd_fault *fault;
> +   bool fault_capable : 1;
>  };
>
>  struct iommufd_hwpt_paging {
> @@ -446,8 +448,17 @@ struct iommufd_fault {
> struct wait_queue_head wait_queue;
>  };
>
> +static inline struct iommufd_fault *
> +iommufd_get_fault(struct iommufd_ucmd *ucmd, u32 id)
> +{
> +   return container_of(iommufd_get_object(ucmd->ictx, id,
> +  IOMMUFD_OBJ_FAULT),
> +   struct iommufd_fault, obj);
> +}
> +
>  int iommufd_fault_alloc(struct iommufd_ucmd *ucmd);
>  void iommufd_fault_destroy(struct iommufd_object *obj);
> +int iommufd_fault_iopf_handler(struct iopf_group *group);
>
>  #ifdef CONFIG_IOMMUFD_TEST
>  int iommufd_test(struct iommufd_ucmd *ucmd);
> diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
> index c32d62b02306..7481cdd57027 100644
> --- a/include/uapi/linux/iommufd.h
> +++ b/include/uapi/linux/iommufd.h
> @@ -357,10 +357,13 @@ struct iommu_vfio_ioas {
>   *the parent HWPT in a nesting configuration.
>   * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU 
> is
>   *   enforced on device attachment
> + * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is
> + * valid.
>   */
>  enum iommufd_hwpt_alloc_flags {
> IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
> IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
> +   IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
>  };
>
>  /**
> @@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
>   * @__reserved: Must be 0
>   * @data_type: One of enum iommu_hwpt_data_type
>   * @data_len: Length of the type specific data
> + * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
> + *IOMMU_HWPT_FAULT_ID_VALID is set.
>   * @data_uptr: User pointer to the type specific data
>   *
>   * Explicitly allocate a hardware page table object. This is the same object
> @@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
> __u32 __reserved;
> __u32 data_type;
> __u32 data_len;
> +   __u32 fault_id;
> __aligned_u64 data_uptr;
>  };
>  #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
> diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
> index 9844a85feeb2..e752d1c49dde 100644
> --- a/drivers/iommu/iommufd/fault.c
> +++ b/drivers/iommu/iommufd/fault.c
> @@ -253,3 +253,17 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
>
> return rc;
>  }
> +
> +int iommufd_fault_iopf_handler(struct iopf_group *group)
> +{
> +   struct iommufd_hw_pagetable *hwpt = group->cookie->domain->fault_data;
> +   struct iommufd_fault *fault = hwpt->fault;
> +
> +   mutex_lock(>mutex);
> +   list_add_tail(>node, >deliver);
> +   mutex_unlock(>mutex);
> +
> +   wake_up_interruptible(>wait_queue);
> +
> +   return 0;
> +}
> diff --git a/drivers/iommu/iommufd/hw_pagetable.c 
> b/drivers/iommu/iommufd/hw_pagetable.c
> index 3f3f1fa1a0a9..2703d5aea4f5 100644
> --- a/drivers/iommu/iommufd/hw_pagetable.c
> +++ b/drivers/iommu/iommufd/hw_pagetable.c
> @@ -8,6 +8,15 @@
>  #include "../iommu-priv.h"
>  #include "iommufd_private.h"
>
> +static void __iommufd_hwpt_destroy(struct iommufd_hw_pagetable *hwpt)
> +{
> +   if (hwpt->domain)
> +   iommu_domain_free(hwpt->domain);
> +
> +   

Re: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-02-20 Thread Baolu Lu

On 2024/2/7 16:14, Tian, Kevin wrote:

From: Lu Baolu 
Sent: Monday, January 22, 2024 3:39 PM

+
+int iommufd_fault_iopf_handler(struct iopf_group *group)
+{
+   struct iommufd_hw_pagetable *hwpt = group->cookie->domain-

fault_data;

+   struct iommufd_fault *fault = hwpt->fault;
+


why not directly using iommufd_fault as the fault_data?


The relationship among these structures is:

iommufd_hwpt -> iommu_domain
  ^
  |
  v
iommufd_fault

It appears preferable to hook the hwpt instead of iommufd_fault to an
iommu_domain structure.

Best regards,
baolu




RE: [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-02-07 Thread Tian, Kevin
> From: Lu Baolu 
> Sent: Monday, January 22, 2024 3:39 PM
> 
> +
> +int iommufd_fault_iopf_handler(struct iopf_group *group)
> +{
> + struct iommufd_hw_pagetable *hwpt = group->cookie->domain-
> >fault_data;
> + struct iommufd_fault *fault = hwpt->fault;
> +

why not directly using iommufd_fault as the fault_data?



[PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable

2024-01-21 Thread Lu Baolu
When allocating a user iommufd_hw_pagetable, the user space is allowed to
associate a fault object with the hw_pagetable by specifying the fault
object ID in the page table allocation data and setting the
IOMMU_HWPT_FAULT_ID_VALID flag bit.

On a successful return of hwpt allocation, the user can retrieve and
respond to page faults by reading and writing the file interface of the
fault object.

Once a fault object has been associated with a hwpt, the hwpt is
iopf-capable, indicated by fault_capable set to true. Attaching,
detaching, or replacing an iopf-capable hwpt to an RID or PASID will
differ from those that are not iopf-capable. The implementation of these
will be introduced in the next patch.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/iommufd/iommufd_private.h | 11 
 include/uapi/linux/iommufd.h|  6 +
 drivers/iommu/iommufd/fault.c   | 14 ++
 drivers/iommu/iommufd/hw_pagetable.c| 36 +++--
 4 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/iommufd/iommufd_private.h 
b/drivers/iommu/iommufd/iommufd_private.h
index 52d83e888bd0..2780bed0c6b1 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -293,6 +293,8 @@ int iommufd_check_iova_range(struct io_pagetable *iopt,
 struct iommufd_hw_pagetable {
struct iommufd_object obj;
struct iommu_domain *domain;
+   struct iommufd_fault *fault;
+   bool fault_capable : 1;
 };
 
 struct iommufd_hwpt_paging {
@@ -446,8 +448,17 @@ struct iommufd_fault {
struct wait_queue_head wait_queue;
 };
 
+static inline struct iommufd_fault *
+iommufd_get_fault(struct iommufd_ucmd *ucmd, u32 id)
+{
+   return container_of(iommufd_get_object(ucmd->ictx, id,
+  IOMMUFD_OBJ_FAULT),
+   struct iommufd_fault, obj);
+}
+
 int iommufd_fault_alloc(struct iommufd_ucmd *ucmd);
 void iommufd_fault_destroy(struct iommufd_object *obj);
+int iommufd_fault_iopf_handler(struct iopf_group *group);
 
 #ifdef CONFIG_IOMMUFD_TEST
 int iommufd_test(struct iommufd_ucmd *ucmd);
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index c32d62b02306..7481cdd57027 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -357,10 +357,13 @@ struct iommu_vfio_ioas {
  *the parent HWPT in a nesting configuration.
  * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU is
  *   enforced on device attachment
+ * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is
+ * valid.
  */
 enum iommufd_hwpt_alloc_flags {
IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
+   IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
 };
 
 /**
@@ -411,6 +414,8 @@ enum iommu_hwpt_data_type {
  * @__reserved: Must be 0
  * @data_type: One of enum iommu_hwpt_data_type
  * @data_len: Length of the type specific data
+ * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
+ *IOMMU_HWPT_FAULT_ID_VALID is set.
  * @data_uptr: User pointer to the type specific data
  *
  * Explicitly allocate a hardware page table object. This is the same object
@@ -441,6 +446,7 @@ struct iommu_hwpt_alloc {
__u32 __reserved;
__u32 data_type;
__u32 data_len;
+   __u32 fault_id;
__aligned_u64 data_uptr;
 };
 #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index 9844a85feeb2..e752d1c49dde 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -253,3 +253,17 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 
return rc;
 }
+
+int iommufd_fault_iopf_handler(struct iopf_group *group)
+{
+   struct iommufd_hw_pagetable *hwpt = group->cookie->domain->fault_data;
+   struct iommufd_fault *fault = hwpt->fault;
+
+   mutex_lock(>mutex);
+   list_add_tail(>node, >deliver);
+   mutex_unlock(>mutex);
+
+   wake_up_interruptible(>wait_queue);
+
+   return 0;
+}
diff --git a/drivers/iommu/iommufd/hw_pagetable.c 
b/drivers/iommu/iommufd/hw_pagetable.c
index 3f3f1fa1a0a9..2703d5aea4f5 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -8,6 +8,15 @@
 #include "../iommu-priv.h"
 #include "iommufd_private.h"
 
+static void __iommufd_hwpt_destroy(struct iommufd_hw_pagetable *hwpt)
+{
+   if (hwpt->domain)
+   iommu_domain_free(hwpt->domain);
+
+   if (hwpt->fault)
+   iommufd_put_object(hwpt->fault->ictx, >fault->obj);
+}
+
 void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)
 {
struct iommufd_hwpt_paging *hwpt_paging =
@@ -22,9 +31,7 @@ void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)