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

Re: [PATCH v7 7/8] vpci/msi: Free MSI resources when init_msi() fails


  • To: Roger Pau Monné <roger.pau@xxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>
  • From: "Chen, Jiqian" <Jiqian.Chen@xxxxxxx>
  • Date: Wed, 23 Jul 2025 07:54:46 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=7flabLh5HZZ4yVVOG4lf/ZxxgUZhthLIe+5N6Sf9MKg=; b=Vio/0Fdv4LhdsG7i6TuiK658vP4aZ9Ghz5+Znb9QhtVLhKimX4jvtsK9TLa/CQDxnIQareMKhLAVfLnlflJJ171NnBZspDmn536TeUlD2a+P2xbo5PtSodx8jAKvBcw6mQDLLObQ95g8a2EaewfNOVcmwXeCp2hlZY+CGwN3NX2DVch5g+fAM7Sb/yosEgbyf1kB12xGXkpN7Up/4hRodgX+YR1l+3GRNCSFAzK8NthuLE9oZhbD9YxQAO+PaAWqLKMtFZj+BvFnzj2E1YfmWioOLaYOc2yM9+NXGxHSPr/idjIpFSz4ibx1cPZMWs+quEhVhZ8K4f3qvU6vkhGJZw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=agI+rKt4S42e+JRHcKMUXO1pispXDP2kPesbvFBhEtqr6TtWAt6Uygl5JbrdX0Ph3do2QPU5u7T7D96HMjsqhpXP3+iE0bAyDN+3QOyZcNpa0SNryYFTD3XfRCWH5l2X4YbBvhUEukn7qn2Fz0QCL+UkKOEpKDHfOG/sQz3yFoshNWbRdUdChhcLLnDRJo2E1mGmNVd/AXyB95IFxvwABTT1RvNuSdvAEvwm0Vwv3+JAUoDAi9jDW+GWh3221vnznQs1tiUQzEtYy6n4HKxlu/VFV3tqh+bDtjI4/r7KjZ2vAit8/SIScNF047/6MoZ9wqnOTjumqXad7SrIno+UNQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amd.com;
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, "Huang, Ray" <Ray.Huang@xxxxxxx>, "Chen, Jiqian" <Jiqian.Chen@xxxxxxx>
  • Delivery-date: Wed, 23 Jul 2025 07:55:01 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHb7LJ3j2C9JyD0LUKFMd0W1xBaJrQ83ZyAgAMb8IA=
  • Thread-topic: [PATCH v7 7/8] vpci/msi: Free MSI resources when init_msi() fails

