Skip to content

Commit

Permalink
iommu/core: Add fault reporting mechanism
Browse files Browse the repository at this point in the history
Add iommu fault report mechanism to the IOMMU API, so implementations
could report about mmu faults (translation errors, hardware errors,
etc..).

Fault reports can be used in several ways:
- mere logging
- reset the device that accessed the faulting address (may be necessary
  in case the device is a remote processor for example)
- implement dynamic PTE/TLB loading

A dedicated iommu_set_fault_handler() API has been added to allow
users, who are interested to receive such reports, to provide
their handler.

Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
  • Loading branch information
Ohad Ben-Cohen authored and Joerg Roedel committed Sep 14, 2011
1 parent 5e1b612 commit 4f3f8d9
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
13 changes: 13 additions & 0 deletions drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ bool iommu_found(void)
}
EXPORT_SYMBOL_GPL(iommu_found);

/**
* iommu_set_fault_handler() - set a fault handler for an iommu domain
* @domain: iommu domain
* @handler: fault handler
*/
void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler)
{
BUG_ON(!domain);

domain->handler = handler;
}

struct iommu_domain *iommu_domain_alloc(void)
{
struct iommu_domain *domain;
Expand Down
51 changes: 51 additions & 0 deletions include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,18 @@
#define IOMMU_CACHE (4) /* DMA cache coherency */

struct device;
struct iommu_domain;

/* iommu fault flags */
#define IOMMU_FAULT_READ 0x0
#define IOMMU_FAULT_WRITE 0x1

typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
struct device *, unsigned long, int);

struct iommu_domain {
void *priv;
iommu_fault_handler_t handler;
};

#define IOMMU_CAP_CACHE_COHERENCY 0x1
Expand Down Expand Up @@ -67,6 +76,43 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova);
extern int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler);

/**
* report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
* @domain: the iommu domain where the fault has happened
* @dev: the device where the fault has happened
* @iova: the faulting address
* @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
*
* This function should be called by the low-level IOMMU implementations
* whenever IOMMU faults happen, to allow high-level users, that are
* interested in such events, to know about them.
*
* This event may be useful for several possible use cases:
* - mere logging of the event
* - dynamic TLB/PTE loading
* - if restarting of the faulting device is required
*
* Returns 0 on success and an appropriate error code otherwise (if dynamic
* PTE/TLB loading will one day be supported, implementations will be able
* to tell whether it succeeded or not according to this return value).
*/
static inline int report_iommu_fault(struct iommu_domain *domain,
struct device *dev, unsigned long iova, int flags)
{
int ret = 0;

/*
* if upper layers showed interest and installed a fault handler,
* invoke it.
*/
if (domain->handler)
ret = domain->handler(domain, dev, iova, flags);

return ret;
}

#else /* CONFIG_IOMMU_API */

Expand Down Expand Up @@ -123,6 +169,11 @@ static inline int domain_has_cap(struct iommu_domain *domain,
return 0;
}

static inline void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler)
{
}

#endif /* CONFIG_IOMMU_API */

#endif /* __LINUX_IOMMU_H */

0 comments on commit 4f3f8d9

Please sign in to comment.