Introduce per-domain page sizes
Get series with b4
b4 am [email protected]Versions newest first
- v1 Latest0 of 5 patches 0 repliesNew
Patches in v1 No applies recorded yet
None of the 5 patches the cover letter announces are in this archive.
Reviews trailers per patch
No Reviewed-by, Acked-by or Tested-by trailers for v1 yet.
Cover letter [PATCH 0/5] Introduce per-domain page sizes
Hi Joerg,
Quoted 28 lines · Joerg Roedel
Quoted 27 lines · Robin Murphy
Hi all,
Since this area seems to be in vogue at the moment, here's what I was working on when the related patches[1][2] popped up, which happens to be more or less the intersection of both. As I recycled some of Will's old series as a starting point, I've retained the cleanup patches from that with their original acks - hope that's OK.
Fortunately, this already looks rather like parts of Joerg's plan[3], so I hope it's a suitable first step. Below is a quick hacked-up example of the kind of caller-controlled special use-case alluded to, using the SMMU/HDLCD combo on Juno - for a 'real' implementation of this we'd want the group-based domain allocation call so the driver could throw the device at that and get its own non-default DMA ops domain to play with.
Robin.
[1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12774 [2]:http://thread.gmane.org/gmane.linux.kernel.iommu/12901 [3]:http://article.gmane.org/gmane.linux.kernel.iommu/12937
Robin Murphy (4):
iommu: of: enforce const-ness of structiommu_ops
iommu: Allow selecting page sizes per domain iommu/dma: Finish optimising higher-order allocations iommu/arm-smmu: Use per-domain page sizes.
Quoted 6 lines
Quoted 2 lines
Will Deacon (1):
iommu: remove unused priv field from structiommu_opsOkay, I am still no happy that this lifts the requirements of the iommu-api for the arm-smmu driver. But to get there we need more core changes and this code is a step in the right direction, so I applied it.
Thanks a lot! I was expecting to pick this up again after the merge window and post an updated version then; as you may already have found, patch 5 conflicts somewhat with the SMMUv2 context format changes in Will's updates branch. The correct resolution requires a bit of rewriting, so below is what that patch looks like when rebased on top of Will's branch. If you'd prefer it in actual merge resolution format, shout and I'll give that a go.
Thanks,
Robin.
--->8---
commit a940dae4e124523bc1cf282c8f36c79f960a0805
Author: Robin Murphy <[email protected]> Date: Mon Mar 14 14:25:07 2016 +0000
iommu/arm-smmu: Use per-domain page sizes.
Now that we can accurately reflect the context format we choose for
each
domain, do that instead of imposing the global
lowest-common-denominator
restriction and potentially ending up with nothing. We currently have a strict 1:1 correspondence between domains and context banks, so we
don't
need to entertain the possibility of multiple formats _within_ a
domain.
drivers/iommu/arm-smmu-v3.c +1 -0
@@ -590,6 +590,7 @@ struct arm_smmu_device {unsigned long ias;/* IPA */ unsigned long oas;/* PA */ +unsigned long pgsize_bitmap;#define ARM_SMMU_MAX_ASIDS (1 << 16)unsigned int asid_bits;
@@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct
arm_smmu_domain *smmu_domain,
return 0;
}
-static struct iommu_ops arm_smmu_ops;
-
static int arm_smmu_domain_finalise(struct iommu_domain *domain) {
int ret;
@@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
}
pgtbl_cfg = (struct io_pgtable_cfg) {
- .pgsize_bitmap = arm_smmu_ops.pgsize_bitmap,
+ .pgsize_bitmap = smmu->pgsize_bitmap,
.ias = ias,
.oas = oas,
.tlb = &arm_smmu_gather_ops,
@@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
if (!pgtbl_ops)
return -ENOMEM;
- arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+ domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
smmu_domain->pgtbl_ops = pgtbl_ops;
ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
@@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
{
u32 reg;
bool coherent;
- unsigned long pgsize_bitmap = 0;
/* IDR0 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
/* Page sizes */
if (reg & IDR5_GRAN64K)
- pgsize_bitmap |= SZ_64K | SZ_512M;
+ smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
if (reg & IDR5_GRAN16K)
- pgsize_bitmap |= SZ_16K | SZ_32M;
+ smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
if (reg & IDR5_GRAN4K)
- pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
+ smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
- arm_smmu_ops.pgsize_bitmap &= pgsize_bitmap;
+ if (arm_smmu_ops.pgsize_bitmap == -1UL)
+ arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+ else
+ arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
/* Output address size */
switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) {
drivers/iommu/arm-smmu.c +1 -2
@@ -343,6 +343,7 @@ struct arm_smmu_device {unsigned long va_size;unsigned long ipa_size;unsigned long pa_size; +unsigned long pgsize_bitmap;u32 num_global_irqs;u32 num_context_irqs;
@@ -388,8 +389,6 @@ struct arm_smmu_domain {struct iommu_domain domain; }; -static struct iommu_ops arm_smmu_ops; -static DEFINE_SPINLOCK (arm_smmu_devices_lock);static LIST_HEAD (arm_smmu_devices);
@@ -949,7 +948,7 @@ static int arm_smmu_init_domain_context(struct
iommu_domain *domain,
}
pgtbl_cfg = (struct io_pgtable_cfg) {
- .pgsize_bitmap = arm_smmu_ops.pgsize_bitmap,
+ .pgsize_bitmap = smmu->pgsize_bitmap,
.ias = ias,
.oas = oas,
.tlb = &arm_smmu_gather_ops,
@@ -963,8 +962,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
goto out_clear_smmu;
}
- /* Update our support page sizes to reflect the page table format */
- arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+ /* Update the domain's page sizes to reflect the page table format */
+ domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
/* Initialise the context bank with our page table cfg */ arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg);
@@ -1793,19 +1792,23 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
}
/* Now we've corralled the various formats, what'll it do? */
- size = 0;
if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S)
- size |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
+ smmu->pgsize_bitmap |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
if (smmu->features &
(ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K))
- size |= SZ_4K | SZ_2M | SZ_1G;
+ smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K)
- size |= SZ_16K | SZ_32M;
+ smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K)
- size |= SZ_64K | SZ_512M;
+ smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
+
+ if (arm_smmu_ops.pgsize_bitmap == -1UL)
+ arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+ else
+ arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
+ dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n",
+ smmu->pgsize_bitmap);
- arm_smmu_ops.pgsize_bitmap &= size;
- dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size);
if (smmu->features & ARM_SMMU_FEAT_TRANS_S1)
dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n",