Skip to content

Commit 52f3fab

Browse files
jpbruckerwilldeacon
authored andcommitted
iommu/arm-smmu-v3: Don't reserve implementation defined register space
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]>
1 parent d100ff3 commit 52f3fab

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

drivers/iommu/arm-smmu-v3.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@
171171
#define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
172172
#define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
173173

174+
#define ARM_SMMU_REG_SZ 0xe00
175+
174176
/* Common MSI config fields */
175177
#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
176178
#define MSI_CFG2_SH GENMASK(5, 4)
@@ -628,6 +630,7 @@ struct arm_smmu_strtab_cfg {
628630
struct arm_smmu_device {
629631
struct device *dev;
630632
void __iomem *base;
633+
void __iomem *page1;
631634

632635
#define ARM_SMMU_FEAT_2_LVL_STRTAB (1 << 0)
633636
#define ARM_SMMU_FEAT_2_LVL_CDTAB (1 << 1)
@@ -733,9 +736,8 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
733736
static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset,
734737
struct arm_smmu_device *smmu)
735738
{
736-
if ((offset > SZ_64K) &&
737-
(smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY))
738-
offset -= SZ_64K;
739+
if (offset > SZ_64K)
740+
return smmu->page1 + offset - SZ_64K;
739741

740742
return smmu->base + offset;
741743
}
@@ -4001,6 +4003,18 @@ err_reset_pci_ops: __maybe_unused;
40014003
return err;
40024004
}
40034005

4006+
static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
4007+
resource_size_t size)
4008+
{
4009+
struct resource res = {
4010+
.flags = IORESOURCE_MEM,
4011+
.start = start,
4012+
.end = start + size - 1,
4013+
};
4014+
4015+
return devm_ioremap_resource(dev, &res);
4016+
}
4017+
40044018
static int arm_smmu_device_probe(struct platform_device *pdev)
40054019
{
40064020
int irq, ret;
@@ -4036,10 +4050,23 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
40364050
}
40374051
ioaddr = res->start;
40384052

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

4061+
if (arm_smmu_resource_size(smmu) > SZ_64K) {
4062+
smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
4063+
ARM_SMMU_REG_SZ);
4064+
if (IS_ERR(smmu->page1))
4065+
return PTR_ERR(smmu->page1);
4066+
} else {
4067+
smmu->page1 = smmu->base;
4068+
}
4069+
40434070
/* Interrupt lines */
40444071

40454072
irq = platform_get_irq_byname_optional(pdev, "combined");

0 commit comments

Comments
 (0)