From ea0829d44f7641874d0d22e95b0792ec58bdcbe0 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Mon, 8 Jul 2024 10:23:17 +0000 Subject: [PATCH] ANDROID: drivers/arm-smmu-v3-kvm: Support KVM_IOMMU_DOMAIN_ANY_TYPE Support KVM_IOMMU_DOMAIN_ANY_TYPE which is used for guest domains as they don't know about the SMMUv3 features. Bug: 357781595 Bug: 348382247 Bug: 236685427 Change-Id: Ife2b027e8094ed7f51a798f21c87b6c8bd0d723c Signed-off-by: Mostafa Saleh --- .../iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c | 43 +++++++++++++------ .../iommu/arm/arm-smmu-v3/pkvm/arm_smmu_v3.h | 1 + 2 files changed, 30 insertions(+), 14 deletions(-) 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 0e2d24135252..fbc0c9cdcde9 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 @@ -1231,6 +1231,31 @@ static void smmu_put_ref_domain(struct hyp_arm_smmu_v3_device *smmu, } } +static int smmu_fix_up_domains(struct hyp_arm_smmu_v3_device *smmu, + struct hyp_arm_smmu_v3_domain *smmu_domain) +{ + /* + * BYPASS domains only supported on stage-2 instances, that is over restrictive + * but for now as stage-1 is limited to VA_BITS to match the kernel, it might + * not cover the ia bits, we don't support it. + */ + if (smmu_domain->type == KVM_ARM_SMMU_DOMAIN_BYPASS) { + if (smmu->features & ARM_SMMU_FEAT_TRANS_S2) + smmu_domain->type = KVM_ARM_SMMU_DOMAIN_S2; + else + return -EINVAL; + } else if (smmu_domain->type == KVM_ARM_SMMU_DOMAIN_ANY) { + /* Any domain defaults to S1 as we don't know if the guest needs pasid. */ + if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) { + smmu_domain->type = KVM_ARM_SMMU_DOMAIN_S1; + } else { + smmu_domain->type = KVM_ARM_SMMU_DOMAIN_S2; + } + } + + return 0; +} + static int smmu_attach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain, u32 sid, u32 pasid, u32 pasid_bits) { @@ -1251,20 +1276,10 @@ static int smmu_attach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_dom goto out_unlock; } - - /* - * BYPASS domains only supported on stage-2 instances, that is over restrictive - * but for now as stage-1 is limited to VA_BITS to match the kernel, it might - * not cover the ia bits, we don't support it. - */ - if (smmu_domain->type == KVM_ARM_SMMU_DOMAIN_BYPASS) { - if (smmu->features & ARM_SMMU_FEAT_TRANS_S2) { - smmu_domain->type = KVM_ARM_SMMU_DOMAIN_S2; - } else { - ret = -EINVAL; - goto out_unlock; - } - } + /* Map domain type to an SMMUv3 stage. */ + ret = smmu_fix_up_domains(smmu, smmu_domain); + if (ret) + goto out_unlock; if (!smmu_existing_in_domain(smmu, smmu_domain)) { if (!smmu_domain_compat(smmu, smmu_domain)) { diff --git a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm_smmu_v3.h b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm_smmu_v3.h index 9565a52ddced..631b9b36613f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm_smmu_v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm_smmu_v3.h @@ -39,6 +39,7 @@ extern struct hyp_arm_smmu_v3_device *kvm_nvhe_sym(kvm_hyp_arm_smmu_v3_smmus); enum kvm_arm_smmu_domain_type { KVM_ARM_SMMU_DOMAIN_BYPASS = KVM_IOMMU_DOMAIN_IDMAP_TYPE, + KVM_ARM_SMMU_DOMAIN_ANY = KVM_IOMMU_DOMAIN_ANY_TYPE, KVM_ARM_SMMU_DOMAIN_S1, KVM_ARM_SMMU_DOMAIN_S2, KVM_ARM_SMMU_DOMAIN_MAX,