/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef __ARM64_KVM_NVHE_IOMMU_H__ #define __ARM64_KVM_NVHE_IOMMU_H__ #include #include #include struct pkvm_iommu; struct pkvm_iommu_ops { /* * Global driver initialization called before devices are registered. * Driver-specific arguments are passed in a buffer shared by the host. * The buffer memory has been pinned in EL2 but host retains R/W access. * Extra care must be taken when reading from it to avoid TOCTOU bugs. * If the driver maintains its own page tables, it is expected to * initialize them to all memory owned by the host. * Driver initialization lock held during callback. */ int (*init)(void *data, size_t size); /* * Driver-specific validation of a device that is being registered. * All fields of the device struct have been populated. * Called with the host lock held. */ int (*validate)(struct pkvm_iommu *dev); /* * Validation of a new child device that is being register by * the parent device the child selected. Called with the host lock held. */ int (*validate_child)(struct pkvm_iommu *dev, struct pkvm_iommu *child); /* * Callback to apply a host stage-2 mapping change at driver level. * Called before 'host_stage2_idmap_apply' with host lock held. */ void (*host_stage2_idmap_prepare)(phys_addr_t start, phys_addr_t end, enum kvm_pgtable_prot prot); /* * Callback to apply a host stage-2 mapping change at device level. * Called after 'host_stage2_idmap_prepare' with host lock held. */ void (*host_stage2_idmap_apply)(struct pkvm_iommu *dev, phys_addr_t start, phys_addr_t end); /* * Callback to finish a host stage-2 mapping change at device level. * Called after 'host_stage2_idmap_apply' with host lock held. */ void (*host_stage2_idmap_complete)(struct pkvm_iommu *dev); /* Power management callbacks. Called with host lock held. */ int (*suspend)(struct pkvm_iommu *dev); int (*resume)(struct pkvm_iommu *dev); /* * Host data abort handler callback. Called with host lock held. * Returns true if the data abort has been handled. */ bool (*host_dabt_handler)(struct pkvm_iommu *dev, struct kvm_cpu_context *host_ctxt, u32 esr, size_t off); /* Amount of memory allocated per-device for use by the driver. */ size_t data_size; }; struct pkvm_iommu { struct pkvm_iommu *parent; struct list_head list; struct list_head siblings; struct list_head children; unsigned long id; const struct pkvm_iommu_ops *ops; phys_addr_t pa; void *va; size_t size; bool powered; char data[]; }; int __pkvm_iommu_driver_init(enum pkvm_iommu_driver_id id, void *data, size_t size); int __pkvm_iommu_register(unsigned long dev_id, enum pkvm_iommu_driver_id drv_id, phys_addr_t dev_pa, size_t dev_size, unsigned long parent_id, void *kern_mem_va, size_t mem_size); int __pkvm_iommu_pm_notify(unsigned long dev_id, enum pkvm_iommu_pm_event event); int __pkvm_iommu_finalize(void); int pkvm_iommu_host_stage2_adjust_range(phys_addr_t addr, phys_addr_t *start, phys_addr_t *end); bool pkvm_iommu_host_dabt_handler(struct kvm_cpu_context *host_ctxt, u32 esr, phys_addr_t fault_pa); void pkvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end, enum kvm_pgtable_prot prot); extern const struct pkvm_iommu_ops pkvm_s2mpu_ops; extern const struct pkvm_iommu_ops pkvm_sysmmu_sync_ops; #endif /* __ARM64_KVM_NVHE_IOMMU_H__ */