#ifndef _DEV_IOMMU_IOMMU_H_
#define _DEV_IOMMU_IOMMU_H_
#include <sys/_task.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <dev/iommu/iommu_types.h>
#include <dev/pci/pcireg.h>
struct bus_dma_tag_common;
struct iommu_map_entry;
TAILQ_HEAD(iommu_map_entries_tailq, iommu_map_entry);
RB_HEAD(iommu_gas_entries_tree, iommu_map_entry);
RB_PROTOTYPE(iommu_gas_entries_tree, iommu_map_entry, rb_entry,
iommu_gas_cmp_entries);
struct iommu_qi_genseq {
u_int gen;
uint32_t seq;
};
struct iommu_map_entry {
iommu_gaddr_t start;
iommu_gaddr_t end;
iommu_gaddr_t first;
iommu_gaddr_t last;
iommu_gaddr_t free_down;
u_int flags;
union {
TAILQ_ENTRY(iommu_map_entry) dmamap_link;
struct iommu_map_entry *tlb_flush_next;
};
RB_ENTRY(iommu_map_entry) rb_entry;
struct iommu_domain *domain;
struct iommu_qi_genseq gseq;
struct spglist pgtbl_free;
};
struct iommu_unit {
struct mtx lock;
device_t dev;
int unit;
struct sysctl_ctx_list sysctl_ctx;
int dma_enabled;
struct task dmamap_load_task;
TAILQ_HEAD(, bus_dmamap_iommu) delayed_maps;
struct taskqueue *delayed_taskqueue;
uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)];
};
struct iommu_domain_map_ops {
int (*map)(struct iommu_domain *domain, struct iommu_map_entry *entry,
vm_page_t *ma, uint64_t pflags, int flags);
int (*unmap)(struct iommu_domain *domain, struct iommu_map_entry *entry,
int flags);
};
struct iommu_domain {
struct iommu_unit *iommu;
const struct iommu_domain_map_ops *ops;
struct mtx lock;
struct task unload_task;
u_int entries_cnt;
struct iommu_map_entries_tailq unload_entries;
struct iommu_gas_entries_tree rb_root;
struct iommu_map_entry *start_gap;
iommu_gaddr_t end;
struct iommu_map_entry *first_place, *last_place;
struct iommu_map_entry *msi_entry;
iommu_gaddr_t msi_base;
vm_paddr_t msi_phys;
u_int flags;
LIST_HEAD(, iommu_ctx) contexts;
};
struct iommu_ctx {
struct iommu_domain *domain;
struct bus_dma_tag_iommu *tag;
LIST_ENTRY(iommu_ctx) link;
u_int refs;
u_long loads;
u_long unloads;
u_int flags;
uint16_t rid;
};
#define IOMMU_CTX_FAULTED 0x0001
#define IOMMU_CTX_DISABLED 0x0002
#define IOMMU_DOMAIN_GAS_INITED 0x0001
#define IOMMU_DOMAIN_PGTBL_INITED 0x0002
#define IOMMU_DOMAIN_IDMAP 0x0010
#define IOMMU_DOMAIN_RMRR 0x0020
#define IOMMU_LOCK(unit) mtx_lock(&(unit)->lock)
#define IOMMU_UNLOCK(unit) mtx_unlock(&(unit)->lock)
#define IOMMU_ASSERT_LOCKED(unit) mtx_assert(&(unit)->lock, MA_OWNED)
#define IOMMU_DOMAIN_LOCK(dom) mtx_lock(&(dom)->lock)
#define IOMMU_DOMAIN_UNLOCK(dom) mtx_unlock(&(dom)->lock)
#define IOMMU_DOMAIN_ASSERT_LOCKED(dom) mtx_assert(&(dom)->lock, MA_OWNED)
void iommu_free_ctx(struct iommu_ctx *ctx);
void iommu_free_ctx_locked(struct iommu_unit *iommu, struct iommu_ctx *ctx);
struct iommu_ctx *iommu_get_ctx(struct iommu_unit *, device_t dev,
uint16_t rid, bool id_mapped, bool rmrr_init);
struct iommu_unit *iommu_find(device_t dev, bool verbose);
void iommu_domain_unload_entry(struct iommu_map_entry *entry, bool free,
bool cansleep);
void iommu_domain_unload(struct iommu_domain *domain,
struct iommu_map_entries_tailq *entries, bool cansleep);
void iommu_unit_pre_instantiate_ctx(struct iommu_unit *iommu);
struct iommu_ctx *iommu_instantiate_ctx(struct iommu_unit *iommu,
device_t dev, bool rmrr);
int iommu_get_requester(device_t dev, device_t *requester, uint16_t *rid);
int iommu_init_busdma(struct iommu_unit *unit);
void iommu_fini_busdma(struct iommu_unit *unit);
void iommu_gas_init_domain(struct iommu_domain *domain);
void iommu_gas_fini_domain(struct iommu_domain *domain);
struct iommu_map_entry *iommu_gas_alloc_entry(struct iommu_domain *domain,
u_int flags);
void iommu_gas_free_entry(struct iommu_map_entry *entry);
void iommu_gas_free_space(struct iommu_map_entry *entry);
void iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start,
iommu_gaddr_t size);
int iommu_gas_map(struct iommu_domain *domain,
const struct bus_dma_tag_common *common, iommu_gaddr_t size, int offset,
u_int eflags, u_int flags, vm_page_t *ma, struct iommu_map_entry **res);
void iommu_gas_free_region(struct iommu_map_entry *entry);
int iommu_gas_map_region(struct iommu_domain *domain,
struct iommu_map_entry *entry, u_int eflags, u_int flags, vm_page_t *ma);
int iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start,
iommu_gaddr_t end, struct iommu_map_entry **entry0);
int iommu_gas_reserve_region_extend(struct iommu_domain *domain,
iommu_gaddr_t start, iommu_gaddr_t end);
void iommu_set_buswide_ctx(struct iommu_unit *unit, u_int busno);
bool iommu_is_buswide_ctx(struct iommu_unit *unit, u_int busno);
void iommu_domain_init(struct iommu_unit *unit, struct iommu_domain *domain,
const struct iommu_domain_map_ops *ops);
void iommu_domain_fini(struct iommu_domain *domain);
bool bus_dma_iommu_set_buswide(device_t dev);
int bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map,
vm_paddr_t start, vm_size_t length, int flags);
bus_dma_tag_t iommu_get_dma_tag(device_t dev, device_t child);
struct iommu_ctx *iommu_get_dev_ctx(device_t dev);
struct iommu_domain *iommu_get_ctx_domain(struct iommu_ctx *ctx);
SYSCTL_DECL(_hw_iommu);
#endif