Skip to content

Commit 8164851

Browse files
committed
Merge tag 'iommu-fixes-v6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux
Pull iommu fixes from Joerg Roedel: "ARM-SMMU fixes: - Fix broken detection of the S2FWB feature - Ensure page-size bitmap is initialised for SVA domains - Fix handling of SMMU client devices with duplicate Stream IDs - Don't fail SMMU probe if Stream IDs are aliased across clients Intel VT-d fixes: - Add quirk for IGFX device - Revert an ATS change to fix a boot failure AMD IOMMU: - Fix potential buffer overflow Core: - Fix for iommu_copy_struct_from_user()" * tag 'iommu-fixes-v6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux: iommu/vt-d: Apply quirk_iommu_igfx for 8086:0044 (QM57/QS57) iommu/vt-d: Revert ATS timing change to fix boot failure iommu: Fix two issues in iommu_copy_struct_from_user() iommu/amd: Fix potential buffer overflow in parse_ivrs_acpihid iommu/arm-smmu-v3: Fail aliasing StreamIDs more gracefully iommu/arm-smmu-v3: Fix iommu_device_probe bug due to duplicated stream ids iommu/arm-smmu-v3: Fix pgsize_bit for sva domains iommu/arm-smmu-v3: Add missing S2FWB feature detection
2 parents 9910aff + 2c8a7c6 commit 8164851

File tree

5 files changed

+58
-22
lines changed

5 files changed

+58
-22
lines changed

drivers/iommu/amd/init.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,6 +3664,14 @@ static int __init parse_ivrs_acpihid(char *str)
36643664
while (*uid == '0' && *(uid + 1))
36653665
uid++;
36663666

3667+
if (strlen(hid) >= ACPIHID_HID_LEN) {
3668+
pr_err("Invalid command line: hid is too long\n");
3669+
return 1;
3670+
} else if (strlen(uid) >= ACPIHID_UID_LEN) {
3671+
pr_err("Invalid command line: uid is too long\n");
3672+
return 1;
3673+
}
3674+
36673675
i = early_acpihid_map_size++;
36683676
memcpy(early_acpihid_map[i].hid, hid, strlen(hid));
36693677
memcpy(early_acpihid_map[i].uid, uid, strlen(uid));

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
411411
return ERR_CAST(smmu_domain);
412412
smmu_domain->domain.type = IOMMU_DOMAIN_SVA;
413413
smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
414+
415+
/*
416+
* Choose page_size as the leaf page size for invalidation when
417+
* ARM_SMMU_FEAT_RANGE_INV is present
418+
*/
419+
smmu_domain->domain.pgsize_bitmap = PAGE_SIZE;
414420
smmu_domain->smmu = smmu;
415421

416422
ret = xa_alloc(&arm_smmu_asid_xa, &asid, smmu_domain,

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,7 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
33883388
mutex_lock(&smmu->streams_mutex);
33893389
for (i = 0; i < fwspec->num_ids; i++) {
33903390
struct arm_smmu_stream *new_stream = &master->streams[i];
3391+
struct rb_node *existing;
33913392
u32 sid = fwspec->ids[i];
33923393

33933394
new_stream->id = sid;
@@ -3398,11 +3399,21 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
33983399
break;
33993400

34003401
/* Insert into SID tree */
3401-
if (rb_find_add(&new_stream->node, &smmu->streams,
3402-
arm_smmu_streams_cmp_node)) {
3403-
dev_warn(master->dev, "stream %u already in tree\n",
3404-
sid);
3405-
ret = -EINVAL;
3402+
existing = rb_find_add(&new_stream->node, &smmu->streams,
3403+
arm_smmu_streams_cmp_node);
3404+
if (existing) {
3405+
struct arm_smmu_master *existing_master =
3406+
rb_entry(existing, struct arm_smmu_stream, node)
3407+
->master;
3408+
3409+
/* Bridged PCI devices may end up with duplicated IDs */
3410+
if (existing_master == master)
3411+
continue;
3412+
3413+
dev_warn(master->dev,
3414+
"Aliasing StreamID 0x%x (from %s) unsupported, expect DMA to be broken\n",
3415+
sid, dev_name(existing_master->dev));
3416+
ret = -ENODEV;
34063417
break;
34073418
}
34083419
}
@@ -4429,6 +4440,8 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
44294440
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3);
44304441
if (FIELD_GET(IDR3_RIL, reg))
44314442
smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
4443+
if (FIELD_GET(IDR3_FWB, reg))
4444+
smmu->features |= ARM_SMMU_FEAT_S2FWB;
44324445

44334446
/* IDR5 */
44344447
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);

