diff options
Diffstat (limited to 'include/linux/iommu.h')
-rw-r--r-- | include/linux/iommu.h | 163 |
1 files changed, 159 insertions, 4 deletions
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f28dff313b07..2767fcdec5a1 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -23,13 +23,14 @@ #include <linux/err.h> #include <linux/of.h> #include <linux/types.h> -#include <linux/scatterlist.h> #include <trace/events/iommu.h> #define IOMMU_READ (1 << 0) #define IOMMU_WRITE (1 << 1) #define IOMMU_CACHE (1 << 2) /* DMA cache coherency */ #define IOMMU_NOEXEC (1 << 3) +#define IOMMU_PRIV (1 << 4) +#define IOMMU_DEVICE (1 << 5) /* Indicates access to device memory */ struct iommu_ops; struct iommu_group; @@ -39,8 +40,12 @@ struct iommu_domain; struct notifier_block; /* iommu fault flags */ -#define IOMMU_FAULT_READ 0x0 -#define IOMMU_FAULT_WRITE 0x1 +#define IOMMU_FAULT_READ (1 << 0) +#define IOMMU_FAULT_WRITE (1 << 1) +#define IOMMU_FAULT_TRANSLATION (1 << 2) +#define IOMMU_FAULT_PERMISSION (1 << 3) +#define IOMMU_FAULT_EXTERNAL (1 << 4) +#define IOMMU_FAULT_TRANSACTION_STALLED (1 << 5) typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); @@ -51,6 +56,10 @@ struct iommu_domain_geometry { bool force_aperture; /* DMA only allowed in mappable range? */ }; +struct iommu_pgtbl_info { + void *pmds; +}; + /* Domain feature flags */ #define __IOMMU_DOMAIN_PAGING (1U << 0) /* Support for iommu_map/unmap */ #define __IOMMU_DOMAIN_DMA_API (1U << 1) /* Domain for use in DMA-API @@ -112,9 +121,28 @@ enum iommu_attr { DOMAIN_ATTR_FSL_PAMU_ENABLE, DOMAIN_ATTR_FSL_PAMUV1, DOMAIN_ATTR_NESTING, /* two stages of translation */ + DOMAIN_ATTR_PT_BASE_ADDR, + DOMAIN_ATTR_SECURE_VMID, + DOMAIN_ATTR_ATOMIC, + DOMAIN_ATTR_CONTEXT_BANK, + DOMAIN_ATTR_TTBR0, + DOMAIN_ATTR_CONTEXTIDR, + DOMAIN_ATTR_PROCID, + DOMAIN_ATTR_DYNAMIC, + DOMAIN_ATTR_NON_FATAL_FAULTS, + DOMAIN_ATTR_S1_BYPASS, + DOMAIN_ATTR_FAST, + DOMAIN_ATTR_PGTBL_INFO, + DOMAIN_ATTR_EARLY_MAP, + DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT, + DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, + DOMAIN_ATTR_ENABLE_TTBR1, + DOMAIN_ATTR_CB_STALL_DISABLE, DOMAIN_ATTR_MAX, }; +extern struct dentry *iommu_debugfs_top; + /** * struct iommu_dm_region - descriptor for a direct mapped memory region * @list: Linked list pointers @@ -142,12 +170,21 @@ struct iommu_dm_region { * @map_sg: map a scatter-gather list of physically contiguous memory chunks * to an iommu domain * @iova_to_phys: translate iova to physical address + * @iova_to_phys_hard: translate iova to physical address using IOMMU hardware * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes * @of_xlate: add OF master IDs to iommu grouping * @pgsize_bitmap: bitmap of supported page sizes + * @get_pgsize_bitmap: gets a bitmap of supported page sizes for a domain + * This takes precedence over @pgsize_bitmap. + * @trigger_fault: trigger a fault on the device attached to an iommu domain + * @reg_read: read an IOMMU register + * @reg_write: write an IOMMU register + * @tlbi_domain: Invalidate all TLBs covering an iommu domain + * @enable_config_clocks: Enable all config clocks for this domain's IOMMU + * @disable_config_clocks: Disable all config clocks for this domain's IOMMU * @priv: per-instance data private to the iommu driver */ struct iommu_ops { @@ -166,6 +203,8 @@ struct iommu_ops { size_t (*map_sg)(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); + phys_addr_t (*iova_to_phys_hard)(struct iommu_domain *domain, + dma_addr_t iova); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); struct iommu_group *(*device_group)(struct device *dev); @@ -186,11 +225,25 @@ struct iommu_ops { int (*domain_set_windows)(struct iommu_domain *domain, u32 w_count); /* Get the numer of window per domain */ u32 (*domain_get_windows)(struct iommu_domain *domain); + int (*dma_supported)(struct iommu_domain *domain, struct device *dev, + u64 mask); + void (*trigger_fault)(struct iommu_domain *domain, unsigned long flags); + unsigned long (*reg_read)(struct iommu_domain *domain, + unsigned long offset); + void (*reg_write)(struct iommu_domain *domain, unsigned long val, + unsigned long offset); + void (*tlbi_domain)(struct iommu_domain *domain); + int (*enable_config_clocks)(struct iommu_domain *domain); + void (*disable_config_clocks)(struct iommu_domain *domain); + uint64_t (*iova_to_pte)(struct iommu_domain *domain, + dma_addr_t iova); #ifdef CONFIG_OF_IOMMU int (*of_xlate)(struct device *dev, struct of_phandle_args *args); #endif + unsigned long (*get_pgsize_bitmap)(struct iommu_domain *domain); + bool (*is_iova_coherent)(struct iommu_domain *domain, dma_addr_t iova); unsigned long pgsize_bitmap; void *priv; }; @@ -212,17 +265,31 @@ extern int iommu_attach_device(struct iommu_domain *domain, struct device *dev); extern void iommu_detach_device(struct iommu_domain *domain, struct device *dev); +extern size_t iommu_pgsize(unsigned long pgsize_bitmap, + unsigned long addr_merge, size_t size); extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev); extern int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); +extern int iommu_unmap_range(struct iommu_domain *domain, unsigned int iova, + unsigned int len); extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg,unsigned int nents, int prot); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); +extern phys_addr_t iommu_iova_to_phys_hard(struct iommu_domain *domain, + dma_addr_t iova); +extern bool iommu_is_iova_coherent(struct iommu_domain *domain, + dma_addr_t iova); extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); +extern void iommu_trigger_fault(struct iommu_domain *domain, + unsigned long flags); +extern unsigned long iommu_reg_read(struct iommu_domain *domain, + unsigned long offset); +extern void iommu_reg_write(struct iommu_domain *domain, unsigned long offset, + unsigned long val); extern void iommu_get_dm_regions(struct device *dev, struct list_head *list); extern void iommu_put_dm_regions(struct device *dev, struct list_head *list); @@ -269,6 +336,9 @@ extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, phys_addr_t offset, u64 size, int prot); extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr); + +extern uint64_t iommu_iova_to_pte(struct iommu_domain *domain, + dma_addr_t iova); /** * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework * @domain: the iommu domain where the fault has happened @@ -292,6 +362,11 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) * Specifically, -ENOSYS is returned if a fault handler isn't installed * (though fault handlers can also return -ENOSYS, in case they want to * elicit the default behavior of the IOMMU drivers). + + * Client fault handler returns -EBUSY to signal to the IOMMU driver + * that the client will take responsibility for any further fault + * handling, including clearing fault status registers or retrying + * the faulting transaction. */ static inline int report_iommu_fault(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags) @@ -314,14 +389,41 @@ static inline size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot) { - return domain->ops->map_sg(domain, iova, sg, nents, prot); + size_t ret; + + trace_map_sg_start(iova, nents); + ret = domain->ops->map_sg(domain, iova, sg, nents, prot); + trace_map_sg_end(iova, nents); + return ret; } +extern int iommu_dma_supported(struct iommu_domain *domain, struct device *dev, + u64 mask); + /* PCI device grouping function */ extern struct iommu_group *pci_device_group(struct device *dev); /* Generic device grouping function */ extern struct iommu_group *generic_device_group(struct device *dev); +static inline void iommu_tlbiall(struct iommu_domain *domain) +{ + if (domain->ops->tlbi_domain) + domain->ops->tlbi_domain(domain); +} + +static inline int iommu_enable_config_clocks(struct iommu_domain *domain) +{ + if (domain->ops->enable_config_clocks) + return domain->ops->enable_config_clocks(domain); + return 0; +} + +static inline void iommu_disable_config_clocks(struct iommu_domain *domain) +{ + if (domain->ops->disable_config_clocks) + domain->ops->disable_config_clocks(domain); +} + #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -379,6 +481,12 @@ static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova, return -ENODEV; } +static inline int iommu_unmap_range(struct iommu_domain *domain, + unsigned int iova, unsigned int len) +{ + return -ENODEV; +} + static inline size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot) @@ -403,11 +511,39 @@ static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_ad return 0; } +static inline phys_addr_t iommu_iova_to_phys_hard(struct iommu_domain *domain, + dma_addr_t iova) +{ + return 0; +} + +static inline bool iommu_is_iova_coherent(struct iommu_domain *domain, + dma_addr_t iova) +{ + return 0; +} + static inline void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token) { } +static inline void iommu_trigger_fault(struct iommu_domain *domain, + unsigned long flags) +{ +} + +static inline unsigned long iommu_reg_read(struct iommu_domain *domain, + unsigned long offset) +{ + return 0; +} + +static inline void iommu_reg_write(struct iommu_domain *domain, + unsigned long val, unsigned long offset) +{ +} + static inline void iommu_get_dm_regions(struct device *dev, struct list_head *list) { @@ -532,6 +668,25 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link) { } +static inline int iommu_dma_supported(struct iommu_domain *domain, + struct device *dev, u64 mask) +{ + return -EINVAL; +} + +static inline void iommu_tlbiall(struct iommu_domain *domain) +{ +} + +static inline int iommu_enable_config_clocks(struct iommu_domain *domain) +{ + return 0; +} + +static inline void iommu_disable_config_clocks(struct iommu_domain *domain) +{ +} + #endif /* CONFIG_IOMMU_API */ #endif /* __LINUX_IOMMU_H */ |