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 <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2024-07-08 10:23:17 +00:00
committed by Carlos Llamas
parent 38ab8e61f9
commit ea0829d44f
2 changed files with 30 additions and 14 deletions
@@ -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)) {
@@ -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,