drivers/iommu/intel/iommu.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3785,29 +3785,35 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
37853785

37863786
intel_iommu_debugfs_create_dev(info);
37873787

3788+
return &iommu->iommu;
3789+
free_table:
3790+
intel_pasid_free_table(dev);
3791+
clear_rbtree:
3792+
device_rbtree_remove(info);
3793+
free:
3794+
kfree(info);
3795+
3796+
return ERR_PTR(ret);
3797+
}
3798+
3799+
static void intel_iommu_probe_finalize(struct device *dev)
3800+
{
3801+
struct device_domain_info *info = dev_iommu_priv_get(dev);
3802+
struct intel_iommu *iommu = info->iommu;
3803+
37883804
/*
37893805
* The PCIe spec, in its wisdom, declares that the behaviour of the
37903806
* device is undefined if you enable PASID support after ATS support.
37913807
* So always enable PASID support on devices which have it, even if
37923808
* we can't yet know if we're ever going to use it.
37933809
*/
37943810
if (info->pasid_supported &&
3795-
!pci_enable_pasid(pdev, info->pasid_supported & ~1))
3811+
!pci_enable_pasid(to_pci_dev(dev), info->pasid_supported & ~1))
37963812
info->pasid_enabled = 1;
37973813

3798-
if (sm_supported(iommu))
3814+
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev))
37993815
iommu_enable_pci_ats(info);
38003816
iommu_enable_pci_pri(info);
3801-
3802-
return &iommu->iommu;
3803-
free_table:
3804-
intel_pasid_free_table(dev);
3805-
clear_rbtree:
3806-
device_rbtree_remove(info);
3807-
free:
3808-
kfree(info);
3809-
3810-
return ERR_PTR(ret);
38113817
}
38123818

38133819
static void intel_iommu_release_device(struct device *dev)
@@ -4391,6 +4397,7 @@ const struct iommu_ops intel_iommu_ops = {
43914397
.domain_alloc_sva = intel_svm_domain_alloc,
43924398
.domain_alloc_nested = intel_iommu_domain_alloc_nested,
43934399
.probe_device = intel_iommu_probe_device,
4400+
.probe_finalize = intel_iommu_probe_finalize,
43944401
.release_device = intel_iommu_release_device,
43954402
.get_resv_regions = intel_iommu_get_resv_regions,
43964403
.device_group = intel_iommu_device_group,
@@ -4432,6 +4439,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_igfx);
44324439
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_igfx);
44334440
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_igfx);
44344441

4442+
/* QM57/QS57 integrated gfx malfunctions with dmar */
4443+
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_iommu_igfx);
4444+
44354445
/* Broadwell igfx malfunctions with dmar */
44364446
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1606, quirk_iommu_igfx);
44374447
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160B, quirk_iommu_igfx);
@@ -4509,7 +4519,6 @@ static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
45094519
}
45104520
}
45114521
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4512-
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
45134522
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
45144523
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
45154524

include/linux/iommu.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,10 +440,10 @@ static inline int __iommu_copy_struct_from_user(
440440
void *dst_data, const struct iommu_user_data *src_data,
441441
unsigned int data_type, size_t data_len, size_t min_len)
442442
{
443-
if (src_data->type != data_type)
444-
return -EINVAL;
445443
if (WARN_ON(!dst_data || !src_data))
446444
return -EINVAL;
445+
if (src_data->type != data_type)
446+
return -EINVAL;
447447
if (src_data->len < min_len || data_len < src_data->len)
448448
return -EINVAL;
449449
return copy_struct_from_user(dst_data, data_len, src_data->uptr,
@@ -456,8 +456,8 @@ static inline int __iommu_copy_struct_from_user(
456456
* include/uapi/linux/iommufd.h
457457
* @user_data: Pointer to a struct iommu_user_data for user space data info
458458
* @data_type: The data type of the @kdst. Must match with @user_data->type
459-
* @min_last: The last memember of the data structure @kdst points in the
460-
* initial version.
459+
* @min_last: The last member of the data structure @kdst points in the initial
460+
* version.
461461
* Return 0 for success, otherwise -error.
462462
*/
463463
#define iommu_copy_struct_from_user(kdst, user_data, data_type, min_last) \

0 commit comments

Comments
 (0)