Skip to content

Commit 017040a

Browse files
committed
Merge: [RHEL10.0] Recent upstream fixes for IOMMU and DMA Engine subsystems
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/150 JIRA: https://issues.redhat.com/browse/RHEL-73411 JIRA: https://issues.redhat.com/browse/RHEL-73412 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git CVE: CVE-2024-53232 CVE: CVE-2024-56568 CVE: CVE-2024-56624 CVE: CVE-2024-56668 CVE: CVE-2024-56669 Omitted-fix: 97cb1fa This depends on some other changes, and is being marked as a fix because it removes something no longer needed once the other code is in place. I need to look at the other changes, but if they are going in, they will go in a separate MR. Recent upstream fixes for the IOMMU and DMA Engine subsystems, including: - Some fixes for dumping io page table info when a DMAR fault occurs for Intel. - Locking fix for AMD v2 page table invalidation. - Fix missed allocation for nested domains in qi batching code which could lead to null pointer dereference. - Defer client probing in arm-smmu to avoid of_dma_configure being called prior to driver_bound resulting in null pointer dereference. - Implement blocking domain for s390. - dmaengine tegra: return correct status when paused. - dmaengine dw: select only supported masters for acpi devices. All submissions to CentOS Stream must reference a ticket in [Red Hat Jira](https://issues.redhat.com/). <details><summary>Click for formatting instructions</summary> Please follow the CentOS Stream [contribution documentation](https://docs.centos.org/en-US/stream-contrib/quickstart/) for how to file this ticket and have it approved. List tickets each on their own line of this description using the format "Resolves: RHEL-1234", "Related: RHEL-2345" or "Reverts: RHEL-3456", as appropriate. </details> Signed-off-by: Jerry Snitselaar <jsnitsel@redhat.com> Approved-by: Donald Dutile <ddutile@redhat.com> Approved-by: Joel Savitz <jsavitz@redhat.com> Approved-by: Eder Zulian <ezulian@redhat.com> Approved-by: John Meneghini <jmeneghi@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Jan Stancek <jstancek@redhat.com>
2 parents 8b75f68 + e2cb62e commit 017040a

File tree

14 files changed

+156
-60
lines changed

14 files changed

+156
-60
lines changed

arch/s390/include/asm/pci.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ struct zpci_bar_struct {
9696
u8 size; /* order 2 exponent */
9797
};
9898

99-
struct s390_domain;
10099
struct kvm_zdev;
101100

102101
#define ZPCI_FUNCTIONS_PER_BUS 256
@@ -186,9 +185,10 @@ struct zpci_dev {
186185
struct dentry *debugfs_dev;
187186

188187
/* IOMMU and passthrough */
189-
struct s390_domain *s390_domain; /* s390 IOMMU domain data */
188+
struct iommu_domain *s390_domain; /* attached IOMMU domain */
190189
struct kvm_zdev *kzdev;
191190
struct mutex kzdev_lock;
191+
spinlock_t dom_lock; /* protect s390_domain change */
192192
};
193193

194194
static inline bool zdev_enabled(struct zpci_dev *zdev)

arch/s390/pci/pci.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
161161
u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE);
162162
struct zpci_iommu_ctrs *ctrs;
163163
struct zpci_fib fib = {0};
164+
unsigned long flags;
164165
u8 cc, status;
165166

166167
if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length)
@@ -172,6 +173,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
172173
WARN_ON((u64) zdev->fmb & 0xf);
173174

174175
/* reset software counters */
176+
spin_lock_irqsave(&zdev->dom_lock, flags);
175177
ctrs = zpci_get_iommu_ctrs(zdev);
176178
if (ctrs) {
177179
atomic64_set(&ctrs->mapped_pages, 0);
@@ -180,6 +182,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
180182
atomic64_set(&ctrs->sync_map_rpcits, 0);
181183
atomic64_set(&ctrs->sync_rpcits, 0);
182184
}
185+
spin_unlock_irqrestore(&zdev->dom_lock, flags);
183186

184187

185188
fib.fmb_addr = virt_to_phys(zdev->fmb);

arch/s390/pci/pci_debug.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,23 @@ static void pci_fmb_show(struct seq_file *m, char *name[], int length,
7171

7272
static void pci_sw_counter_show(struct seq_file *m)
7373
{
74-
struct zpci_iommu_ctrs *ctrs = zpci_get_iommu_ctrs(m->private);
74+
struct zpci_dev *zdev = m->private;
75+
struct zpci_iommu_ctrs *ctrs;
7576
atomic64_t *counter;
77+
unsigned long flags;
7678
int i;
7779

80+
spin_lock_irqsave(&zdev->dom_lock, flags);
81+
ctrs = zpci_get_iommu_ctrs(m->private);
7882
if (!ctrs)
79-
return;
83+
goto unlock;
8084

8185
counter = &ctrs->mapped_pages;
8286
for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
8387
seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
8488
atomic64_read(counter));
89+
unlock:
90+
spin_unlock_irqrestore(&zdev->dom_lock, flags);
8591
}
8692

8793
static int pci_perf_show(struct seq_file *m, void *v)

drivers/dma/dw/acpi.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88

