[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
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.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |