xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: "Roger Pau Monné" <roger.pau@citrix.com>
To: Oleksandr Andrushchenko <Oleksandr_Andrushchenko@epam.com>
Cc: Jan Beulich <jbeulich@suse.com>,
	"julien@xen.org" <julien@xen.org>,
	"sstabellini@kernel.org" <sstabellini@kernel.org>,
	Oleksandr Tyshchenko <Oleksandr_Tyshchenko@epam.com>,
	Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>,
	Artem Mygaiev <Artem_Mygaiev@epam.com>,
	"andrew.cooper3@citrix.com" <andrew.cooper3@citrix.com>,
	"george.dunlap@citrix.com" <george.dunlap@citrix.com>,
	"paul@xen.org" <paul@xen.org>,
	Bertrand Marquis <bertrand.marquis@arm.com>,
	Rahul Singh <rahul.singh@arm.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH v6 03/13] vpci: move lock outside of struct vpci
Date: Fri, 4 Feb 2022 11:57:30 +0100	[thread overview]
Message-ID: <Yf0Gml+2ERdcOJ5K@Air-de-Roger> (raw)
In-Reply-To: <9ed3f4ac-0a2d-ed45-9872-7c3f356a469e@epam.com>

On Fri, Feb 04, 2022 at 10:12:46AM +0000, Oleksandr Andrushchenko wrote:
> Hi, Jan!
> 
> On 04.02.22 11:15, Jan Beulich wrote:
> > On 04.02.2022 09:58, Oleksandr Andrushchenko wrote:
> >> On 04.02.22 09:52, Jan Beulich wrote:
> >>> On 04.02.2022 07:34, Oleksandr Andrushchenko wrote:
> >>>> @@ -285,6 +286,12 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only)
> >>>>                    continue;
> >>>>            }
> >>>>    
> >>>> +        spin_lock(&tmp->vpci_lock);
> >>>> +        if ( !tmp->vpci )
> >>>> +        {
> >>>> +            spin_unlock(&tmp->vpci_lock);
> >>>> +            continue;
> >>>> +        }
> >>>>            for ( i = 0; i < ARRAY_SIZE(tmp->vpci->header.bars); i++ )
> >>>>            {
> >>>>                const struct vpci_bar *bar = &tmp->vpci->header.bars[i];
> >>>> @@ -303,12 +310,14 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only)
> >>>>                rc = rangeset_remove_range(mem, start, end);
> >>>>                if ( rc )
> >>>>                {
> >>>> +                spin_unlock(&tmp->vpci_lock);
> >>>>                    printk(XENLOG_G_WARNING "Failed to remove [%lx, %lx]: %d\n",
> >>>>                           start, end, rc);
> >>>>                    rangeset_destroy(mem);
> >>>>                    return rc;
> >>>>                }
> >>>>            }
> >>>> +        spin_unlock(&tmp->vpci_lock);
> >>>>        }
> >>> At the first glance this simply looks like another unjustified (in the
> >>> description) change, as you're not converting anything here but you
> >>> actually add locking (and I realize this was there before, so I'm sorry
> >>> for not pointing this out earlier).
> >> Well, I thought that the description already has "...the lock can be
> >> used (and in a few cases is used right away) to check whether vpci
> >> is present" and this is enough for such uses as here.
> >>>    But then I wonder whether you
> >>> actually tested this, since I can't help getting the impression that
> >>> you're introducing a live-lock: The function is called from cmd_write()
> >>> and rom_write(), which in turn are called out of vpci_write(). Yet that
> >>> function already holds the lock, and the lock is not (currently)
> >>> recursive. (For the 3rd caller of the function - init_bars() - otoh
> >>> the locking looks to be entirely unnecessary.)
> >> Well, you are correct: if tmp != pdev then it is correct to acquire
> >> the lock. But if tmp == pdev and rom_only == true
> >> then we'll deadlock.
> >>
> >> It seems we need to have the locking conditional, e.g. only lock
> >> if tmp != pdev
> > Which will address the live-lock, but introduce ABBA deadlock potential
> > between the two locks.
> I am not sure I can suggest a better solution here
> @Roger, @Jan, could you please help here?

I think we could set the locking order based on the memory address of
the locks, ie:

if ( &tmp->vpci_lock < &pdev->vpci_lock )
{
    spin_unlock(&pdev->vpci_lock);
    spin_lock(&tmp->vpci_lock);
    spin_lock(&pdev->vpci_lock);
    if ( !pdev->vpci || &pdev->vpci->header != header )
        /* ERROR: vpci removed or recreated. */
}
else
    spin_lock(&tmp->vpci_lock);

