From: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
"Oleksandr Andrushchenko" <Oleksandr_Andrushchenko@epam.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Roger Pau Monné" <roger.pau@citrix.com>, "Wei Liu" <wl@xen.org>,
"George Dunlap" <george.dunlap@citrix.com>,
"Julien Grall" <julien@xen.org>, "Paul Durrant" <paul@xen.org>
Subject: Re: [RFC PATCH 07/10] xen: pci: add per-device locking
Date: Mon, 20 Feb 2023 22:29:31 +0000 [thread overview]
Message-ID: <87cz64ynqs.fsf@epam.com> (raw)
In-Reply-To: <alpine.DEB.2.22.394.2301271615330.1978264@ubuntu-linux-20-04-desktop>
Hi Stefano,
Stefano Stabellini <sstabellini@kernel.org> writes:
> On Wed, 31 Aug 2022, Volodymyr Babchuk wrote:
>> Spinlock in struct pci_device will be used to protect access to device
>> itself. Right now it is used mostly by MSI code.
>>
>> Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
>
> There are 2 instances of:
>
> BUG_ON(list_empty(&dev->msi_list));
>
> in xen/arch/x86/msi.c:__pci_disable_msi and
> xen/arch/x86/msi.c:__pci_disable_msix which are not protected by
> pcidev_lock. However list_empty needs to be protected. (pci_disable_msi
> can also be called from xen/arch/x86/irq.c where it is not surrounded by
> pcidev_lock.)
I checked all call paths. pci_disable_msi() is called from three places in
xen/arch/x86/irq.c. As I can see, all three are "protected" with
ASSERT(pcidevs_locked()), or am I missing something?
>
> Given that they are BUG_ON, I wonder if we could remove them instead of
> adding locks there. It would make things simpler.
Well, I will be happy to remove them, if there are no objections.
>
>
>> ---
>> xen/arch/x86/hvm/vmsi.c | 6 +++++-
>> xen/arch/x86/msi.c | 16 ++++++++++++++++
>> xen/drivers/passthrough/msi.c | 8 +++++++-
>> xen/drivers/passthrough/pci.c | 2 ++
>> xen/include/xen/pci.h | 12 ++++++++++++
>> 5 files changed, 42 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
>> index 7fb1075673..c9e5f279c5 100644
>> --- a/xen/arch/x86/hvm/vmsi.c
>> +++ b/xen/arch/x86/hvm/vmsi.c
>> @@ -203,10 +203,14 @@ static struct msi_desc *msixtbl_addr_to_desc(
>>
>> nr_entry = (addr - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
>>
>> + pcidev_lock(entry->pdev);
>> list_for_each_entry( desc, &entry->pdev->msi_list, list )
>> if ( desc->msi_attrib.type == PCI_CAP_ID_MSIX &&
>> - desc->msi_attrib.entry_nr == nr_entry )
>> + desc->msi_attrib.entry_nr == nr_entry ) {
>> + pcidev_unlock(entry->pdev);
>
> code style
>
>
>> return desc;
>> + }
>> + pcidev_unlock(entry->pdev);
>>
>> return NULL;
>> }
>> diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
>> index bccaccb98b..6b62c4f452 100644
>> --- a/xen/arch/x86/msi.c
>> +++ b/xen/arch/x86/msi.c
>> @@ -389,6 +389,7 @@ static bool msi_set_mask_bit(struct irq_desc *desc, bool host, bool guest)
>> default:
>> return 0;
>> }
>> +
>
> spurious change
>
>
>> entry->msi_attrib.host_masked = host;
>> entry->msi_attrib.guest_masked = guest;
>>
>> @@ -585,12 +586,17 @@ static struct msi_desc *find_msi_entry(struct pci_dev *dev,
>> {
>> struct msi_desc *entry;
>>
>> + pcidev_lock(dev);
>> list_for_each_entry( entry, &dev->msi_list, list )
>> {
>> if ( entry->msi_attrib.type == cap_id &&
>> (irq == -1 || entry->irq == irq) )
>> + {
>> + pcidev_unlock(dev);
>> return entry;
>> + }
>> }
>> + pcidev_unlock(dev);
>>
>> return NULL;
>> }
>> @@ -661,7 +667,9 @@ static int msi_capability_init(struct pci_dev *dev,
>> maskbits |= ~(uint32_t)0 >> (32 - dev->msi_maxvec);
>> pci_conf_write32(dev->sbdf, mpos, maskbits);
>> }
>> + pcidev_lock(dev);
>> list_add_tail(&entry->list, &dev->msi_list);
>> + pcidev_unlock(dev);
>>
>> *desc = entry;
>> /* Restore the original MSI enabled bits */
>> @@ -946,7 +954,9 @@ static int msix_capability_init(struct pci_dev *dev,
>>
>> pcidev_get(dev);
>>
>> + pcidev_lock(dev);
>> list_add_tail(&entry->list, &dev->msi_list);
>> + pcidev_unlock(dev);
>> *desc = entry;
>> }
>>
>> @@ -1231,11 +1241,13 @@ static void msi_free_irqs(struct pci_dev* dev)
>> {
>> struct msi_desc *entry, *tmp;
>>
>> + pcidev_lock(dev);
>> list_for_each_entry_safe( entry, tmp, &dev->msi_list, list )
>> {
>> pci_disable_msi(entry);
>> msi_free_irq(entry);
>> }
>> + pcidev_unlock(dev);
>> }
>>
>> void pci_cleanup_msi(struct pci_dev *pdev)
>> @@ -1354,6 +1366,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
>> if ( ret )
>> return ret;
>>
>> + pcidev_lock(pdev);
>> list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
>> {
>> unsigned int i = 0, nr = 1;
>> @@ -1371,6 +1384,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
>> dprintk(XENLOG_ERR, "Restore MSI for %pp entry %u not set?\n",
>> &pdev->sbdf, i);
>> spin_unlock_irqrestore(&desc->lock, flags);
>> + pcidev_unlock(pdev);
>> if ( type == PCI_CAP_ID_MSIX )
>> pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
>> control & ~PCI_MSIX_FLAGS_ENABLE);
>> @@ -1393,6 +1407,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
>> if ( unlikely(!memory_decoded(pdev)) )
>> {
>> spin_unlock_irqrestore(&desc->lock, flags);
>> + pcidev_unlock(pdev);
>> pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
>> control & ~PCI_MSIX_FLAGS_ENABLE);
>> return -ENXIO;
>> @@ -1438,6 +1453,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
>> pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
>> control | PCI_MSIX_FLAGS_ENABLE);
>>
>> + pcidev_unlock(pdev);
>> return 0;
>> }
>>
>> diff --git a/xen/drivers/passthrough/msi.c b/xen/drivers/passthrough/msi.c
>> index ce1a450f6f..98f4d2721a 100644
>> --- a/xen/drivers/passthrough/msi.c
>> +++ b/xen/drivers/passthrough/msi.c
>> @@ -22,6 +22,7 @@ int pdev_msi_init(struct pci_dev *pdev)
>> {
>> unsigned int pos;
>>
>> + pcidev_lock(pdev);
>> INIT_LIST_HEAD(&pdev->msi_list);
>>
>> pos = pci_find_cap_offset(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
>> @@ -41,7 +42,10 @@ int pdev_msi_init(struct pci_dev *pdev)
>> uint16_t ctrl;
>>
>> if ( !msix )
>> - return -ENOMEM;
>> + {
>> + pcidev_unlock(pdev);
>> + return -ENOMEM;
>> + }
>>
>> spin_lock_init(&msix->table_lock);
>>
>> @@ -51,6 +55,8 @@ int pdev_msi_init(struct pci_dev *pdev)
>> pdev->msix = msix;
>> }
>>
>> + pcidev_unlock(pdev);
>> +
>> return 0;
>> }
>>
>> diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
>> index c8da80b981..c83397211b 100644
>> --- a/xen/drivers/passthrough/pci.c
>> +++ b/xen/drivers/passthrough/pci.c
>> @@ -1383,7 +1383,9 @@ static int cf_check _dump_pci_devices(struct pci_seg *pseg, void *arg)
>> printk("%pd", pdev->domain);
>> printk(" - node %-3d refcnt %d", (pdev->node != NUMA_NO_NODE) ? pdev->node : -1,
>> atomic_read(&pdev->refcnt));
>> + pcidev_lock(pdev);
>> pdev_dump_msi(pdev);
>> + pcidev_unlock(pdev);
>> printk("\n");
>> }
>> spin_unlock(&pseg->alldevs_lock);
>> diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
>> index e71a180ef3..d0a7339d84 100644
>> --- a/xen/include/xen/pci.h
>> +++ b/xen/include/xen/pci.h
>> @@ -106,6 +106,8 @@ struct pci_dev {
>> uint8_t msi_maxvec;
>> uint8_t phantom_stride;
>>
>> + /* Device lock */
>> + spinlock_t lock;
>> nodeid_t node; /* NUMA node */
>>
>> /* Device to be quarantined, don't automatically re-assign to dom0 */
>> @@ -235,6 +237,16 @@ int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
>> void msixtbl_pt_unregister(struct domain *, struct pirq *);
>> void msixtbl_pt_cleanup(struct domain *d);
>>
>> +static inline void pcidev_lock(struct pci_dev *pdev)
>> +{
>> + spin_lock(&pdev->lock);
>> +}
>> +
>> +static inline void pcidev_unlock(struct pci_dev *pdev)
>> +{
>> + spin_unlock(&pdev->lock);
>> +}
>> +
>> #ifdef CONFIG_HVM
>> int arch_pci_clean_pirqs(struct domain *d);
>> #else
>> --
>> 2.36.1
>>
next prev parent reply other threads:[~2023-02-20 22:30 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-31 14:10 [RFC PATCH 00/10] Rework PCI locking Volodymyr Babchuk
2022-08-31 14:10 ` [RFC PATCH 01/10] xen: pci: add per-domain pci list lock Volodymyr Babchuk
2023-01-26 23:18 ` Stefano Stabellini
2023-01-27 8:01 ` Jan Beulich
2023-02-14 23:38 ` Volodymyr Babchuk
2023-02-15 9:06 ` Jan Beulich
2022-08-31 14:10 ` [RFC PATCH 04/10] xen: add reference counter support Volodymyr Babchuk
2023-02-15 11:20 ` Jan Beulich
2023-02-17 1:56 ` Volodymyr Babchuk
2023-02-17 7:53 ` Jan Beulich
2023-02-19 22:34 ` Volodymyr Babchuk
2022-08-31 14:10 ` [RFC PATCH 03/10] xen: pci: introduce ats_list_lock Volodymyr Babchuk
2023-01-26 23:56 ` Stefano Stabellini
2023-01-27 8:13 ` Jan Beulich
2023-02-17 1:20 ` Volodymyr Babchuk
2023-02-17 7:39 ` Jan Beulich
2022-08-31 14:10 ` [RFC PATCH 02/10] xen: pci: add pci_seg->alldevs_lock Volodymyr Babchuk
2023-01-26 23:40 ` Stefano Stabellini
2023-02-28 16:32 ` Jan Beulich
2022-08-31 14:11 ` [RFC PATCH 06/10] xen: pci: print reference counter when dumping pci_devs Volodymyr Babchuk
2022-08-31 14:11 ` [RFC PATCH 05/10] xen: pci: introduce reference counting for pdev Volodymyr Babchuk
2023-01-27 0:43 ` Stefano Stabellini
2023-02-20 22:00 ` Volodymyr Babchuk
2023-02-28 17:06 ` Jan Beulich
2022-08-31 14:11 ` [RFC PATCH 08/10] xen: pci: remove pcidev_[un]lock[ed] calls Volodymyr Babchuk
2023-01-28 1:32 ` Stefano Stabellini
2023-02-20 23:13 ` Volodymyr Babchuk
2023-02-21 9:50 ` Jan Beulich
2023-03-09 1:22 ` Volodymyr Babchuk
2023-03-09 9:06 ` Jan Beulich
2023-02-28 16:51 ` Jan Beulich
2022-08-31 14:11 ` [RFC PATCH 07/10] xen: pci: add per-device locking Volodymyr Babchuk
2023-01-28 0:56 ` Stefano Stabellini
2023-02-20 22:29 ` Volodymyr Babchuk [this message]
2023-02-28 16:46 ` Jan Beulich
2022-08-31 14:11 ` [RFC PATCH 09/10] [RFC only] xen: iommu: remove last pcidevs_lock() calls in iommu Volodymyr Babchuk
2023-01-28 1:36 ` Stefano Stabellini
2023-02-20 0:41 ` Volodymyr Babchuk
2023-02-28 16:25 ` Jan Beulich
2022-08-31 14:11 ` [RFC PATCH 10/10] [RFC only] xen: pci: remove pcidev_lock() function Volodymyr Babchuk
2022-09-06 10:32 ` [RFC PATCH 00/10] Rework PCI locking Jan Beulich
2023-01-18 18:21 ` Julien Grall
2023-01-19 9:47 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87cz64ynqs.fsf@epam.com \
--to=volodymyr_babchuk@epam.com \
--cc=Oleksandr_Andrushchenko@epam.com \
--cc=andrew.cooper3@citrix.com \
--cc=george.dunlap@citrix.com \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=paul@xen.org \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.org \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.