]>
Commit | Line | Data |
---|---|---|
8ce29aad GKH |
1 | From stable+bounces-35122-greg=kroah.com@vger.kernel.org Mon Apr 1 18:53:59 2024 |
2 | From: Alex Williamson <alex.williamson@redhat.com> | |
3 | Date: Mon, 1 Apr 2024 10:52:55 -0600 | |
4 | Subject: vfio/pci: Disable auto-enable of exclusive INTx IRQ | |
5 | To: stable@vger.kernel.org | |
6 | Cc: Alex Williamson <alex.williamson@redhat.com>, sashal@kernel.org, gregkh@linuxfoundation.org, eric.auger@redhat.com, Kevin Tian <kevin.tian@intel.com> | |
7 | Message-ID: <20240401165302.3699643-2-alex.williamson@redhat.com> | |
8 | ||
9 | From: Alex Williamson <alex.williamson@redhat.com> | |
10 | ||
11 | [ Upstream commit fe9a7082684eb059b925c535682e68c34d487d43 ] | |
12 | ||
13 | Currently for devices requiring masking at the irqchip for INTx, ie. | |
14 | devices without DisINTx support, the IRQ is enabled in request_irq() | |
15 | and subsequently disabled as necessary to align with the masked status | |
16 | flag. This presents a window where the interrupt could fire between | |
17 | these events, resulting in the IRQ incrementing the disable depth twice. | |
18 | This would be unrecoverable for a user since the masked flag prevents | |
19 | nested enables through vfio. | |
20 | ||
21 | Instead, invert the logic using IRQF_NO_AUTOEN such that exclusive INTx | |
22 | is never auto-enabled, then unmask as required. | |
23 | ||
24 | Cc: <stable@vger.kernel.org> | |
25 | Fixes: 89e1f7d4c66d ("vfio: Add PCI device driver") | |
26 | Reviewed-by: Kevin Tian <kevin.tian@intel.com> | |
27 | Reviewed-by: Eric Auger <eric.auger@redhat.com> | |
28 | Link: https://lore.kernel.org/r/20240308230557.805580-2-alex.williamson@redhat.com | |
29 | Signed-off-by: Alex Williamson <alex.williamson@redhat.com> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
31 | --- | |
32 | drivers/vfio/pci/vfio_pci_intrs.c | 17 ++++++++++------- | |
33 | 1 file changed, 10 insertions(+), 7 deletions(-) | |
34 | ||
35 | --- a/drivers/vfio/pci/vfio_pci_intrs.c | |
36 | +++ b/drivers/vfio/pci/vfio_pci_intrs.c | |
37 | @@ -199,8 +199,15 @@ static int vfio_intx_set_signal(struct v | |
38 | ||
39 | vdev->ctx[0].trigger = trigger; | |
40 | ||
41 | + /* | |
42 | + * Devices without DisINTx support require an exclusive interrupt, | |
43 | + * IRQ masking is performed at the IRQ chip. The masked status is | |
44 | + * protected by vdev->irqlock. Setup the IRQ without auto-enable and | |
45 | + * unmask as necessary below under lock. DisINTx is unmodified by | |
46 | + * the IRQ configuration and may therefore use auto-enable. | |
47 | + */ | |
48 | if (!vdev->pci_2_3) | |
49 | - irqflags = 0; | |
50 | + irqflags = IRQF_NO_AUTOEN; | |
51 | ||
52 | ret = request_irq(pdev->irq, vfio_intx_handler, | |
53 | irqflags, vdev->ctx[0].name, vdev); | |
54 | @@ -211,13 +218,9 @@ static int vfio_intx_set_signal(struct v | |
55 | return ret; | |
56 | } | |
57 | ||
58 | - /* | |
59 | - * INTx disable will stick across the new irq setup, | |
60 | - * disable_irq won't. | |
61 | - */ | |
62 | spin_lock_irqsave(&vdev->irqlock, flags); | |
63 | - if (!vdev->pci_2_3 && vdev->ctx[0].masked) | |
64 | - disable_irq_nosync(pdev->irq); | |
65 | + if (!vdev->pci_2_3 && !vdev->ctx[0].masked) | |
66 | + enable_irq(pdev->irq); | |
67 | spin_unlock_irqrestore(&vdev->irqlock, flags); | |
68 | ||
69 | return 0; |