Skip to content

Commit e3b9bf1

Browse files
committed
Merge tag 'arm-smmu-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu
Arm SMMU updates for 5.19 - Add new Qualcomm device-tree compatible strings - Add new Nvidia device-tree compatible string for Tegra234 - Fix UAF in SMMUv3 shared virtual addressing code - Force identity-mapped domains for users of ye olde SMMU legacy binding - Minor cleanups
2 parents af2d861 + 628bf55 commit e3b9bf1

File tree

7 files changed

+82
-9
lines changed

7 files changed

+82
-9
lines changed

Documentation/devicetree/bindings/iommu/arm,smmu.yaml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ properties:
3737
- qcom,sc7180-smmu-500
3838
- qcom,sc7280-smmu-500
3939
- qcom,sc8180x-smmu-500
40+
- qcom,sc8280xp-smmu-500
4041
- qcom,sdm845-smmu-500
4142
- qcom,sdx55-smmu-500
43+
- qcom,sdx65-smmu-500
4244
- qcom,sm6350-smmu-500
4345
- qcom,sm8150-smmu-500
4446
- qcom,sm8250-smmu-500
@@ -62,8 +64,9 @@ properties:
6264
for improved performance.
6365
items:
6466
- enum:
65-
- nvidia,tegra194-smmu
6667
- nvidia,tegra186-smmu
68+
- nvidia,tegra194-smmu
69+
- nvidia,tegra234-smmu
6770
- const: nvidia,smmu-500
6871
- items:
6972
- const: arm,mmu-500
@@ -157,6 +160,17 @@ properties:
157160
power-domains:
158161
maxItems: 1
159162

163+
nvidia,memory-controller:
164+
description: |
165+
A phandle to the memory controller on NVIDIA Tegra186 and later SoCs.
166+
The memory controller needs to be programmed with a mapping of memory
167+
client IDs to ARM SMMU stream IDs.
168+
169+
If this property is absent, the mapping programmed by early firmware
170+
will be used and it is not guaranteed that IOMMU translations will be
171+
enabled for any given device.
172+
$ref: /schemas/types.yaml#/definitions/phandle
173+
160174
required:
161175
- compatible
162176
- reg
@@ -172,13 +186,20 @@ allOf:
172186
compatible:
173187
contains:
174188
enum:
175-
- nvidia,tegra194-smmu
176189
- nvidia,tegra186-smmu
190+
- nvidia,tegra194-smmu
191+
- nvidia,tegra234-smmu
177192
then:
178193
properties:
179194
reg:
180195
minItems: 1
181196
maxItems: 2
197+
198+
# The reference to the memory controller is required to ensure that the
199+
# memory client to stream ID mapping can be done synchronously with the
200+
# IOMMU attachment.
201+
required:
202+
- nvidia,memory-controller
182203
else:
183204
properties:
184205
reg:

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/mm.h>
77
#include <linux/mmu_context.h>
88
#include <linux/mmu_notifier.h>
9+
#include <linux/sched/mm.h>
910
#include <linux/slab.h>
1011

1112
#include "arm-smmu-v3.h"
@@ -96,9 +97,14 @@ static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm)
9697
struct arm_smmu_ctx_desc *cd;
9798
struct arm_smmu_ctx_desc *ret = NULL;
9899

100+
/* Don't free the mm until we release the ASID */
101+
mmgrab(mm);
102+
99103
asid = arm64_mm_context_get(mm);
100-
if (!asid)
101-
return ERR_PTR(-ESRCH);
104+
if (!asid) {
105+
err = -ESRCH;
106+
goto out_drop_mm;
107+
}
102108

103109
cd = kzalloc(sizeof(*cd), GFP_KERNEL);
104110
if (!cd) {
@@ -165,6 +171,8 @@ static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm)
165171
kfree(cd);
166172
out_put_context:
167173
arm64_mm_context_put(mm);
174+
out_drop_mm:
175+
mmdrop(mm);
168176
return err < 0 ? ERR_PTR(err) : ret;
169177
}
170178

@@ -173,6 +181,7 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd)
173181
if (arm_smmu_free_asid(cd)) {
174182
/* Unpin ASID */
175183
arm64_mm_context_put(cd->mm);
184+
mmdrop(cd->mm);
176185
kfree(cd);
177186
}
178187
}
@@ -183,7 +192,14 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
183192
{
184193
struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
185194
struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
186-
size_t size = end - start + 1;
195+
size_t size;
196+
197+
/*
198+
* The mm_types defines vm_end as the first byte after the end address,
199+
* different from IOMMU subsystem using the last address of an address
200+
* range. So do a simple translation here by calculating size correctly.
201+
*/
202+
size = end - start;
187203

188204
if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM))
189205
arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,6 +3770,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
37703770

