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

Re: [PATCH v1 3/3] xen/vpci: header: filter PCI capabilities


  • To: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Mon, 14 Aug 2023 16:58:03 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; 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=IxTTRlsxaVj3fTFIAi7otFLprYSJ2Iniq0rD1iMefOc=; b=Akjs4ERdJZqoJymSeIV3OfXeN5mP35Nq4xTyHcdB1O5+Bccdui4TmHAQx7REhhascJRgspHKIj86qq/cgdsmdNoQySALufG1iVDvOph+zl5Ec8khqi9yGkSQ0PoEdaarl4qxUa7GhcAMvzSwLJvvTsKRqjzTc7k35JIia53x/b8AF/V5JaPFYG0BrGRuUHQAXhDnp4TFQSgrR1bY7v5OPqXNnGdJFAFFXkcEfBrUg8OsO08cUU5XNEkv4q1N9EhxVHpeEp92WT9Xh/SbKoSB9pvHXuR0tvfal7s0E+1j6LssGooF6UPBB1KD8W73VkSzOTin+nUo9HcYN7zdsxxnlQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Xy9mgw/OnG42oGMyOPEr4qE1dNbTpSsNuSTHOCmpDj10ytRORHKXj3raGm9Sc8PkG79idoYwnj9xrxKJAwuhgfu3o/ceegwAKlULDvT1wBb01AKcVWdWBl/w5Z9CgUPHwJfxvzGpXG3PCyW6aOV8H2FO0HlouEVBFIkk1QJtMMI9KmIprkvJJAnE0lTAJ8CwQoBXwse0fzsE+Vpqx4RMKP3xWlCTJ0cPdmH+uO27XPD/OgK7jjyOPffw8KSNow9VTnwyRaNClX6LWMur839aEmPYJTCdXCGHqexOhML+ca1fcewO5qb0KiTZsbuWPwskt+H8dD4LNmajNKa1+/gJfg==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
  • Cc: Roger Pau Monné <roger.pau@xxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Mon, 14 Aug 2023 14:58:15 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 10.08.2023 21:12, Stewart Hildebrand wrote:
> Xen vPCI only supports virtualizing the MSI and MSI-X capabilities, so all 
> other
> PCI capabilities should be hidden from a domU for now.

I'm not sure about "should"; imo this would need evaluating for every cap
type separately. I'm okay though to take this as a starting point. What
needs considering (and mentioning here) is that there may be (iirc: are)
drivers which depend on being able to find/access certain capabilities.

Also - what about extended capabilities? Don't we want to hide them all
then as well (by returning 0 for the 32-bit value at 0x100)?

> --- a/xen/drivers/vpci/header.c
> +++ b/xen/drivers/vpci/header.c
> @@ -513,6 +513,36 @@ static void cf_check rom_write(
>          rom->addr = val & PCI_ROM_ADDRESS_MASK;
>  }
>  
> +static uint8_t vpci_find_next_cap(pci_sbdf_t sbdf, uint8_t pos)
> +{
> +    uint8_t id;
> +    int ttl;
> +
> +    if ( pos < 0x40 )
> +        pos = pci_conf_read8(sbdf, PCI_CAPABILITY_LIST);
> +    else
> +        pos = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_NEXT);

How about avoiding the if/else by having the caller pass in a useful
value, rather than PCI_CAPABILITY_LIST? I.e.

#define PCI_CAP_LIST_FIRST (PCI_CAPABILITY_LIST - PCI_CAP_LIST_NEXT)

> +    for ( ttl = 48; ttl > 0; ttl-- )
> +    {
> +        if ( pos < 0x40 )
> +            break;
> +
> +        pos &= ~3;
> +        id = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_ID);
> +
> +        if ( id == 0xff )
> +            break;
> +
> +        if ( id == PCI_CAP_ID_MSI ||
> +             id == PCI_CAP_ID_MSIX )
> +            return pos;

Can this please start out as switch() right away?

> +        pos = pci_conf_read8(sbdf, pos + PCI_CAP_LIST_NEXT);
> +    }
> +    return 0;
> +}

Nit: Blank line please ahead of main function return point.

I also notice that the function isn't really vPCI-specific in any way
(except for the specific PCI_CAP_ID_* compared against). Would it
perhaps make sense to have it be a general utility function, living in
xen/drivers/pci/pci.c next to its relatives?

> @@ -544,6 +574,54 @@ static int cf_check init_bars(struct pci_dev *pdev)
>      if ( rc )
>          return rc;
>  
> +    if ( !is_hardware_domain(pdev->domain) )
> +    {
> +        if ( (pci_conf_read16(pdev->sbdf, PCI_STATUS) & PCI_STATUS_CAP_LIST)
> +             == 0 )
> +        {
> +            /* RAZ/WI */
> +            rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
> +                                   PCI_CAPABILITY_LIST, 1, NULL);
> +            if ( rc )
> +                return rc;
> +        }
> +        else
> +        {
> +            /* Only expose capabilities to the guest that vPCI can handle. */
> +            uint8_t next, ttl;
> +
> +            next = vpci_find_next_cap(pdev->sbdf, PCI_CAPABILITY_LIST);
> +
> +            rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
> +                                   PCI_CAPABILITY_LIST, 1,
> +                                   (void *)(uintptr_t)next);

In vpci_find_next_cap() the low 2 bits were masked off. While reserved
at present, I wonder whether we wouldn't be better off passing them
"through".

> +            if ( rc )
> +                return rc;
> +
> +            for ( ttl = 48; ttl > 0; ttl-- )

vpci_find_next_cap() already bounds its loops; you effectively allow for
48*48 iterations here. It would seem better if the ttl applied globally,
and would hence want to be an in/out for vpci_find_next_cap().

Also note that according to ./CODING_STYLE ttl shouldn't be uint<N>_t
(this likely extends to other uses of such types here), and plain int
also isn't really appropriate for a value which can't go negative.

Jan



 


Rackspace

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