Loading drivers/iommu/arm-smmu.c +1 −0 Original line number Diff line number Diff line Loading @@ -812,6 +812,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, return 0; out_clear_smmu: __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); smmu_domain->smmu = NULL; out_unlock: mutex_unlock(&smmu_domain->init_mutex); Loading drivers/iommu/io-pgtable-arm.c +45 −13 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ #define ARM_MALI_LPAE_TTBR_READ_INNER BIT(2) #define ARM_MALI_LPAE_TTBR_SHARE_OUTER BIT(4) #define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL #define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL /* IOPTE accessors */ #define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d)) Loading Loading @@ -1015,27 +1018,56 @@ arm_32_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) static struct io_pgtable * arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) { struct io_pgtable *iop; struct arm_lpae_io_pgtable *data; if (cfg->ias != 48 || cfg->oas > 40) /* No quirks for Mali (hopefully) */ if (cfg->quirks) return NULL; if (cfg->ias > 48 || cfg->oas > 40) return NULL; cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G); iop = arm_64_lpae_alloc_pgtable_s1(cfg, cookie); if (iop) { u64 mair, ttbr; /* Copy values as union fields overlap */ mair = cfg->arm_lpae_s1_cfg.mair[0]; ttbr = cfg->arm_lpae_s1_cfg.ttbr[0]; data = arm_lpae_alloc_pgtable(cfg); if (!data) return NULL; /* Mali seems to need a full 4-level table regardless of IAS */ if (data->levels < ARM_LPAE_MAX_LEVELS) { data->levels = ARM_LPAE_MAX_LEVELS; data->pgd_size = sizeof(arm_lpae_iopte); } /* * MEMATTR: Mali has no actual notion of a non-cacheable type, so the * best we can do is mimic the out-of-tree driver and hope that the * "implementation-defined caching policy" is good enough. Similarly, * we'll use it for the sake of a valid attribute for our 'device' * index, although callers should never request that in practice. */ cfg->arm_mali_lpae_cfg.memattr = (ARM_MALI_LPAE_MEMATTR_IMP_DEF << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_NC)) | (ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | (ARM_MALI_LPAE_MEMATTR_IMP_DEF << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV)); data->pgd = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL, cfg); if (!data->pgd) goto out_free_data; /* Ensure the empty pgd is visible before TRANSTAB can be written */ wmb(); cfg->arm_mali_lpae_cfg.memattr = mair; cfg->arm_mali_lpae_cfg.transtab = ttbr | cfg->arm_mali_lpae_cfg.transtab = virt_to_phys(data->pgd) | ARM_MALI_LPAE_TTBR_READ_INNER | ARM_MALI_LPAE_TTBR_ADRMODE_TABLE; } return &data->iop; return iop; out_free_data: kfree(data); return NULL; } struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { Loading Loading
drivers/iommu/arm-smmu.c +1 −0 Original line number Diff line number Diff line Loading @@ -812,6 +812,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, return 0; out_clear_smmu: __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); smmu_domain->smmu = NULL; out_unlock: mutex_unlock(&smmu_domain->init_mutex); Loading
drivers/iommu/io-pgtable-arm.c +45 −13 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ #define ARM_MALI_LPAE_TTBR_READ_INNER BIT(2) #define ARM_MALI_LPAE_TTBR_SHARE_OUTER BIT(4) #define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL #define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL /* IOPTE accessors */ #define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d)) Loading Loading @@ -1015,27 +1018,56 @@ arm_32_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) static struct io_pgtable * arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) { struct io_pgtable *iop; struct arm_lpae_io_pgtable *data; if (cfg->ias != 48 || cfg->oas > 40) /* No quirks for Mali (hopefully) */ if (cfg->quirks) return NULL; if (cfg->ias > 48 || cfg->oas > 40) return NULL; cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G); iop = arm_64_lpae_alloc_pgtable_s1(cfg, cookie); if (iop) { u64 mair, ttbr; /* Copy values as union fields overlap */ mair = cfg->arm_lpae_s1_cfg.mair[0]; ttbr = cfg->arm_lpae_s1_cfg.ttbr[0]; data = arm_lpae_alloc_pgtable(cfg); if (!data) return NULL; /* Mali seems to need a full 4-level table regardless of IAS */ if (data->levels < ARM_LPAE_MAX_LEVELS) { data->levels = ARM_LPAE_MAX_LEVELS; data->pgd_size = sizeof(arm_lpae_iopte); } /* * MEMATTR: Mali has no actual notion of a non-cacheable type, so the * best we can do is mimic the out-of-tree driver and hope that the * "implementation-defined caching policy" is good enough. Similarly, * we'll use it for the sake of a valid attribute for our 'device' * index, although callers should never request that in practice. */ cfg->arm_mali_lpae_cfg.memattr = (ARM_MALI_LPAE_MEMATTR_IMP_DEF << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_NC)) | (ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | (ARM_MALI_LPAE_MEMATTR_IMP_DEF << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV)); data->pgd = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL, cfg); if (!data->pgd) goto out_free_data; /* Ensure the empty pgd is visible before TRANSTAB can be written */ wmb(); cfg->arm_mali_lpae_cfg.memattr = mair; cfg->arm_mali_lpae_cfg.transtab = ttbr | cfg->arm_mali_lpae_cfg.transtab = virt_to_phys(data->pgd) | ARM_MALI_LPAE_TTBR_READ_INNER | ARM_MALI_LPAE_TTBR_ADRMODE_TABLE; } return &data->iop; return iop; out_free_data: kfree(data); return NULL; } struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { Loading