Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
iommu/arm-smmu-v3: Don't reserve implementation defined register space
Browse files Browse the repository at this point in the history
Some SMMUv3 implementation embed the Perf Monitor Group Registers (PMCG)
inside the first 64kB region of the SMMU. Since PMCG are managed by a
separate driver, this layout causes resource reservation conflicts
during boot.

To avoid this conflict, don't reserve the MMIO regions that are
implementation defined. Although devm_ioremap_resource() still works on
full pages under the hood, this way we benefit from resource conflict
checks.

Fixes: 7d839b4 ("perf/smmuv3: Add arm64 smmuv3 pmu driver")
Signed-off-by: Jean-Philippe Brucker <[email protected]>
Reviewed-by: Robin Murphy <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Will Deacon <[email protected]>
  • Loading branch information
jpbrucker authored and willdeacon committed May 18, 2020
1 parent d100ff3 commit 52f3fab
Showing 1 changed file with 31 additions and 4 deletions.
35 changes: 31 additions & 4 deletions drivers/iommu/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@
#define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
#define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc

#define ARM_SMMU_REG_SZ 0xe00

/* Common MSI config fields */
#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
#define MSI_CFG2_SH GENMASK(5, 4)
Expand Down Expand Up @@ -628,6 +630,7 @@ struct arm_smmu_strtab_cfg {
struct arm_smmu_device {
struct device *dev;
void __iomem *base;
void __iomem *page1;

#define ARM_SMMU_FEAT_2_LVL_STRTAB (1 << 0)
#define ARM_SMMU_FEAT_2_LVL_CDTAB (1 << 1)
Expand Down Expand Up @@ -733,9 +736,8 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset,
struct arm_smmu_device *smmu)
{
if ((offset > SZ_64K) &&
(smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY))
offset -= SZ_64K;
if (offset > SZ_64K)
return smmu->page1 + offset - SZ_64K;

return smmu->base + offset;
}
Expand Down Expand Up @@ -4001,6 +4003,18 @@ err_reset_pci_ops: __maybe_unused;
return err;
}

static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
resource_size_t size)
{
struct resource res = {
.flags = IORESOURCE_MEM,
.start = start,
.end = start + size - 1,
};

return devm_ioremap_resource(dev, &res);
}

static int arm_smmu_device_probe(struct platform_device *pdev)
{
int irq, ret;
Expand Down Expand Up @@ -4036,10 +4050,23 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
}
ioaddr = res->start;

smmu->base = devm_ioremap_resource(dev, res);
/*
* Don't map the IMPLEMENTATION DEFINED regions, since they may contain
* the PMCG registers which are reserved by the PMU driver.
*/
smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);

if (arm_smmu_resource_size(smmu) > SZ_64K) {
smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
ARM_SMMU_REG_SZ);
if (IS_ERR(smmu->page1))
return PTR_ERR(smmu->page1);
} else {
smmu->page1 = smmu->base;
}

/* Interrupt lines */

irq = platform_get_irq_byname_optional(pdev, "combined");
Expand Down

0 comments on commit 52f3fab

Please sign in to comment.