From: Robin Murphy robin.murphy@arm.com
mainline inclusion from mainline-v6.10-rc1 commit 734554fdfce6731b22f0777ec3f1e4a853354883 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB4WDJ CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The disable_bypass parameter has been mostly meaningless for a long time since the introduction of default domains. Its original intent is now fulfilled by the controls users have over the default domain type, and its remaining effect in the brief window between Stream Table initialisation and default domain creation hardly seems worth the complication. Furthermore, thanks to 2-level Stream Tables, disabling disable_bypass (there's another reason not to like it right there) has never guaranteed that any particular StreamID *will* bypass anyway - any device which might actually care about that wants RMRs - so there's not really much lost by taking away that option (which has already been non-default for nearing 6 years now).
As part of this, also remove the weird behaviour where we "successfully" probe and register a non-functional SMMU if the DT "#iommu-cells" property is wrong. I have no memory of what possessed me to think that was a good idea at the time, and by now I suspect it's likely to break things worse than simply failing probe would.
Signed-off-by: Robin Murphy robin.murphy@arm.com Reviewed-by: Mostafa Saleh smostafa@google.com Link: https://lore.kernel.org/r/ea3ac4cd595a81b5511729601b2f7d4668178438.171233592... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Kunkun Jiang jiangkunkun@huawei.com
--------------------------------
Conflicts: drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c fce2deba0d2d4afd99cdaa700b0eacc035e71de0 (iommu/arm-smmu-v3: Add suspend and resume support) ed007ade0cef81fb47328683b8a7eec5edfa8494 (virtcca feature: secure smmu init) --- drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c | 24 +++-------- drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.h | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 43 ++++++------------- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 - 4 files changed, 19 insertions(+), 52 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c index 34e0060420af..29d4c0c71041 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.c @@ -608,25 +608,14 @@ EXPORT_SYMBOL_GPL(virtcca_smmu_map_init); * arm_s_smmu_device_enable - Enable the smmu secure state * @smmu: An SMMUv3 instance * @enables: The smmu attribute need to enable - * @bypass: Bypass smmu - * @disable_bypass: Global bypass smmu */ static void arm_s_smmu_device_enable(struct arm_smmu_device *smmu, - u32 enables, bool bypass, bool disable_bypass) + u32 enables) { int ret = 0;
- /* Enable the SMMU interface, or ensure bypass */ - if (!bypass || disable_bypass) { - enables |= CR0_SMMUEN; - } else { - ret = virtcca_smmu_update_gbpa(smmu, 0, S_GBPA_ABORT); - if (ret) { - dev_err(smmu->dev, "S_SMMU: failed to update s gbpa!\n"); - smmu->s_smmu_id = ARM_S_SMMU_INVALID_ID; - return; - } - } + /* Enable the SMMU interface */ + enables |= CR0_SMMUEN; /* Mask BIT1 and BIT4 which are RES0 in SMMU_S_CRO */ ret = virtcca_smmu_write_reg_sync(smmu, enables & ~SMMU_S_CR0_RESERVED, enables & ~SMMU_S_CR0_RESERVED, ARM_SMMU_S_CR0, ARM_SMMU_S_CR0ACK); @@ -680,10 +669,9 @@ static bool arm_s_smmu_idr1_support_secure(struct arm_smmu_device *smmu) * @smmu: An SMMUv3 instance * @ioaddr: SMMU address * @resume: Resume or not - * @disable_bypass: Global disable smmu bypass */ void virtcca_smmu_device_init(struct platform_device *pdev, struct arm_smmu_device *smmu, - resource_size_t ioaddr, bool resume, bool disable_bypass) + resource_size_t ioaddr, bool resume) { u64 rv; int ret, irq; @@ -843,6 +831,6 @@ void virtcca_smmu_device_init(struct platform_device *pdev, struct arm_smmu_devi /* Enable the secure irqs */ virtcca_smmu_setup_irqs(smmu, resume);
- /* Enable the secure smmu interface, or ensure bypass */ - arm_s_smmu_device_enable(smmu, enables, smmu->bypass, disable_bypass); + /* Enable the secure smmu interface */ + arm_s_smmu_device_enable(smmu, enables); } diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.h index 3d1786db7508..997c45a4f99a 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-s-smmu-v3.h @@ -165,7 +165,7 @@ void virtcca_smmu_cmdq_write_entries(struct arm_smmu_device *smmu, u64 *cmds, bool virtcca_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg); void _arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg); void virtcca_smmu_device_init(struct platform_device *pdev, - struct arm_smmu_device *smmu, resource_size_t ioaddr, bool resume, bool disable_bypass); + struct arm_smmu_device *smmu, resource_size_t ioaddr, bool resume);
static inline bool virtcca_smmu_enable(struct arm_smmu_device *smmu) { diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index e0193cfe433d..f0768df45d75 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -34,11 +34,6 @@ #include "arm-s-smmu-v3.h" #endif
-static bool disable_bypass = true; -module_param(disable_bypass, bool, 0444); -MODULE_PARM_DESC(disable_bypass, - "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); - static bool disable_msipolling; module_param(disable_msipolling, bool, 0444); MODULE_PARM_DESC(disable_msipolling, @@ -1801,17 +1796,13 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target, * This can safely directly manipulate the STE memory without a sync sequence * because the STE table has not been installed in the SMMU yet. */ -static void arm_smmu_init_initial_stes(struct arm_smmu_device *smmu, - struct arm_smmu_ste *strtab, +static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab, unsigned int nent) { unsigned int i;
for (i = 0; i < nent; ++i) { - if (disable_bypass) - arm_smmu_make_abort_ste(strtab); - else - arm_smmu_make_bypass_ste(smmu, strtab); + arm_smmu_make_abort_ste(strtab); strtab++; } } @@ -1839,7 +1830,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid) return -ENOMEM; }
- arm_smmu_init_initial_stes(smmu, desc->l2ptr, 1 << STRTAB_SPLIT); + arm_smmu_init_initial_stes(desc->l2ptr, 1 << STRTAB_SPLIT); arm_smmu_write_strtab_l1_desc(strtab, desc); return 0; } @@ -3207,10 +3198,10 @@ static void arm_smmu_release_device(struct device *dev) iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
/* Put the STE back to what arm_smmu_init_strtab() sets */ - if (disable_bypass && !dev->iommu->require_direct) - arm_smmu_attach_dev_blocked(&arm_smmu_blocked_domain, dev); - else + if (dev->iommu->require_direct) arm_smmu_attach_dev_identity(&arm_smmu_identity_domain, dev); + else + arm_smmu_attach_dev_blocked(&arm_smmu_blocked_domain, dev);
arm_smmu_disable_pasid(master); arm_smmu_remove_master(master); @@ -3845,7 +3836,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu) reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits); cfg->strtab_base_cfg = reg;
- arm_smmu_init_initial_stes(smmu, strtab, cfg->num_l1_ents); + arm_smmu_init_initial_stes(strtab, cfg->num_l1_ents); return 0; }
@@ -4203,7 +4194,6 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume) reg = readl_relaxed(smmu->base + ARM_SMMU_CR0); if (reg & CR0_SMMUEN) { dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n"); - WARN_ON(is_kdump_kernel() && !disable_bypass); arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0); }
@@ -4312,14 +4302,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume) if (is_kdump_kernel()) enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
- /* Enable the SMMU interface, or ensure bypass */ - if (!smmu->bypass || disable_bypass) { - enables |= CR0_SMMUEN; - } else { - ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT); - if (ret) - return ret; - } + /* Enable the SMMU interface */ + enables |= CR0_SMMUEN; ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, ARM_SMMU_CR0ACK); if (ret) { @@ -5063,12 +5047,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev) ret = arm_smmu_device_dt_probe(pdev, smmu); } else { ret = arm_smmu_device_acpi_probe(pdev, smmu); - if (ret == -ENODEV) - return ret; } - - /* Set bypass mode according to firmware probing result */ - smmu->bypass = !!ret; + if (ret) + return ret;
/* Base address */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -5137,7 +5118,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev) return ret;
#ifdef CONFIG_HISI_VIRTCCA_CODA - virtcca_smmu_device_init(pdev, smmu, ioaddr, false, disable_bypass); + virtcca_smmu_device_init(pdev, smmu, ioaddr, false); #endif
/* And we're up. Go go go! */ diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index 76487e5d55cc..e4864337054d 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -755,8 +755,6 @@ struct arm_smmu_device { struct rb_root streams; struct mutex streams_mutex;
- bool bypass; - #ifdef CONFIG_HISI_VIRTCCA_CODA int s_evtq_irq; int s_gerr_irq;