blob: 4cc97a2ffb791b68407e76b62fafbb9a31c24221 [file] [log] [blame] [edit]
/* 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__ */