[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v6 03/13] vpci: move lock outside of struct vpci


  • To: Oleksandr Andrushchenko <andr2000@xxxxxxxxx>, roger.pau@xxxxxxxxxx
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Fri, 4 Feb 2022 08:52:52 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=U3e1pm3Fm1Vdpk8T3tYL0kSS63VDrtItiFu6xb5gSeQ=; b=CCt5nVWT158XTXRYfGZMPnoLWSIR7tsENi1k9yKp05BdIHOhERlJwdYj9TakRLLTLxJgEqxOmjtdiOiHn4OL3PskWO66GL+1mb+o5Wov/VxOEEgO7aca8jCF/PPSTQ8qkU4hlYm8+qRa962NdyE60wIXMtfMUQ/VO2yDV6Q5d3oU1pvze2gw3xUqh2cOLzIOlNNQZKEoD2xPZ1eByM2Y/kSqoIECPeR7bNahCEWKcP1M+nFzva/uT6HD3zMRAveg2ac8nWTmiNL+PZ9GGVp6BLXSYYkr4VTduamIb1F49W1rj6w+uHpzgbGAtmn9g10SNMM/tBDeWqx2Mv9tSWWY5w==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cgRpOfS9HxFZIBnGvtrWdgdG+tP7VkJh4MnipgIEEbedUIwYw+lR2Qc7gI89su5YjYeeBzrHCzpEHNHSSGcZG1bBjia4GC01BE6jTBen5bWmkQS/K7dxHiZqQ+abVGcQxu+mJ2qkH2jPqQmYlOTKExf5umud6PzFdSnddBowRSM6mKSPvJ+2enWii6VeIDOV8qDVJV0yGfk6OlCGT4dl6WNcgkh5vH9pi+S9+NYau2T1iU7pmMSHYPiZ7aRCOMVOxuwj17NvjZSDdAmEP9JDg12QLyGk9VYdlNjiokVz9vO/PXyhL9F5BXRAT25eA1KUAEqGUMKCbhFnGpR6yRgUtQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
  • Cc: julien@xxxxxxx, sstabellini@xxxxxxxxxx, oleksandr_tyshchenko@xxxxxxxx, volodymyr_babchuk@xxxxxxxx, artem_mygaiev@xxxxxxxx, andrew.cooper3@xxxxxxxxxx, george.dunlap@xxxxxxxxxx, paul@xxxxxxx, bertrand.marquis@xxxxxxx, rahul.singh@xxxxxxx, Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Fri, 04 Feb 2022 07:53:18 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

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). 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.)

Then again this was present already even in Roger's original patch, so
I guess I must be missing something ...

> --- a/xen/drivers/vpci/msix.c
> +++ b/xen/drivers/vpci/msix.c
> @@ -138,7 +138,7 @@ static void control_write(const struct pci_dev *pdev, 
> unsigned int reg,
>          pci_conf_write16(pdev->sbdf, reg, val);
>  }
>  
> -static struct vpci_msix *msix_find(const struct domain *d, unsigned long 
> addr)
> +static struct vpci_msix *msix_get(const struct domain *d, unsigned long addr)
>  {
>      struct vpci_msix *msix;
>  
> @@ -150,15 +150,29 @@ static struct vpci_msix *msix_find(const struct domain 
> *d, unsigned long addr)
>          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) )
> +            {
> +                spin_lock(&msix->pdev->vpci_lock);
>                  return msix;
> +            }

I think deliberately returning with a lock held requires a respective
comment ahead of the function.

>      }
>  
>      return NULL;
>  }
>  
> +static void msix_put(struct vpci_msix *msix)
> +{
> +    if ( !msix )
> +        return;
> +
> +    spin_unlock(&msix->pdev->vpci_lock);
> +}

Maybe shorter

    if ( msix )
        spin_unlock(&msix->pdev->vpci_lock);

? Yet there's only one case where you may pass NULL in here, so
maybe it's better anyway to move the conditional ...

>  static int msix_accept(struct vcpu *v, unsigned long addr)
>  {
> -    return !!msix_find(v->domain, addr);
> +    struct vpci_msix *msix = msix_get(v->domain, addr);
> +
> +    msix_put(msix);
> +    return !!msix;
>  }

... here?

> @@ -186,7 +200,7 @@ static int msix_read(struct vcpu *v, unsigned long addr, 
> unsigned int len,
>                       unsigned long *data)
>  {
>      const struct domain *d = v->domain;
> -    struct vpci_msix *msix = msix_find(d, addr);
> +    struct vpci_msix *msix = msix_get(d, addr);
>      const struct vpci_msix_entry *entry;
>      unsigned int offset;
>  
> @@ -196,7 +210,10 @@ static int msix_read(struct vcpu *v, unsigned long addr, 
> unsigned int len,
>          return X86EMUL_RETRY;
>  
>      if ( !access_allowed(msix->pdev, addr, len) )
> +    {
> +        msix_put(msix);
>          return X86EMUL_OKAY;
> +    }
>  
>      if ( VMSIX_ADDR_IN_RANGE(addr, msix->pdev->vpci, VPCI_MSIX_PBA) )
>      {
> @@ -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. (I'm not sure Roger actually implied this
when suggesting to switch to the get/put pair.)

> @@ -327,7 +334,12 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, 
> unsigned int size)
>      if ( !pdev )
>          return vpci_read_hw(sbdf, reg, size);
>  
> -    spin_lock(&pdev->vpci->lock);
> +    spin_lock(&pdev->vpci_lock);
> +    if ( !pdev->vpci )
> +    {
> +        spin_unlock(&pdev->vpci_lock);
> +        return vpci_read_hw(sbdf, reg, size);
> +    }

Didn't you say you would add justification of this part of the change
(and its vpci_write() counterpart) to the description?

Jan




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.