All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Roger Pau Monné" <roger.pau@citrix.com>
To: Jiqian Chen <Jiqian.Chen@amd.com>
Cc: xen-devel@lists.xenproject.org, Huang Rui <ray.huang@amd.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Anthony PERARD <anthony.perard@vates.tech>,
	Michal Orzel <michal.orzel@amd.com>,
	Jan Beulich <jbeulich@suse.com>, Julien Grall <julien@xen.org>,
	Stefano Stabellini <sstabellini@kernel.org>
Subject: Re: [PATCH v7 4/8] vpci: Hide extended capability when it fails to initialize
Date: Mon, 21 Jul 2025 18:04:41 +0200	[thread overview]
Message-ID: <aH5lGXW19o4iD0sj@macbook.local> (raw)
In-Reply-To: <20250704070803.314366-5-Jiqian.Chen@amd.com>

On Fri, Jul 04, 2025 at 03:07:59PM +0800, Jiqian Chen wrote:
> When vpci fails to initialize a extended capability of device, it
> just returns an error and vPCI gets disabled for the whole device.
> 
> So, add function to hide extended capability when initialization
> fails. And remove the failed extended capability handler from vpci
> extended capability list.
> 
> Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
> ---
> Comment left over for the situation that "capability in 0x100 can't be removed case"
> from Jan in last version, need Roger's input.
> 
> Jan:
> Can we rely on OSes recognizing ID 0 as "just skip"?
> Since the size isn't encoded in the header, there might be issues lurking here.

I think it's the best we can aim to do TBH, I don't see any other way
to workaround this.  Size is indeed not encoded, but the next
capability pointer doesn't need to know the size of the current
capability to fetch the next one.

