]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - arch/powerpc/include/asm/iommu.h
vfio: powerpc/spapr: Register memory and define IOMMU v2
[mirror_ubuntu-zesty-kernel.git] / arch / powerpc / include / asm / iommu.h
index 44a20ccf06b4441b75338d3e35b7c972c720c449..f9957eb4c659ab5d5175a63bf9c182f49c2482bd 100644 (file)
@@ -45,15 +45,32 @@ extern int iommu_is_off;
 extern int iommu_force_on;
 
 struct iommu_table_ops {
+       /*
+        * When called with direction==DMA_NONE, it is equal to clear().
+        * uaddr is a linear map address.
+        */
        int (*set)(struct iommu_table *tbl,
                        long index, long npages,
                        unsigned long uaddr,
                        enum dma_data_direction direction,
                        struct dma_attrs *attrs);
+#ifdef CONFIG_IOMMU_API
+       /*
+        * Exchanges existing TCE with new TCE plus direction bits;
+        * returns old TCE and DMA direction mask.
+        * @tce is a physical address.
+        */
+       int (*exchange)(struct iommu_table *tbl,
+                       long index,
+                       unsigned long *hpa,
+                       enum dma_data_direction *direction);
+#endif
        void (*clear)(struct iommu_table *tbl,
                        long index, long npages);
+       /* get() returns a physical address */
        unsigned long (*get)(struct iommu_table *tbl, long index);
        void (*flush)(struct iommu_table *tbl);
+       void (*free)(struct iommu_table *tbl);
 };
 
 /* These are used by VIO */
@@ -80,6 +97,9 @@ struct iommu_pool {
 struct iommu_table {
        unsigned long  it_busno;     /* Bus number this table belongs to */
        unsigned long  it_size;      /* Size of iommu table in entries */
+       unsigned long  it_indirect_levels;
+       unsigned long  it_level_size;
+       unsigned long  it_allocated_size;
        unsigned long  it_offset;    /* Offset into global table */
        unsigned long  it_base;      /* mapped address of tce table */
        unsigned long  it_index;     /* which iommu table this is */
@@ -92,10 +112,15 @@ struct iommu_table {
        unsigned long *it_map;       /* A simple allocation bitmap for now */
        unsigned long  it_page_shift;/* table iommu page size */
        struct list_head it_group_list;/* List of iommu_table_group_link */
+       unsigned long *it_userspace; /* userspace view of the table */
        struct iommu_table_ops *it_ops;
-       void (*set_bypass)(struct iommu_table *tbl, bool enable);
 };
 
+#define IOMMU_TABLE_USERSPACE_ENTRY(tbl, entry) \
+               ((tbl)->it_userspace ? \
+                       &((tbl)->it_userspace[(entry) - (tbl)->it_offset]) : \
+                       NULL)
+
 /* Pure 2^n version of get_order */
 static inline __attribute_const__
 int get_iommu_order(unsigned long size, struct iommu_table *tbl)
@@ -126,6 +151,30 @@ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
                                            int nid);
 #define IOMMU_TABLE_GROUP_MAX_TABLES   1
 
+struct iommu_table_group;
+
+struct iommu_table_group_ops {
+       unsigned long (*get_table_size)(
+                       __u32 page_shift,
+                       __u64 window_size,
+                       __u32 levels);
+       long (*create_table)(struct iommu_table_group *table_group,
+                       int num,
+                       __u32 page_shift,
+                       __u64 window_size,
+                       __u32 levels,
+                       struct iommu_table **ptbl);
+       long (*set_window)(struct iommu_table_group *table_group,
+                       int num,
+                       struct iommu_table *tblnew);
+       long (*unset_window)(struct iommu_table_group *table_group,
+                       int num);
+       /* Switch ownership from platform code to external user (e.g. VFIO) */
+       void (*take_ownership)(struct iommu_table_group *table_group);
+       /* Switch ownership from external user (e.g. VFIO) back to core */
+       void (*release_ownership)(struct iommu_table_group *table_group);
+};
+
 struct iommu_table_group_link {
        struct list_head next;
        struct rcu_head rcu;
@@ -133,8 +182,16 @@ struct iommu_table_group_link {
 };
 
 struct iommu_table_group {
+       /* IOMMU properties */
+       __u32 tce32_start;
+       __u32 tce32_size;
+       __u64 pgsizes; /* Bitmap of supported page sizes */
+       __u32 max_dynamic_windows_supported;
+       __u32 max_levels;
+
        struct iommu_group *group;
        struct iommu_table *tables[IOMMU_TABLE_GROUP_MAX_TABLES];
+       struct iommu_table_group_ops *ops;
 };
 
 #ifdef CONFIG_IOMMU_API
@@ -144,6 +201,8 @@ extern void iommu_register_group(struct iommu_table_group *table_group,
 extern int iommu_add_device(struct device *dev);
 extern void iommu_del_device(struct device *dev);
 extern int __init tce_iommu_bus_notifier_init(void);
+extern long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry,
+               unsigned long *hpa, enum dma_data_direction *direction);
 #else
 static inline void iommu_register_group(struct iommu_table_group *table_group,
                                        int pci_domain_number,
@@ -216,10 +275,6 @@ extern int iommu_tce_clear_param_check(struct iommu_table *tbl,
                unsigned long npages);
 extern int iommu_tce_put_param_check(struct iommu_table *tbl,
                unsigned long ioba, unsigned long tce);
-extern int iommu_tce_build(struct iommu_table *tbl, unsigned long entry,
-               unsigned long hwaddr, enum dma_data_direction direction);
-extern unsigned long iommu_clear_tce(struct iommu_table *tbl,
-               unsigned long entry);
 
 extern void iommu_flush_tce(struct iommu_table *tbl);
 extern int iommu_take_ownership(struct iommu_table *tbl);