On 2025/7/22 00:21, Roger Pau Monné wrote:
> On Fri, Jul 04, 2025 at 03:08:02PM +0800, Jiqian Chen wrote:
>> When init_msi() fails, current logic return fail and free MSI-related
>> resources in vpci_deassign_device(). But the previous new changes will
>> hide MSI capability and return success, it can't reach
>> vpci_deassign_device() to remove resources if hiding success, so those
>> resources must be removed in cleanup function of MSI.
>>
>> To do that, implement cleanup function for MSI.
>>
>> Signed-off-by: Jiqian Chen <Jiqian.Chen@xxxxxxx>
>> ---
>> cc: "Roger Pau Monné" <roger.pau@xxxxxxxxxx>
>> ---
>> v6->v7 changes:
>> * Change the pointer parameter of cleanup_msi() to be const.
>> * When vpci_remove_registers() in cleanup_msi() fails, not to return
>>   directly, instead try to free msi and re-add ctrl handler.
>> * Pass pdev->vpci into vpci_add_register() instead of pdev->vpci->msi in
>>   init_msi() since we need that every handler realize that msi is NULL
>>   when msi is free but handlers are still in there.
>>
>> v5->v6 changes:
>> No.
>>
>> v4->v5 changes:
>> * Change definition "static void cleanup_msi" to "static int cf_check 
>> cleanup_msi"
>>   since cleanup hook is changed to be int.
>> * Add a read-only register for MSI Control Register in the end of 
>> cleanup_msi.
>>
>> v3->v4 changes:
>> * Change function name from fini_msi() to cleanup_msi().
>> * Remove unnecessary comment.
>> * Change to use XFREE to free vpci->msi.
>>
>> v2->v3 changes:
>> * Remove all fail path, and use fini_msi() hook instead.
>> * Change the method to calculating the size of msi registers.
>>
>> v1->v2 changes:
>> * Added a new function fini_msi to free all MSI resources instead of using 
>> an array
>>   to record registered registers.
>>
>> Best regards,
>> Jiqian Chen.
>> ---
>>  xen/drivers/vpci/msi.c | 111 ++++++++++++++++++++++++++++++++++-------
>>  1 file changed, 94 insertions(+), 17 deletions(-)
>>
>> diff --git a/xen/drivers/vpci/msi.c b/xen/drivers/vpci/msi.c
>> index c3eba4e14870..09b91a685df5 100644
>> --- a/xen/drivers/vpci/msi.c
>> +++ b/xen/drivers/vpci/msi.c
>> @@ -25,7 +25,11 @@
>>  static uint32_t cf_check control_read(
>>      const struct pci_dev *pdev, unsigned int reg, void *data)
>>  {
>> -    const struct vpci_msi *msi = data;
>> +    const struct vpci *vpci = data;
>> +    const struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return pci_conf_read16(pdev->sbdf, reg);
>>  
>>      return MASK_INSR(fls(pdev->msi_maxvec) - 1, PCI_MSI_FLAGS_QMASK) |
>>             MASK_INSR(fls(msi->vectors) - 1, PCI_MSI_FLAGS_QSIZE) |
>> @@ -37,12 +41,16 @@ static uint32_t cf_check control_read(
>>  static void cf_check control_write(
>>      const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
>>  {
>> -    struct vpci_msi *msi = data;
>> +    struct vpci *vpci = data;
>> +    struct vpci_msi *msi = vpci->msi;
>>      unsigned int vectors = min_t(uint8_t,
>>                                   1u << MASK_EXTR(val, PCI_MSI_FLAGS_QSIZE),
>>                                   pdev->msi_maxvec);
>>      bool new_enabled = val & PCI_MSI_FLAGS_ENABLE;
>>  
>> +    if ( !msi )
>> +        return;
>> +
>>      /*
>>       * No change if the enable field and the number of vectors is
>>       * the same or the device is not enabled, in which case the
>> @@ -101,7 +109,11 @@ static void update_msi(const struct pci_dev *pdev, 
>> struct vpci_msi *msi)
>>  static uint32_t cf_check address_read(
>>      const struct pci_dev *pdev, unsigned int reg, void *data)
>>  {
>> -    const struct vpci_msi *msi = data;
>> +    const struct vpci *vpci = data;
>> +    const struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return ~(uint32_t)0;
>>  
>>      return msi->address;
>>  }
>> @@ -109,7 +121,11 @@ static uint32_t cf_check address_read(
>>  static void cf_check address_write(
>>      const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
>>  {
>> -    struct vpci_msi *msi = data;
>> +    struct vpci *vpci = data;
>> +    struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return;
>>  
>>      /* Clear low part. */
>>      msi->address &= ~0xffffffffULL;
>> @@ -122,7 +138,11 @@ static void cf_check address_write(
>>  static uint32_t cf_check address_hi_read(
>>      const struct pci_dev *pdev, unsigned int reg, void *data)
>>  {
>> -    const struct vpci_msi *msi = data;
>> +    const struct vpci *vpci = data;
>> +    const struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return ~(uint32_t)0;
>>  
>>      return msi->address >> 32;
>>  }
>> @@ -130,7 +150,11 @@ static uint32_t cf_check address_hi_read(
>>  static void cf_check address_hi_write(
>>      const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
>>  {
>> -    struct vpci_msi *msi = data;
>> +    struct vpci *vpci = data;
>> +    struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return;
>>  
>>      /* Clear and update high part. */
>>      msi->address  = (uint32_t)msi->address;
>> @@ -143,7 +167,11 @@ static void cf_check address_hi_write(
>>  static uint32_t cf_check data_read(
>>      const struct pci_dev *pdev, unsigned int reg, void *data)
>>  {
>> -    const struct vpci_msi *msi = data;
>> +    const struct vpci *vpci = data;
>> +    const struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return ~(uint32_t)0;
>>  
>>      return msi->data;
>>  }
>> @@ -151,7 +179,11 @@ static uint32_t cf_check data_read(
>>  static void cf_check data_write(
>>      const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
>>  {
>> -    struct vpci_msi *msi = data;
>> +    struct vpci *vpci = data;
>> +    struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return;
>>  
>>      msi->data = val;
>>  
>> @@ -162,7 +194,11 @@ static void cf_check data_write(
>>  static uint32_t cf_check mask_read(
>>      const struct pci_dev *pdev, unsigned int reg, void *data)
>>  {
>> -    const struct vpci_msi *msi = data;
>> +    const struct vpci *vpci = data;
>> +    const struct vpci_msi *msi = vpci->msi;
>> +
>> +    if ( !msi )
>> +        return ~(uint32_t)0;
>>  
>>      return msi->mask;
>>  }
>> @@ -170,9 +206,14 @@ static uint32_t cf_check mask_read(
>>  static void cf_check mask_write(
>>      const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
>>  {
>> -    struct vpci_msi *msi = data;
>> -    uint32_t dmask = msi->mask ^ val;
>> +    struct vpci *vpci = data;
>> +    struct vpci_msi *msi = vpci->msi;
>> +    uint32_t dmask;
>> +
>> +    if ( !msi )
>> +        return;
>>  
>> +    dmask = msi->mask ^ val;
>>      if ( !dmask )
>>          return;
>>  
>> @@ -193,6 +234,42 @@ static void cf_check mask_write(
>>      msi->mask = val;
>>  }
>>  
>> +static int cf_check cleanup_msi(const struct pci_dev *pdev)
>> +{
>> +    int rc;
>> +    unsigned int end;
>> +    struct vpci *vpci = pdev->vpci;
>> +    const unsigned int msi_pos = pdev->msi_pos;
>> +    const unsigned int ctrl = msi_control_reg(msi_pos);
>> +
>> +    if ( !msi_pos || !vpci->msi )
>> +        return 0;
>> +
>> +    if ( vpci->msi->masking )
>> +        end = msi_pending_bits_reg(msi_pos, vpci->msi->address64);
>> +    else
>> +        end = msi_mask_bits_reg(msi_pos, vpci->msi->address64) - 2;
>> +
>> +    rc = vpci_remove_registers(vpci, ctrl, end - ctrl);
>> +    if ( rc )
>> +        printk(XENLOG_WARNING "%pd %pp: fail to remove MSI handlers 
>> rc=%d\n",
>> +               pdev->domain, &pdev->sbdf, rc);
> 
> I think you could possibly do this as:
> 
> if ( rc )
> {
>     printk(...);
>     ASSERT_UNREACHABLE();
>     return rc;
> }
> 
> Given the code in vpci_remove_registers() an error in the removal of
> registers would likely imply memory corruption, at which point it's
> best to fully disable the device.  That would allow you having to
> modify all the handlers to pass vpci instead of msi structs.
> 
> That will avoid a lot of the extra code churn of having to change the
> handler parameters.
OK, got it.
Since Jan proposed this consideration in v6, I need to ask for his opinion.
Hi Jan, do you fine with this change?

> 
> Thanks, Roger.

-- 
Best regards,
Jiqian Chen.

 


Rackspace

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