From 87dd5e4d384e2abe589903242baf98fea79d7c7e Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Tue, 8 Apr 2025 10:13:07 +0000 Subject: [PATCH] ANDROID: KVM: iommu: Add flags to attach_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no way to pass device specific information at attach time (to handle errata or special IOMMU configuration). Add a new argument to attach hypercalls “flags” which can be passed from the EL1 to EL2 driver to describe any driver specific information. It ‘s mandatory for devices supporting pvIOMMU, to reserve the value “0” as this is not exposed to guests and “0” would be passed. Bug: 357781595 Change-Id: I81a0b82591a0fe6d952f46025fbd95a82020c14d Signed-off-by: Mostafa Saleh --- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/hyp/include/nvhe/iommu.h | 5 +++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 ++- arch/arm64/kvm/hyp/nvhe/iommu/iommu.c | 5 +++-- arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c | 2 +- arch/arm64/kvm/iommu.c | 4 ++-- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c | 2 +- drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c | 2 +- 8 files changed, 14 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index b1ebe2b4b408..f0525c3ccb04 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1767,7 +1767,7 @@ static inline void kvm_iommu_sg_free(struct kvm_iommu_sg *sg, unsigned int nents #ifndef __KVM_NVHE_HYPERVISOR__ int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, unsigned int endpoint, unsigned int pasid, - unsigned int ssid_bits); + unsigned int ssid_bits, unsigned long flags); int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, unsigned int endpoint, unsigned int pasid); int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type); diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h index 2f20a2908369..f112d61044ed 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/iommu.h +++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h @@ -18,7 +18,8 @@ void kvm_iommu_reclaim_pages_atomic(void *p, u8 order); int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type); int kvm_iommu_free_domain(pkvm_handle_t domain_id); int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, - u32 endpoint_id, u32 pasid, u32 pasid_bits); + u32 endpoint_id, u32 pasid, u32 pasid_bits, + unsigned long flags); int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, u32 endpoint_id, u32 pasid); size_t kvm_iommu_map_pages(pkvm_handle_t domain_id, @@ -56,7 +57,7 @@ struct kvm_iommu_ops { void (*free_domain)(struct kvm_hyp_iommu_domain *domain); struct kvm_hyp_iommu *(*get_iommu_by_id)(pkvm_handle_t iommu_id); int (*attach_dev)(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain, - u32 endpoint_id, u32 pasid, u32 pasid_bits); + u32 endpoint_id, u32 pasid, u32 pasid_bits, unsigned long flags); int (*detach_dev)(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain, u32 endpoint_id, u32 pasid); int (*map_pages)(struct kvm_hyp_iommu_domain *domain, unsigned long iova, diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index d80b2bdb6561..fc3d8a4a8bba 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -1724,9 +1724,10 @@ static void handle___pkvm_host_iommu_attach_dev(struct kvm_cpu_context *host_ctx DECLARE_REG(unsigned int, endpoint, host_ctxt, 3); DECLARE_REG(unsigned int, pasid, host_ctxt, 4); DECLARE_REG(unsigned int, pasid_bits, host_ctxt, 5); + DECLARE_REG(unsigned long, flags, host_ctxt, 6); ret = kvm_iommu_attach_dev(iommu, domain, endpoint, - pasid, pasid_bits); + pasid, pasid_bits, flags); hyp_reqs_smccc_encode(ret, host_ctxt, this_cpu_ptr(&host_hyp_reqs)); } diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c index 3592c15a8a08..2b9d9ace4b36 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c @@ -387,7 +387,8 @@ int kvm_iommu_force_free_domain(pkvm_handle_t domain_id, struct pkvm_hyp_vm *vm) } int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, - u32 endpoint_id, u32 pasid, u32 pasid_bits) + u32 endpoint_id, u32 pasid, u32 pasid_bits, + unsigned long flags) { int ret; struct kvm_hyp_iommu *iommu; @@ -417,7 +418,7 @@ int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, goto out_unlock; } - ret = kvm_iommu_ops->attach_dev(iommu, domain, endpoint_id, pasid, pasid_bits); + ret = kvm_iommu_ops->attach_dev(iommu, domain, endpoint_id, pasid, pasid_bits, flags); if (ret) domain_put(domain); diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c index ddd9f9ffdee1..d634171fb61a 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c @@ -86,7 +86,7 @@ static bool pkvm_guest_iommu_attach_dev(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exi iommu_id = route.iommu; sid = route.sid; - ret = kvm_iommu_attach_dev(iommu_id, domain_id, sid, pasid, pasid_bits); + ret = kvm_iommu_attach_dev(iommu_id, domain_id, sid, pasid, pasid_bits, 0); if (ret == -ENOMEM) { /* * The driver will request memory when returning -ENOMEM, so go back to host to diff --git a/arch/arm64/kvm/iommu.c b/arch/arm64/kvm/iommu.c index 55e513eae24f..6eadb23e8271 100644 --- a/arch/arm64/kvm/iommu.c +++ b/arch/arm64/kvm/iommu.c @@ -209,10 +209,10 @@ void kvm_iommu_guest_free_mc(struct kvm_hyp_memcache *mc) /* Hypercall abstractions exposed to kernel IOMMU drivers */ int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, unsigned int endpoint, unsigned int pasid, - unsigned int ssid_bits) + unsigned int ssid_bits, unsigned long flags) { return kvm_call_hyp_nvhe_mc(__pkvm_host_iommu_attach_dev, iommu_id, domain_id, - endpoint, pasid, ssid_bits); + endpoint, pasid, ssid_bits, flags); } EXPORT_SYMBOL(kvm_iommu_attach_dev); diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c index 793c84361864..6aa47c22f3e4 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kvm.c @@ -324,7 +324,7 @@ static int kvm_arm_smmu_set_dev_pasid(struct iommu_domain *domain, int sid = fwspec->ids[i]; ret = kvm_iommu_attach_dev(host_smmu->id, kvm_smmu_domain->id, - sid, pasid, master->ssid_bits); + sid, pasid, master->ssid_bits, 0); if (ret) { dev_err(smmu->dev, "cannot attach device %s (0x%x): %d\n", dev_name(dev), sid, ret); diff --git a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c index 77d84b398142..0e43706c23e9 100644 --- a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c @@ -1246,7 +1246,7 @@ static int smmu_fix_up_domains(struct hyp_arm_smmu_v3_device *smmu, } static int smmu_attach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain, - u32 sid, u32 pasid, u32 pasid_bits) + u32 sid, u32 pasid, u32 pasid_bits, unsigned long flags) { int i; int ret;