99
static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
1010
{
11+
struct dw_dma *dw = to_dw_dma(chan->device);
12+
struct dw_dma_chip_pdata *data = dev_get_drvdata(dw->dma.dev);
1113
struct acpi_dma_spec *dma_spec = param;
1214
struct dw_dma_slave slave = {
1315
.dma_dev = dma_spec->dev,
1416
.src_id = dma_spec->slave_id,
1517
.dst_id = dma_spec->slave_id,
16-
.m_master = 0,
17-
.p_master = 1,
18+
.m_master = data->m_master,
19+
.p_master = data->p_master,
1820
};
1921

2022
return dw_dma_filter(chan, &slave);

drivers/dma/dw/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ struct dw_dma_chip_pdata {
5151
int (*probe)(struct dw_dma_chip *chip);
5252
int (*remove)(struct dw_dma_chip *chip);
5353
struct dw_dma_chip *chip;
54+
u8 m_master;
55+
u8 p_master;
5456
};
5557

5658
static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = {
5759
.probe = dw_dma_probe,
5860
.remove = dw_dma_remove,
61+
.m_master = 0,
62+
.p_master = 1,
5963
};
6064

6165
static const struct dw_dma_platform_data idma32_pdata = {
@@ -72,6 +76,8 @@ static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = {
7276
.pdata = &idma32_pdata,
7377
.probe = idma32_dma_probe,
7478
.remove = idma32_dma_remove,
79+
.m_master = 0,
80+
.p_master = 0,
7581
};
7682

7783
static const struct dw_dma_platform_data xbar_pdata = {
@@ -88,6 +94,8 @@ static __maybe_unused const struct dw_dma_chip_pdata xbar_chip_pdata = {
8894
.pdata = &xbar_pdata,
8995
.probe = idma32_dma_probe,
9096
.remove = idma32_dma_remove,
97+
.m_master = 0,
98+
.p_master = 0,
9199
};
92100

93101
#endif /* _DMA_DW_INTERNAL_H */

drivers/dma/dw/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
5656
if (ret)
5757
return ret;
5858

59-
dw_dma_acpi_controller_register(chip->dw);
60-
6159
pci_set_drvdata(pdev, data);
6260

61+
dw_dma_acpi_controller_register(chip->dw);
62+
6363
return 0;
6464
}
6565

drivers/dma/tegra186-gpc-dma.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ struct tegra_dma_channel {
231231
bool config_init;
232232
char name[30];
233233
enum dma_transfer_direction sid_dir;
234+
enum dma_status status;
234235
int id;
235236
int irq;
236237
int slave_id;
@@ -393,6 +394,8 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
393394
tegra_dma_dump_chan_regs(tdc);
394395
}
395396

397+
tdc->status = DMA_PAUSED;
398+
396399
return ret;
397400
}
398401

@@ -419,6 +422,8 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
419422
val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
420423
val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
421424
tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
425+
426+
tdc->status = DMA_IN_PROGRESS;
422427
}
423428

424429
static int tegra_dma_device_resume(struct dma_chan *dc)
@@ -544,6 +549,7 @@ static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
544549

545550
tegra_dma_sid_free(tdc);
546551
tdc->dma_desc = NULL;
552+
tdc->status = DMA_COMPLETE;
547553
}
548554

549555
static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc,
@@ -716,6 +722,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
716722
tdc->dma_desc = NULL;
717723
}
718724

725+
tdc->status = DMA_COMPLETE;
719726
tegra_dma_sid_free(tdc);
720727
vchan_get_all_descriptors(&tdc->vc, &head);
721728
spin_unlock_irqrestore(&tdc->vc.lock, flags);
@@ -769,6 +776,9 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
769776
if (ret == DMA_COMPLETE)
770777
return ret;
771778

779+
if (tdc->status == DMA_PAUSED)
780+
ret = DMA_PAUSED;
781+
772782
spin_lock_irqsave(&tdc->vc.lock, flags);
773783
vd = vchan_find_desc(&tdc->vc, cookie);
774784
if (vd) {

drivers/iommu/amd/io_pgtable_v2.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,11 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
268268
out:
269269
if (updated) {
270270
struct protection_domain *pdom = io_pgtable_ops_to_domain(ops);
271+
unsigned long flags;
271272

273+
spin_lock_irqsave(&pdom->lock, flags);
272274
amd_iommu_domain_flush_pages(pdom, o_iova, size);
275+
spin_unlock_irqrestore(&pdom->lock, flags);
273276
}
274277

275278
if (mapped)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,9 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)
801801
return 0;
802802
}
803803

804-
struct dentry *cmdqv_debugfs_dir;
804+
#ifdef CONFIG_IOMMU_DEBUGFS
805+
static struct dentry *cmdqv_debugfs_dir;
806+
#endif
805807

806808
static struct arm_smmu_device *
807809
__tegra241_cmdqv_probe(struct arm_smmu_device *smmu, struct resource *res,

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,17 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
14371437
goto out_free;
14381438
} else {
14391439
smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
1440+
1441+
/*
1442+
* Defer probe if the relevant SMMU instance hasn't finished
1443+
* probing yet. This is a fragile hack and we'd ideally
1444+
* avoid this race in the core code. Until that's ironed
1445+
* out, however, this is the most pragmatic option on the
1446+
* table.
1447+
*/
1448+
if (!smmu)
1449+
return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER,
1450+
"smmu dev has not bound yet\n"));
14401451
}
14411452

14421453
ret = -EINVAL;

0 commit comments

Comments
 (0)