| /* SPDX-License-Identifier: GPL-2.0 */ |
| #ifndef __ARM64_KVM_NVHE_IOMMU_H__ |
| #define __ARM64_KVM_NVHE_IOMMU_H__ |
| |
| #include <kvm/iommu.h> |
| #include <linux/io-pgtable.h> |
| #include <nvhe/pkvm.h> |
| |
| #if IS_ENABLED(CONFIG_ARM_SMMU_V3_PKVM) |
| #include <linux/io-pgtable-arm.h> |
| |
| int kvm_arm_io_pgtable_init_s1(struct io_pgtable_cfg *cfg, |
| struct arm_lpae_io_pgtable *data); |
| int kvm_arm_io_pgtable_init_s2(struct io_pgtable_cfg *cfg, |
| struct arm_lpae_io_pgtable *data); |
| int kvm_arm_io_pgtable_alloc(struct io_pgtable *iop, unsigned long pgd_hva); |
| int kvm_arm_io_pgtable_free(struct io_pgtable *iop); |
| size_t kvm_arm_io_pgtable_size(struct io_pgtable *iopt); |
| #endif /* CONFIG_ARM_SMMU_V3_PKVM */ |
| |
| #if IS_ENABLED(CONFIG_KVM_IOMMU) |
| int kvm_iommu_init(void); |
| int kvm_iommu_init_device(struct kvm_hyp_iommu *iommu); |
| void *kvm_iommu_donate_page(void); |
| void kvm_iommu_reclaim_page(void *p); |
| |
| /* Hypercall handlers */ |
| int kvm_iommu_alloc_domain(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| unsigned long pgd_hva, int type, |
| struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_free_domain(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| u32 endpoint_id, u32 pasid, u32 pasid_bits, |
| struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| u32 endpoint_id, u32 pasid, struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_map_pages(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| unsigned long iova, phys_addr_t paddr, size_t pgsize, |
| size_t pgcount, int prot, struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_unmap_pages(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, |
| unsigned long iova, size_t pgsize, size_t pgcount, |
| struct pkvm_hyp_vcpu *ctxt); |
| phys_addr_t kvm_iommu_iova_to_phys(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, unsigned long iova, |
| struct pkvm_hyp_vcpu *ctxt); |
| int kvm_iommu_alloc_guest_domain(pkvm_handle_t iommu_id, struct pkvm_hyp_vcpu *ctxt, |
| pkvm_handle_t *ret_domain); |
| int kvm_iommu_force_detach_dev(pkvm_handle_t iommu_id, u32 endpoint_id, u32 pasid); |
| #else /* !CONFIG_KVM_IOMMU */ |
| static inline int kvm_iommu_alloc_domain(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| unsigned long pgd_hva, int type, |
| struct pkvm_hyp_vcpu *ctxt) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int kvm_iommu_free_domain(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| u32 endpoint_id, u32 pasid, |
| u32 pasid_bits) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| u32 pasid, |
| u32 endpoint_id) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int kvm_iommu_map_pages(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| unsigned long iova, phys_addr_t paddr, |
| size_t pgsize, size_t pgcount, int prot) |
| { |
| return -ENODEV; |
| } |
| |
| static inline int kvm_iommu_unmap_pages(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| unsigned long iova, size_t pgsize, |
| size_t pgcount) |
| { |
| return 0; |
| } |
| |
| static inline phys_addr_t kvm_iommu_iova_to_phys(pkvm_handle_t iommu_id, |
| pkvm_handle_t domain_id, |
| unsigned long iova) |
| { |
| return 0; |
| } |
| |
| int kvm_iommu_alloc_guest_domain(pkvm_handle_t iommu_id, struct pkvm_hyp_vcpu *ctxt, |
| pkvm_handle_t *ret_domain) |
| { |
| return 0; |
| } |
| |
| int kvm_iommu_force_detach_dev(pkvm_handle_t iommu_id, u32 endpoint_id) |
| { |
| return 0; |
| } |
| #endif /* CONFIG_KVM_IOMMU */ |
| |
| struct kvm_iommu_tlb_cookie { |
| struct kvm_hyp_iommu *iommu; |
| pkvm_handle_t domain_id; |
| struct kvm_hyp_iommu_domain *domain; |
| }; |
| |
| struct kvm_iommu_ops { |
| int (*init)(void); |
| struct kvm_hyp_iommu *(*get_iommu_by_id)(pkvm_handle_t smmu_id); |
| int (*alloc_iopt)(struct io_pgtable *iopt, unsigned long pgd_hva); |
| int (*free_iopt)(struct io_pgtable *iopt); |
| size_t (*iopt_size)(struct io_pgtable *iopt); |
| int (*attach_dev)(struct kvm_hyp_iommu *iommu, pkvm_handle_t domain_id, |
| struct kvm_hyp_iommu_domain *domain, u32 endpoint_id, u32 pasid, |
| u32 pasid_bits); |
| int (*detach_dev)(struct kvm_hyp_iommu *iommu, pkvm_handle_t domain_id, |
| struct kvm_hyp_iommu_domain *domain, u32 endpoint_id, u32 pasid); |
| int (*alloc_domain)(pkvm_handle_t iommu_id, struct io_pgtable_params **pgtable, int type); |
| }; |
| |
| extern struct kvm_iommu_ops *kvm_iommu_ops; |
| |
| #endif /* __ARM64_KVM_NVHE_IOMMU_H__ */ |