> ---
> cc: "Roger Pau Monné" <roger.pau@citrix.com>
> cc: Andrew Cooper <andrew.cooper3@citrix.com>
> cc: Anthony PERARD <anthony.perard@vates.tech>
> cc: Michal Orzel <michal.orzel@amd.com>
> cc: Jan Beulich <jbeulich@suse.com>
> cc: Julien Grall <julien@xen.org>
> cc: Stefano Stabellini <sstabellini@kernel.org>
> ---
> v6->v7 changes:
> * Change the pointer parameter of vpci_get_previous_ext_cap_register()
>   and vpci_ext_capability_hide() to be const.
> 
> v5->v6 changes:
> * Change to use for loop to compact code of vpci_get_previous_ext_cap_register().
> * Rename parameter rm to r in vpci_ext_capability_hide().
> * Change comment to describ the case that hide capability of position
>   0x100U.
> 
> v4->v5 changes:
> * Modify the hex digits of PCI_EXT_CAP_NEXT_MASK and PCI_EXT_CAP_NEXT to be low case.
> * Rename vpci_ext_capability_mask to vpci_ext_capability_hide.
> 
> v3->v4 changes:
> * Change definition of PCI_EXT_CAP_NEXT to be "#define PCI_EXT_CAP_NEXT(header)
>   (MASK_EXTR(header, PCI_EXT_CAP_NEXT_MASK) & 0xFFCU)" to avoid redundancy.
> * Modify the commit message.
> * Change vpci_ext_capability_mask() to return error instead of using ASSERT.
> * Set the capability ID part to be zero when we need to hide the capability of position 0x100U.
> * Add check "if ( !offset )" in vpci_ext_capability_mask().
> 
> v2->v3 changes:
> * Separated from the last version patch "vpci: Hide capability when it fails to initialize".
> * Whole implementation changed because last version is wrong.
>   This version gets target handler and previous handler from vpci->handlers, then remove the target.
> * Note: a case in function vpci_ext_capability_mask() needs to be discussed,
>   because it may change the offset of next capability when the offset of target
>   capability is 0x100U(the first extended capability), my implementation is just to
>   ignore and let hardware to handle the target capability.
> 
> v1->v2 changes:
> * Removed the "priorities" of initializing capabilities since it isn't used anymore.
> * Added new function vpci_capability_mask() and vpci_ext_capability_mask() to
>   remove failed capability from list.
> * Called vpci_make_msix_hole() in the end of init_msix().
> 
> Best regards,
> Jiqian Chen.
> ---
>  xen/drivers/vpci/vpci.c    | 88 ++++++++++++++++++++++++++++++++++++++
>  xen/include/xen/pci_regs.h |  5 ++-
>  2 files changed, 92 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
> index a91c3d4a1415..8be4b53533a3 100644
> --- a/xen/drivers/vpci/vpci.c
> +++ b/xen/drivers/vpci/vpci.c
> @@ -165,6 +165,92 @@ static int vpci_capability_hide(const struct pci_dev *pdev, unsigned int cap)
>      return 0;
>  }
>  
> +static struct vpci_register *vpci_get_previous_ext_cap_register(
> +    const struct vpci *vpci, unsigned int offset)
> +{
> +    unsigned int pos = PCI_CFG_SPACE_SIZE;
> +    struct vpci_register *r;
> +
> +    if ( offset <= PCI_CFG_SPACE_SIZE )
> +    {
> +        ASSERT_UNREACHABLE();
> +        return NULL;
> +    }
> +
> +    for ( r = vpci_get_register(vpci, pos, 4); r;
> +          r = pos > PCI_CFG_SPACE_SIZE ? vpci_get_register(vpci, pos, 4)
> +                                       : NULL )
> +    {
> +        uint32_t header = (uint32_t)(uintptr_t)r->private;
> +
> +        ASSERT(header == (uintptr_t)r->private);
> +
> +        pos = PCI_EXT_CAP_NEXT(header);
> +        if ( pos == offset )
> +            break;
> +    }
> +
> +    return r;
> +}
> +
> +static int vpci_ext_capability_hide(
> +    const struct pci_dev *pdev, unsigned int cap)
> +{
> +    const unsigned int offset = pci_find_ext_capability(pdev->sbdf, cap);
> +    struct vpci_register *r, *prev_r;
> +    struct vpci *vpci = pdev->vpci;
> +    uint32_t header, pre_header;
> +
> +    if ( offset < PCI_CFG_SPACE_SIZE )
> +    {
> +        ASSERT_UNREACHABLE();
> +        return 0;
> +    }
> +
> +    spin_lock(&vpci->lock);
> +    r = vpci_get_register(vpci, offset, 4);
> +    if ( !r )
> +    {
> +        spin_unlock(&vpci->lock);
> +        return -ENODEV;
> +    }
> +
> +    header = (uint32_t)(uintptr_t)r->private;
> +    if ( offset == PCI_CFG_SPACE_SIZE )
> +    {
> +        if ( PCI_EXT_CAP_NEXT(header) <= PCI_CFG_SPACE_SIZE )
> +            r->private = (void *)(uintptr_t)0;
> +        else
> +            /*
> +             * The first extended capability (0x100) can not be removed from
> +             * the linked list, so instead mask its capability ID to return 0
> +             * and force OSes to skip it.

s/and force/hopefully forcing/.  I think that's the best Xen can
possibly do in this situation.  Unless someone has a more reliable
idea.

With that adjusted:

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks.


  reply	other threads:[~2025-07-21 16:05 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-04  7:07 [PATCH v7 0/8] Support hiding capability when its initialization fails Jiqian Chen
2025-07-04  7:07 ` [PATCH v7 1/8] vpci/header: Emulate extended capability list for dom0 Jiqian Chen
2025-07-08 14:10   ` Jan Beulich
2025-07-09  5:29     ` Chen, Jiqian
2025-07-09  5:32       ` Jan Beulich
2025-07-09  5:34         ` Chen, Jiqian
2025-07-21 14:16           ` Roger Pau Monné
2025-07-23  6:45             ` Chen, Jiqian
2025-07-04  7:07 ` [PATCH v7 2/8] vpci: Refactor REGISTER_VPCI_INIT Jiqian Chen
2025-07-08 14:52   ` Jan Beulich
2025-07-21 14:37   ` Roger Pau Monné
2025-07-23  7:20     ` Chen, Jiqian
2025-07-23  8:19       ` Roger Pau Monné
2025-07-04  7:07 ` [PATCH v7 3/8] vpci: Hide legacy capability when it fails to initialize Jiqian Chen
2025-07-21 15:48   ` Roger Pau Monné
2025-07-23  7:33     ` Chen, Jiqian
2025-07-23  8:15       ` Roger Pau Monné
2025-07-04  7:07 ` [PATCH v7 4/8] vpci: Hide extended " Jiqian Chen
2025-07-21 16:04   ` Roger Pau Monné [this message]
2025-07-04  7:08 ` [PATCH v7 5/8] vpci: Refactor vpci_remove_register to remove matched registers Jiqian Chen
2025-07-04  7:08 ` [PATCH v7 6/8] vpci/rebar: Free Rebar resources when init_rebar() fails Jiqian Chen
2025-07-21 16:08   ` Roger Pau Monné
2025-07-04  7:08 ` [PATCH v7 7/8] vpci/msi: Free MSI resources when init_msi() fails Jiqian Chen
2025-07-08 15:13   ` Jan Beulich
2025-07-09  6:10     ` Chen, Jiqian
2025-07-09  6:49       ` Jan Beulich
2025-07-21 16:21   ` Roger Pau Monné
2025-07-23  7:54     ` Chen, Jiqian
2025-07-23  9:39       ` Jan Beulich
2025-07-04  7:08 ` [PATCH v7 8/8] vpci/msix: Free MSIX resources when init_msix() fails Jiqian Chen
2025-07-21 16:24   ` Roger Pau Monné

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=aH5lGXW19o4iD0sj@macbook.local \
    --to=roger.pau@citrix.com \
    --cc=Jiqian.Chen@amd.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=anthony.perard@vates.tech \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=ray.huang@amd.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 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.