That however creates a window where the address of the BARs on the
current device (pdev) could be changed, so the result of the mapping
might be skewed. I think the guest would only have itself to blame for
that, as changing the position of the BARs while toggling memory
decoding is not something sensible to do.

> >
> >>>> @@ -222,10 +239,10 @@ static int msix_read(struct vcpu *v, unsigned long addr, unsigned int len,
> >>>>                break;
> >>>>            }
> >>>>    
> >>>> +        msix_put(msix);
> >>>>            return X86EMUL_OKAY;
> >>>>        }
> >>>>    
> >>>> -    spin_lock(&msix->pdev->vpci->lock);
> >>>>        entry = get_entry(msix, addr);
> >>>>        offset = addr & (PCI_MSIX_ENTRY_SIZE - 1);
> >>> You're increasing the locked region quite a bit here. If this is really
> >>> needed, it wants explaining. And if this is deemed acceptable as a
> >>> "side effect", it wants justifying or at least stating imo. Same for
> >>> msix_write() then, obviously.
> >> Yes, I do increase the locking region here, but the msix variable needs
> >> to be protected all the time, so it seems to be obvious that it remains
> >> under the lock
> > What does the msix variable have to do with the vPCI lock? If you see
> > a need to grow the locked region here, then surely this is independent
> > of your conversion of the lock, and hence wants to be a prereq fix
> > (which may in fact want/need backporting).
> First of all, the implementation of msix_get is wrong and needs to be:
> 
> /*
>   * Note: if vpci_msix found, then this function returns with
>   * pdev->vpci_lock held. Use msix_put to unlock.
>   */
> static struct vpci_msix *msix_get(const struct domain *d, unsigned long addr)
> {
>      struct vpci_msix *msix;
> 
>      list_for_each_entry ( msix, &d->arch.hvm.msix_tables, next )

Strictly speaking you would also need to introduce a lock here to
protect msix_tables.

This was all designed when hot-adding (or removing) PCI devices to the
domain wasn't supported.

>      {
>          const struct vpci_bar *bars;
>          unsigned int i;
> 
>          spin_lock(&msix->pdev->vpci_lock);
>          if ( !msix->pdev->vpci )
>          {
>              spin_unlock(&msix->pdev->vpci_lock);
>              continue;
>          }
> 
>          bars = msix->pdev->vpci->header.bars;
>          for ( i = 0; i < ARRAY_SIZE(msix->tables); i++ )
>              if ( bars[msix->tables[i] & PCI_MSIX_BIRMASK].enabled &&
>                   VMSIX_ADDR_IN_RANGE(addr, msix->pdev->vpci, i) )
>                  return msix;
> 
>          spin_unlock(&msix->pdev->vpci_lock);
>      }
> 
>      return NULL;
> }
> 
> Then, both msix_{read|write} can dereference msix->pdev->vpci early,
> this is why Roger suggested we move to msix_{get|put} here.
> And yes, we grow the locked region here and yes this might want a
> prereq fix. Or just be fixed while at it.

Ideally yes, we would need a separate fix that introduced
msix_{get,put}, because the currently unlocked regions of
msix_{read,write} do access the BAR address fields, and doing so
without holding the vpci lock would be racy. I would expect that the
writing/reading of the addr field is done in a single instruction, so
it's unlikely to be a problem in practice. That's kind of similar to
the fact that modify_bars also accesses the addr and size fields of
remote BARs without taking the respective lock.

Once the lock is moved outside of the vpci struct and it's used to
assert that pdev->vpci is present then we do need to hold it while
accessing vpci, or else the struct could be removed under our feet.

Roger.


  parent reply	other threads:[~2022-02-04 10:58 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-04  6:34 [PATCH v6 00/13] PCI devices passthrough on Arm, part 3 Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 01/13] xen/pci: arm: add stub for is_memory_hole Oleksandr Andrushchenko
