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

Re: [RFC XEN PATCH v14 5/5] tools: Add new function to do PIRQ (un)map on PVH dom0


  • To: Anthony PERARD <anthony.perard@xxxxxxxxxx>
  • From: "Chen, Jiqian" <Jiqian.Chen@xxxxxxx>
  • Date: Wed, 4 Sep 2024 09:31:24 +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=4366na6ZGBOphdr9L6xDokpDwHCHPhE1nGPkDwL3ao4=; b=AoxxZKJOu/B1tYZvRL3PUy7n3zYFiqk6TTKXo8q+rH6S1+9gqzgxBGwCXJxsOwausy8ARI4dDyGgJcIxz8Lwm2Gxx1WLvPu2ZviOPXtKenwcLV69ftBXcKJF19R+XemKbZ3IqlWnraoLqqERsBLroEkTwp2Qavfymm9sDT/Gxo4RU+eP2p9YnT5VH+6JxtcIeoo7/3JrtJ7ve7/F0Wmwa/d3cn+9kotMAy1O6T7oWG3bqSFP6l/R1RLGqAc+6WtkRZF5J8MCjqY9kBulhysBdGplrkmB9/T6ClR6B/NAIfr70Mp+a/uJpHx1rRczZXsyKDIbkkIya2Ao/W/g2l09mw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=u3EOlFVgJr3Eds4gdYpBBuzr9e5raI2foLDZXY9POPRWWLOWed9YVaSIiYX10fLHzQYDBw5qpEfJlZ5oL//Vk5uu4wNmVn3/EQkmfivSbJZ8gPNm/OugKN93c7VQeirWfxtrU89QL1AeHCIX9/fM+Nhh9LnNt0bTG6RCKILR5GMFLZd39WYdC3l3i14MvuE0XlVMaRx51rk7RgoI6rqVk7ukdhgaoR/I336/A3DloBBZ7KRHWTu1n2iNyeqZoy3ICr4YoCntb2E3W9HStsXa+XYLtPok+OkhX4GYrJXeoVsv5xgRzXx9W+XKwBbTVenp+zNiGjYAfpy9VuydcYzrzQ==
  • 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>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, George Dunlap <gwd@xxxxxxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, "Daniel P . Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>, "Hildebrand, Stewart" <Stewart.Hildebrand@xxxxxxx>, "Chen, Jiqian" <Jiqian.Chen@xxxxxxx>, "Huang, Ray" <Ray.Huang@xxxxxxx>
  • Delivery-date: Wed, 04 Sep 2024 09:31:31 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHa/c+abfVk9KVnC0+rcXTrEz8pcbJGTmsAgAGWBIA=
  • Thread-topic: [RFC XEN PATCH v14 5/5] tools: Add new function to do PIRQ (un)map on PVH dom0

On 2024/9/4 01:16, Anthony PERARD wrote:
> On Tue, Sep 03, 2024 at 03:04:24PM +0800, Jiqian Chen wrote:
>> When dom0 is PVH, and passthrough a device to dumU, xl will
>> use the gsi number of device to do a pirq mapping, see
>> pci_add_dm_done->xc_physdev_map_pirq, but the gsi number is
>> got from file /sys/bus/pci/devices/<sbdf>/irq, that confuses
>> irq and gsi, they are in different space and are not equal,
>> so it will fail when mapping.
>> To solve this issue, use xc_physdev_gsi_from_dev to get the
> 
> The function name has changed, it's not xc_physdev_gsi_from_dev anymore
> ;-). It is always possible to write commit description without naming
> the functions that are going to be use, they are in the patch anyway.
> But, the description should be updated to reflect changes in previous
> patches.
Will change in next version, and include all your below comments, thank you 
very much!

