Skip to content

Commit 8cc9315

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Prepare IOMMU domain for IOPF
This adds some mechanisms around the iommu_domain so that the I/O page fault handling framework could route a page fault to the domain and call the fault handler from it. Add pointers to the page fault handler and its private data in struct iommu_domain. The fault handler will be called with the private data as a parameter once a page fault is routed to the domain. Any kernel component which owns an iommu domain could install handler and its private parameter so that the page fault could be further routed and handled. This also prepares the SVA implementation to be the first consumer of the per-domain page fault handling model. The I/O page fault handler for SVA is copied to the SVA file with mmget_not_zero() added before mmap_read_lock(). Suggested-by: Jean-Philippe Brucker <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Jean-Philippe Brucker <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Tested-by: Zhangfei Gao <[email protected]> Tested-by: Tony Zhu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 1c26357 commit 8cc9315

File tree

5 files changed

+80
-0
lines changed

5 files changed

+80
-0
lines changed

drivers/iommu/io-pgfault.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ static void iopf_handle_group(struct work_struct *work)
181181
* request completes, outstanding faults will have been dealt with by the time
182182
* the PASID is freed.
183183
*
184+
* Any valid page fault will be eventually routed to an iommu domain and the
185+
* page fault handler installed there will get called. The users of this
186+
* handling framework should guarantee that the iommu domain could only be
187+
* freed after the device has stopped generating page faults (or the iommu
188+
* hardware has been set to block the page faults) and the pending page faults
189+
* have been flushed.
190+
*
184191
* Return: 0 on success and <0 on error.
185192
*/
186193
int iommu_queue_iopf(struct iommu_fault *fault, void *cookie)

drivers/iommu/iommu-sva-lib.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,61 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle)
180180
return domain->mm->pasid;
181181
}
182182
EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
183+
184+
/*
185+
* I/O page fault handler for SVA
186+
*/
187+
enum iommu_page_response_code
188+
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data)
189+
{
190+
vm_fault_t ret;
191+
struct vm_area_struct *vma;
192+
struct mm_struct *mm = data;
193+
unsigned int access_flags = 0;
194+
unsigned int fault_flags = FAULT_FLAG_REMOTE;
195+
struct iommu_fault_page_request *prm = &fault->prm;
196+
enum iommu_page_response_code status = IOMMU_PAGE_RESP_INVALID;
197+
198+
if (!(prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID))
199+
return status;
200+
201+
if (!mmget_not_zero(mm))
202+
return status;
203+
204+
mmap_read_lock(mm);
205+
206+
vma = find_extend_vma(mm, prm->addr);
207+
if (!vma)
208+
/* Unmapped area */
209+
goto out_put_mm;
210+
211+
if (prm->perm & IOMMU_FAULT_PERM_READ)
212+
access_flags |= VM_READ;
213+
214+
if (prm->perm & IOMMU_FAULT_PERM_WRITE) {
215+
access_flags |= VM_WRITE;
216+
fault_flags |= FAULT_FLAG_WRITE;
217+
}
218+
219+
if (prm->perm & IOMMU_FAULT_PERM_EXEC) {
220+
access_flags |= VM_EXEC;
221+
fault_flags |= FAULT_FLAG_INSTRUCTION;
222+
}
223+
224+
if (!(prm->perm & IOMMU_FAULT_PERM_PRIV))
225+
fault_flags |= FAULT_FLAG_USER;
226+
227+
if (access_flags & ~vma->vm_flags)
228+
/* Access fault */
229+
goto out_put_mm;
230+
231+
ret = handle_mm_fault(vma, prm->addr, fault_flags, NULL);
232+
status = ret & VM_FAULT_ERROR ? IOMMU_PAGE_RESP_INVALID :
233+
IOMMU_PAGE_RESP_SUCCESS;
234+
235+
out_put_mm:
236+
mmap_read_unlock(mm);
237+
mmput(mm);
238+
239+
return status;
240+
}

drivers/iommu/iommu-sva-lib.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ int iopf_queue_flush_dev(struct device *dev);
2626
struct iopf_queue *iopf_queue_alloc(const char *name);
2727
void iopf_queue_free(struct iopf_queue *queue);
2828
int iopf_queue_discard_partial(struct iopf_queue *queue);
29+
enum iommu_page_response_code
30+
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data);
2931

3032
#else /* CONFIG_IOMMU_SVA */
3133
static inline int iommu_queue_iopf(struct iommu_fault *fault, void *cookie)
@@ -63,5 +65,11 @@ static inline int iopf_queue_discard_partial(struct iopf_queue *queue)
6365
{
6466
return -ENODEV;
6567
}
68+
69+
static inline enum iommu_page_response_code
70+
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data)
71+
{
72+
return IOMMU_PAGE_RESP_INVALID;
73+
}
6674
#endif /* CONFIG_IOMMU_SVA */
6775
#endif /* _IOMMU_SVA_LIB_H */

drivers/iommu/iommu.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333

3434
#include "dma-iommu.h"
3535

36+
#include "iommu-sva-lib.h"
37+
3638
static struct kset *iommu_group_kset;
3739
static DEFINE_IDA(iommu_group_ida);
3840

@@ -3309,6 +3311,8 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
33093311
domain->type = IOMMU_DOMAIN_SVA;
33103312
mmgrab(mm);
33113313
domain->mm = mm;
3314+
domain->iopf_handler = iommu_sva_handle_iopf;
3315+
domain->fault_data = mm;
33123316

33133317
return domain;
33143318
}

include/linux/iommu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ struct iommu_domain {
9898
unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */
9999
struct iommu_domain_geometry geometry;
100100
struct iommu_dma_cookie *iova_cookie;
101+
enum iommu_page_response_code (*iopf_handler)(struct iommu_fault *fault,
102+
void *data);
103+
void *fault_data;
101104
union {
102105
struct {
103106
iommu_fault_handler_t handler;

0 commit comments

Comments
 (0)