2022-02-04  8:51   ` Julien Grall
2022-02-04  9:01     ` Oleksandr Andrushchenko
2022-02-04  9:41       ` Julien Grall
2022-02-04  9:47         ` Oleksandr Andrushchenko
2022-02-04  9:57           ` Julien Grall
2022-02-04 10:35             ` Oleksandr Andrushchenko
2022-02-04 11:00               ` Julien Grall
2022-02-04 11:25                 ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 02/13] rangeset: add RANGESETF_no_print flag Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 03/13] vpci: move lock outside of struct vpci Oleksandr Andrushchenko
2022-02-04  7:52   ` Jan Beulich
2022-02-04  8:13     ` Oleksandr Andrushchenko
2022-02-04  8:36       ` Jan Beulich
2022-02-04  8:58     ` Oleksandr Andrushchenko
2022-02-04  9:15       ` Jan Beulich
2022-02-04 10:12         ` Oleksandr Andrushchenko
2022-02-04 10:49           ` Jan Beulich
2022-02-04 11:13             ` Roger Pau Monné
2022-02-04 11:37               ` Jan Beulich
2022-02-04 12:37                 ` Oleksandr Andrushchenko
2022-02-04 12:47                   ` Jan Beulich
2022-02-04 12:53                     ` Oleksandr Andrushchenko
2022-02-04 13:03                       ` Jan Beulich
2022-02-04 13:06                       ` Roger Pau Monné
2022-02-04 14:43                         ` Oleksandr Andrushchenko
2022-02-04 14:57                           ` Roger Pau Monné
2022-02-07 11:08                             ` Oleksandr Andrushchenko
2022-02-07 12:34                               ` Jan Beulich
2022-02-07 12:57                                 ` Oleksandr Andrushchenko
2022-02-07 13:02                                   ` Jan Beulich
2022-02-07 12:46                               ` Roger Pau Monné
2022-02-07 13:53                                 ` Oleksandr Andrushchenko
2022-02-07 14:11                                   ` Jan Beulich
2022-02-07 14:27                                     ` Roger Pau Monné
2022-02-07 14:33                                       ` Jan Beulich
2022-02-07 14:35                                       ` Oleksandr Andrushchenko
2022-02-07 15:11                                         ` Oleksandr Andrushchenko
2022-02-07 15:26                                           ` Jan Beulich
2022-02-07 16:07                                             ` Oleksandr Andrushchenko
2022-02-07 16:15                                               ` Jan Beulich
2022-02-07 16:21                                                 ` Oleksandr Andrushchenko
2022-02-07 16:37                                                   ` Jan Beulich
2022-02-07 16:44                                                     ` Oleksandr Andrushchenko
2022-02-08  7:35                                                       ` Oleksandr Andrushchenko
2022-02-08  8:57                                                         ` Jan Beulich
2022-02-08  9:03                                                           ` Oleksandr Andrushchenko
2022-02-08 10:50                                                         ` Roger Pau Monné
2022-02-08 11:13                                                           ` Oleksandr Andrushchenko
2022-02-08 13:38                                                             ` Roger Pau Monné
2022-02-08 13:52                                                               ` Oleksandr Andrushchenko
2022-02-08  8:53                                                       ` Jan Beulich
2022-02-08  9:00                                                         ` Oleksandr Andrushchenko
2022-02-08 10:11                                                     ` Roger Pau Monné
2022-02-08 10:32                                                       ` Oleksandr Andrushchenko
2022-02-07 16:08                                             ` Roger Pau Monné
2022-02-07 16:12                                               ` Jan Beulich
2022-02-07 14:28                                     ` Oleksandr Andrushchenko
2022-02-07 14:19                                   ` Roger Pau Monné
2022-02-07 14:27                                     ` Oleksandr Andrushchenko
2022-02-04 11:37               ` Oleksandr Andrushchenko
2022-02-04 12:15                 ` Roger Pau Monné
2022-02-04 10:57           ` Roger Pau Monné [this message]
2022-02-04  6:34 ` [PATCH v6 04/13] vpci: restrict unhandled read/write operations for guests Oleksandr Andrushchenko
2022-02-04 14:11   ` Jan Beulich
2022-02-04 14:24     ` Oleksandr Andrushchenko
2022-02-08  8:00       ` Oleksandr Andrushchenko
2022-02-08  9:04         ` Jan Beulich
2022-02-08  9:09           ` Oleksandr Andrushchenko
2022-02-08  9:05         ` Roger Pau Monné
2022-02-08  9:10           ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 05/13] vpci: add hooks for PCI device assign/de-assign Oleksandr Andrushchenko
2022-02-07 16:28   ` Jan Beulich
2022-02-08  8:32     ` Oleksandr Andrushchenko
2022-02-08  9:13       ` Jan Beulich
2022-02-08  9:27         ` Oleksandr Andrushchenko
2022-02-08  9:44           ` Jan Beulich
2022-02-08  9:55             ` Oleksandr Andrushchenko
2022-02-08 10:09               ` Jan Beulich
2022-02-08 10:22                 ` Oleksandr Andrushchenko
2022-02-08 10:29                   ` Jan Beulich
2022-02-08 10:52                     ` Oleksandr Andrushchenko
2022-02-08 11:00                       ` Jan Beulich
2022-02-08 11:25                         ` Oleksandr Andrushchenko
2022-02-10  8:21                           ` Oleksandr Andrushchenko
2022-02-10  9:22                             ` Jan Beulich
2022-02-10  9:33                               ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 06/13] vpci/header: implement guest BAR register handlers Oleksandr Andrushchenko
2022-02-07 17:06   ` Jan Beulich
2022-02-08  8:06     ` Oleksandr Andrushchenko
2022-02-08  9:16       ` Jan Beulich
2022-02-08  9:29         ` Roger Pau Monné
2022-02-08  9:25   ` Roger Pau Monné
2022-02-08  9:31     ` Oleksandr Andrushchenko
2022-02-08  9:48       ` Jan Beulich
2022-02-08  9:57         ` Oleksandr Andrushchenko
2022-02-08 10:15           ` Jan Beulich
2022-02-08 10:29             ` Oleksandr Andrushchenko
2022-02-08 13:58               ` Roger Pau Monné
2022-02-04  6:34 ` [PATCH v6 07/13] vpci/header: handle p2m range sets per BAR Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 08/13] vpci/header: program p2m with guest BAR view Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 09/13] vpci/header: emulate PCI_COMMAND register for guests Oleksandr Andrushchenko
2022-02-04 14:25   ` Jan Beulich
2022-02-08  8:13     ` Oleksandr Andrushchenko
2022-02-08  9:33       ` Jan Beulich
2022-02-08  9:38         ` Oleksandr Andrushchenko
2022-02-08  9:52           ` Jan Beulich
2022-02-08  9:58             ` Oleksandr Andrushchenko
2022-02-08 11:11               ` Roger Pau Monné
2022-02-08 11:29                 ` Oleksandr Andrushchenko
2022-02-08 14:09                   ` Roger Pau Monné
2022-02-08 14:13                     ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 10/13] vpci/header: reset the command register when adding devices Oleksandr Andrushchenko
2022-02-04 14:30   ` Jan Beulich
2022-02-04 14:37     ` Oleksandr Andrushchenko
2022-02-07  7:29       ` Jan Beulich
2022-02-07 11:27         ` Oleksandr Andrushchenko
2022-02-07 12:38           ` Jan Beulich
2022-02-07 12:51             ` Oleksandr Andrushchenko
2022-02-07 12:54               ` Jan Beulich
2022-02-07 14:17                 ` Oleksandr Andrushchenko
2022-02-07 14:31                   ` Jan Beulich
2022-02-07 14:46                     ` Oleksandr Andrushchenko
2022-02-07 15:05                       ` Jan Beulich
2022-02-07 15:14                         ` Oleksandr Andrushchenko
2022-02-07 15:28                           ` Jan Beulich
2022-02-07 15:59                             ` Oleksandr Andrushchenko
2022-02-10 12:54                     ` Oleksandr Andrushchenko
2022-02-10 13:36                       ` Jan Beulich
2022-02-10 13:56                         ` Oleksandr Andrushchenko
2022-02-10 12:59                     ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 11/13] vpci: add initial support for virtual PCI bus topology Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 12/13] xen/arm: translate virtual PCI bus topology for guests Oleksandr Andrushchenko
2022-02-04  7:56   ` Jan Beulich
2022-02-04  8:18     ` Oleksandr Andrushchenko
2022-02-04  6:34 ` [PATCH v6 13/13] xen/arm: account IO handlers for emulated PCI MSI-X Oleksandr Andrushchenko
2022-02-11 15:28   ` Julien Grall

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=Yf0Gml+2ERdcOJ5K@Air-de-Roger \
    --to=roger.pau@citrix.com \
    --cc=Artem_Mygaiev@epam.com \
    --cc=Oleksandr_Andrushchenko@epam.com \
    --cc=Oleksandr_Tyshchenko@epam.com \
    --cc=Volodymyr_Babchuk@epam.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=bertrand.marquis@arm.com \
    --cc=george.dunlap@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=paul@xen.org \
    --cc=rahul.singh@arm.com \
    --cc=sstabellini@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).