> 
>> real gsi and add a new function xc_physdev_map_pirq_gsi to get
>> a free pirq for gsi(why not use current function
>> xc_physdev_map_pirq, because it doesn't support to allocate a
>> free pirq, what's more, to prevent changing it and affecting
>> its callers, so add xc_physdev_map_pirq_gsi).
>>
>> Besides, PVH dom0 doesn't have PIRQ flag, it doesn't do
>> PHYSDEVOP_map_pirq for each gsi. So grant function callstack
>> pci_add_dm_done->XEN_DOMCTL_irq_permission will fail at function
>> domain_pirq_to_irq. And old hypercall XEN_DOMCTL_irq_permission
>> requires passing in pirq, it is not suitable for dom0 that
>> doesn't have PIRQs to grant irq permission.
>> To solve this issue, use the new hypercall
>> XEN_DOMCTL_gsi_permission to grant the permission of irq(
>> translate from gsi) to dumU when dom0 has no PIRQs.
>>
>> Signed-off-by: Jiqian Chen <Jiqian.Chen@xxxxxxx>
>> Signed-off-by: Huang Rui <ray.huang@xxxxxxx>
>> Signed-off-by: Chen Jiqian <Jiqian.Chen@xxxxxxx>
>> ---
>> diff --git a/tools/libs/ctrl/xc_physdev.c b/tools/libs/ctrl/xc_physdev.c
>> index 460a8e779ce8..c752cd1f4410 100644
>> --- a/tools/libs/ctrl/xc_physdev.c
>> +++ b/tools/libs/ctrl/xc_physdev.c
>> @@ -95,6 +95,33 @@ int xc_physdev_map_pirq_msi(xc_interface *xch,
>>      return rc;
>>  }
>>  
>> +int xc_physdev_map_pirq_gsi(xc_interface *xch,
>> +                            uint32_t domid,
>> +                            int gsi,
>> +                            int *pirq)
>> +{
>> +    int rc;
>> +    struct physdev_map_pirq map;
>> +
>> +    if ( !pirq )
>> +    {
>> +        errno = EINVAL;
>> +        return -1;
>> +    }
>> +    memset(&map, 0, sizeof(struct physdev_map_pirq));
>> +    map.domid = domid;
>> +    map.type = MAP_PIRQ_TYPE_GSI;
>> +    map.index = gsi;
> 
> You can write instead, when declaring `map`:
> 
>     struct physdev_map_pirq map = {
>         .domid = domid,
>         .type = MAP_PIRQ_TYPE_GSI,
>         .index = gsi,
>     };
> 
> Then there's no need to call memset(), the compiler will know what to
> do.
> 
>> +    map.pirq = *pirq;
>> +
>> +    rc = do_physdev_op(xch, PHYSDEVOP_map_pirq, &map, sizeof(map));
>> +
>> +    if ( !rc )
>> +        *pirq = map.pirq;
>> +
>> +    return rc;
>> +}
>> +
>>  int xc_physdev_unmap_pirq(xc_interface *xch,
>>                            uint32_t domid,
>>                            int pirq)
>> diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
>> index 96cb4da0794e..2014a67e6e56 100644
>> --- a/tools/libs/light/libxl_pci.c
>> +++ b/tools/libs/light/libxl_pci.c
>> @@ -17,6 +17,7 @@
>>  #include "libxl_osdeps.h" /* must come before any other headers */
>>  
>>  #include "libxl_internal.h"
>> +#include "libxl_arch.h"
>>  
>>  #define PCI_BDF                "%04x:%02x:%02x.%01x"
>>  #define PCI_BDF_SHORT          "%02x:%02x.%01x"
>> @@ -1478,32 +1479,43 @@ static void pci_add_dm_done(libxl__egc *egc,
>>      fclose(f);
>>      if (!pci_supp_legacy_irq())
>>          goto out_no_irq;
>> -    sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> -                                pci->bus, pci->dev, pci->func);
>> -    f = fopen(sysfs_path, "r");
>> -    if (f == NULL) {
>> -        LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
>> -        goto out_no_irq;
>> -    }
>> -    if ((fscanf(f, "%u", &irq) == 1) && irq) {
>> -        r = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
>> -        if (r < 0) {
>> -            LOGED(ERROR, domainid, "xc_physdev_map_pirq irq=%d (error=%d)",
>> -                  irq, r);
>> -            fclose(f);
>> -            rc = ERROR_FAIL;
>> +
>> +    /* When dom0 is PVH, should use gsi to map pirq and grant permission */
>> +    rc = libxl__arch_local_domain_has_pirq_notion(gc);
>> +    if (!rc) {
> 
> Here, you can libxl__arch_local_domain_has_pirq_notion() within the if()
> condition because the function returns a bool. (Also, `rc` is for libxl
> error code, so we can make the mistake here in thinking that there an
> error code been been store.) Alternatively, you could declare "bool ok"
> and use that.
> 
> After that, it will be easier to read the condition has "if has pirq" or
> "if ok" instead of "if no error".
> 
> 
> 
>> +        rc = libxl__arch_hvm_map_gsi(gc, pci_encode_bdf(pci), domid);
>> +        if (rc) {
>> +            LOGED(ERROR, domainid, "libxl__arch_hvm_map_gsi failed");
> 
> I think LOGD() instead of LOGED() would be enough here.
> libxl__arch_hvm_map_gsi() already logs `strerror(errno)` so there's no
> need to print it again.
> 
>>              goto out;
>>          }
>> -        r = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
>> -        if (r < 0) {
>> -            LOGED(ERROR, domainid,
>> -                  "xc_domain_irq_permission irq=%d (error=%d)", irq, r);
>> -            fclose(f);
>> -            rc = ERROR_FAIL;
>> -            goto out;
>> +    } else {
>> +        sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> +                                    pci->bus, pci->dev, pci->func);
>> +        f = fopen(sysfs_path, "r");
>> +        if (f == NULL) {
>> +            LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
>> +            goto out_no_irq;
>> +        }
>> +        if ((fscanf(f, "%u", &irq) == 1) && irq) {
>> +            r = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
>> +            if (r < 0) {
>> +                LOGED(ERROR, domainid, "xc_physdev_map_pirq irq=%d 
>> (error=%d)",
>> +                    irq, r);
>> +                fclose(f);
>> +                rc = ERROR_FAIL;
>> +                goto out;
>> +            }
>> +            r = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
>> +            if (r < 0) {
>> +                LOGED(ERROR, domainid,
>> +                    "xc_domain_irq_permission irq=%d (error=%d)", irq, r);
>> +                fclose(f);
>> +                rc = ERROR_FAIL;
>> +                goto out;
>> +            }
>>          }
>> +        fclose(f);
>>      }
>> -    fclose(f);
>>  
>>      /* Don't restrict writes to the PCI config space from this VM */
>>      if (pci->permissive) {
>> @@ -2229,33 +2241,43 @@ skip_bar:
>>      if (!pci_supp_legacy_irq())
>>          goto skip_legacy_irq;
>>  
>> -    sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> -                           pci->bus, pci->dev, pci->func);
>> -
>> -    f = fopen(sysfs_path, "r");
>> -    if (f == NULL) {
>> -        LOGED(ERROR, domid, "Couldn't open %s", sysfs_path);
>> -        goto skip_legacy_irq;
>> -    }
>> +    /* When dom0 is PVH, should use gsi to unmap pirq and deny permission */
>> +    rc = libxl__arch_local_domain_has_pirq_notion(gc);
>> +    if (!rc) {
>> +        rc = libxl__arch_hvm_unmap_gsi(gc, pci_encode_bdf(pci), domid);
>> +        if (rc) {
>> +            LOGED(ERROR, domid, "libxl__arch_hvm_unmap_gsi failed");
>> +            goto out;
>> +        }
>> +    } else {
>> +        sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> +                            pci->bus, pci->dev, pci->func);
>>  
>> -    if ((fscanf(f, "%u", &irq) == 1) && irq) {
>> -        rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
>> -        if (rc < 0) {
>> -            /*
>> -             * QEMU may have already unmapped the IRQ. So the error
>> -             * may be spurious. For now, still print an error message as
>> -             * it is not easy to distinguished between valid and
>> -             * spurious error.
>> -             */
>> -            LOGED(ERROR, domid, "xc_physdev_unmap_pirq irq=%d", irq);
>> +        f = fopen(sysfs_path, "r");
>> +        if (f == NULL) {
>> +            LOGED(ERROR, domid, "Couldn't open %s", sysfs_path);
>> +            goto skip_legacy_irq;
>>          }
>> -        rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
>> -        if (rc < 0) {
>> -            LOGED(ERROR, domid, "xc_domain_irq_permission irq=%d", irq);
>> +
>> +        if ((fscanf(f, "%u", &irq) == 1) && irq) {
>> +            rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
>> +            if (rc < 0) {
>> +                /*
>> +                * QEMU may have already unmapped the IRQ. So the error
> 
> The * ...     here ^ should be aligned with the * on the previous line.
> 
>> +                * may be spurious. For now, still print an error message as
>> +                * it is not easy to distinguished between valid and
>> +                * spurious error.
>> +                */
>> +                LOGED(ERROR, domid, "xc_physdev_unmap_pirq irq=%d", irq);
>> +            }
>> +            rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
>> +            if (rc < 0) {
>> +                LOGED(ERROR, domid, "xc_domain_irq_permission irq=%d", irq);
>> +            }
>>          }
>> -    }
>>  
>> -    fclose(f);
>> +        fclose(f);
>> +    }
>>  
>>  skip_legacy_irq:
>>  
>> diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
>> index 60643d6f5376..20e3956f09b8 100644
>> --- a/tools/libs/light/libxl_x86.c
>> +++ b/tools/libs/light/libxl_x86.c
>> +int libxl__arch_hvm_map_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
>> +{
>> +    int pirq = -1, gsi, r;
>> +
>> +    gsi = xc_pcidev_get_gsi(CTX->xch, sbdf);
>> +    if (gsi < 0) {
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    r = xc_physdev_map_pirq_gsi(CTX->xch, domid, gsi, &pirq);
>> +    if (r < 0) {
>> +        LOGED(ERROR, domid, "xc_physdev_map_pirq_gsi gsi=%d ret=%d", gsi, 
>> r);
> 
> `r` should be -1, I don't think loggin it is useful..
> 
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    r = xc_domain_gsi_permission(CTX->xch, domid, gsi, 
>> XEN_DOMCTL_GSI_GRANT);
>> +    if (r < 0) {
>> +        LOGED(ERROR, domid, "xc_domain_gsi_permission gsi=%d ret=%d", gsi, 
>> r);
> 
> Same here. And in the next function.
> 
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int libxl__arch_hvm_unmap_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
>> +{
>> +    int pirq = -1, gsi, r;
>> +
>> +    gsi = xc_pcidev_get_gsi(CTX->xch, sbdf);
>> +    if (gsi < 0) {
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    /* Before unmapping, use mapping to get the already mapped pirq first */
>> +    r = xc_physdev_map_pirq_gsi(CTX->xch, domid, gsi, &pirq);
>> +    if (r < 0) {
>> +        LOGED(ERROR, domid, "xc_physdev_map_pirq_gsi gsi=%d ret=%d", gsi, 
>> r);
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    r = xc_physdev_unmap_pirq(CTX->xch, domid, pirq);
>> +    if (r < 0) {
>> +        LOGED(ERROR, domid, "xc_physdev_unmap_pirq gsi=%d ret=%d", gsi, r);
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    r = xc_domain_gsi_permission(CTX->xch, domid, gsi, 
>> XEN_DOMCTL_GSI_REVOKE);
>> +    if (r < 0) {
>> +        LOGED(ERROR, domid, "xc_domain_gsi_permission gsi=%d ret=%d", gsi, 
>> r);
>> +        return ERROR_FAIL;
>> +    }
>> +
>> +    return 0;
>> +}
> 
> 
> Thanks,
> 

-- 
Best regards,
Jiqian Chen.

 


Rackspace

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