37713771
/* Base address */
37723772
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3773+
if (!res)
3774+
return -EINVAL;
37733775
if (resource_size(res) < arm_smmu_resource_size(smmu)) {
37743776
dev_err(dev, "MMIO region too small (%pr)\n", res);
37753777
return -EINVAL;

drivers/iommu/arm/arm-smmu/arm-smmu-impl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
211211
if (of_property_read_bool(np, "calxeda,smmu-secure-config-access"))
212212
smmu->impl = &calxeda_impl;
213213

214-
if (of_device_is_compatible(np, "nvidia,tegra194-smmu") ||
214+
if (of_device_is_compatible(np, "nvidia,tegra234-smmu") ||
215+
of_device_is_compatible(np, "nvidia,tegra194-smmu") ||
215216
of_device_is_compatible(np, "nvidia,tegra186-smmu"))
216217
return nvidia_smmu_impl_init(smmu);
217218

drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,34 @@ static void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct devi
258258
dev_name(dev), err);
259259
}
260260

261+
static int nvidia_smmu_init_context(struct arm_smmu_domain *smmu_domain,
262+
struct io_pgtable_cfg *pgtbl_cfg,
263+
struct device *dev)
264+
{
265+
struct arm_smmu_device *smmu = smmu_domain->smmu;
266+
const struct device_node *np = smmu->dev->of_node;
267+
268+
/*
269+
* Tegra194 and Tegra234 SoCs have the erratum that causes walk cache
270+
* entries to not be invalidated correctly. The problem is that the walk
271+
* cache index generated for IOVA is not same across translation and
272+
* invalidation requests. This is leading to page faults when PMD entry
273+
* is released during unmap and populated with new PTE table during
274+
* subsequent map request. Disabling large page mappings avoids the
275+
* release of PMD entry and avoid translations seeing stale PMD entry in
276+
* walk cache.
277+
* Fix this by limiting the page mappings to PAGE_SIZE on Tegra194 and
278+
* Tegra234.
279+
*/
280+
if (of_device_is_compatible(np, "nvidia,tegra234-smmu") ||
281+
of_device_is_compatible(np, "nvidia,tegra194-smmu")) {
282+
smmu->pgsize_bitmap = PAGE_SIZE;
283+
pgtbl_cfg->pgsize_bitmap = smmu->pgsize_bitmap;
284+
}
285+
286+
return 0;
287+
}
288+
261289
static const struct arm_smmu_impl nvidia_smmu_impl = {
262290
.read_reg = nvidia_smmu_read_reg,
263291
.write_reg = nvidia_smmu_write_reg,
@@ -268,10 +296,12 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
268296
.global_fault = nvidia_smmu_global_fault,
269297
.context_fault = nvidia_smmu_context_fault,
270298
.probe_finalize = nvidia_smmu_probe_finalize,
299+
.init_context = nvidia_smmu_init_context,
271300
};
272301

273302
static const struct arm_smmu_impl nvidia_smmu_single_impl = {
274303
.probe_finalize = nvidia_smmu_probe_finalize,
304+
.init_context = nvidia_smmu_init_context,
275305
};
276306

277307
struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)

drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = {
408408
{ .compatible = "qcom,sc7180-smmu-500" },
409409
{ .compatible = "qcom,sc7280-smmu-500" },
410410
{ .compatible = "qcom,sc8180x-smmu-500" },
411+
{ .compatible = "qcom,sc8280xp-smmu-500" },
411412
{ .compatible = "qcom,sdm630-smmu-v2" },
412413
{ .compatible = "qcom,sdm845-smmu-500" },
413414
{ .compatible = "qcom,sm6125-smmu-500" },

drivers/iommu/arm/arm-smmu/arm-smmu.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,9 @@ static int arm_smmu_def_domain_type(struct device *dev)
15741574
struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);
15751575
const struct arm_smmu_impl *impl = cfg->smmu->impl;
15761576

1577+
if (using_legacy_binding)
1578+
return IOMMU_DOMAIN_IDENTITY;
1579+
15771580
if (impl && impl->def_domain_type)
15781581
return impl->def_domain_type(dev);
15791582

@@ -2092,11 +2095,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
20922095
if (err)
20932096
return err;
20942097

2095-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2096-
ioaddr = res->start;
2097-
smmu->base = devm_ioremap_resource(dev, res);
2098+
smmu->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
20982099
if (IS_ERR(smmu->base))
20992100
return PTR_ERR(smmu->base);
2101+
ioaddr = res->start;
21002102
/*
21012103
* The resource size should effectively match the value of SMMU_TOP;
21022104
* stash that temporarily until we know PAGESIZE to validate it with.

0 commit comments

Comments
 (0)