[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xl: Implement PCI passthrough force removal
# HG changeset patch # User Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> # Date 1286383095 -3600 # Node ID 1385b15e168f682d3c5593c78eaab89d501c4524 # Parent 02e199c96ece5d2853514a14ce7407fd8167ae47 xl: Implement PCI passthrough force removal This fixes two errors with removing PCI devices from HVM domains. The first error is that the handling of "pci-rem" device-model command is erroneously implemented in qemu and difficult (impossible?) to get right. For example, during domain shutdown there can be a race where the guest OS unloads it's drivers and perhaps even shuts down PCI subsystem before the pci-rem command has been received by qemu. This means that no OS is present to write to the port which causes the dm command to be acknowledged. We fix this by implementing a 'force removal' option to libxl_device_pci_remove which is always set to 1 during guest shutdown. It can be optionally enabled on the xl command line for other occasions. The second error is that if a guest OS doesn't respond to the SCI interrupt and therefore the pci-rem dm command, which can happen if the guest OS has no ACPI PCI hotplug support, then device removal bails with an error but only AFTER removing the device from xenstore. This means that xenstore gets in to an inconsistent state where an assigned device also appears to be assignable. This is fixed by moving xenstore device removal to occur only after the device has really been removed. Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> committer: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- tools/libxl/libxl.h | 2 +- tools/libxl/libxl_pci.c | 39 +++++++++++++++++++++++++-------------- tools/libxl/xl_cmdimpl.c | 12 ++++++++---- 3 files changed, 34 insertions(+), 19 deletions(-) diff -r 02e199c96ece -r 1385b15e168f tools/libxl/libxl.h --- a/tools/libxl/libxl.h Wed Oct 06 11:00:19 2010 +0100 +++ b/tools/libxl/libxl.h Wed Oct 06 17:38:15 2010 +0100 @@ -406,7 +406,7 @@ int libxl_device_vfb_hard_shutdown(libxl int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid); int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev); -int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev); +int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int force); int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid); int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, uint32_t domid, int *num); int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, int *num); diff -r 02e199c96ece -r 1385b15e168f tools/libxl/libxl_pci.c --- a/tools/libxl/libxl_pci.c Wed Oct 06 11:00:19 2010 +0100 +++ b/tools/libxl/libxl_pci.c Wed Oct 06 17:38:15 2010 +0100 @@ -841,7 +841,8 @@ out: return rc; } -static int do_pci_remove(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev) +static int do_pci_remove(libxl__gc *gc, uint32_t domid, + libxl_device_pci *pcidev, int force) { libxl_ctx *ctx = libxl__gc_owner(gc); libxl_device_pci *assigned; @@ -858,8 +859,6 @@ static int do_pci_remove(libxl__gc *gc, } } - libxl_device_pci_remove_xenstore(gc, domid, pcidev); - hvm = libxl__domain_is_hvm(ctx, domid); if (hvm) { if (libxl__wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) { @@ -878,7 +877,12 @@ static int do_pci_remove(libxl__gc *gc, xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem")); if (libxl__wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) < 0) { LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device Model didn't respond in time"); - return ERROR_FAIL; + /* This depends on guest operating system acknowledging the + * SCI, if it doesn't respond in time then we may wish to + * force the removal. + */ + if ( !force ) + return ERROR_FAIL; } } path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); @@ -924,7 +928,7 @@ skip1: if ((fscanf(f, "%u", &irq) == 1) && irq) { rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq); if (rc < 0) { - LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq); + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_physdev_unmap_pirq irq=%d", irq); } rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0); if (rc < 0) { @@ -948,13 +952,16 @@ out: stubdomid = libxl_get_stubdom_id(ctx, domid); if (stubdomid != 0) { libxl_device_pci pcidev_s = *pcidev; - libxl_device_pci_remove(ctx, stubdomid, &pcidev_s); - } - - return 0; -} - -int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) + libxl_device_pci_remove(ctx, stubdomid, &pcidev_s, force); + } + + libxl_device_pci_remove_xenstore(gc, domid, pcidev); + + return 0; +} + +int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, + libxl_device_pci *pcidev, int force) { libxl__gc gc = LIBXL_INIT_GC(ctx); unsigned int orig_vdev, pfunc_mask; @@ -980,7 +987,7 @@ int libxl_device_pci_remove(libxl_ctx *c }else{ pcidev->vdevfn = orig_vdev; } - if ( do_pci_remove(&gc, domid, pcidev) ) + if ( do_pci_remove(&gc, domid, pcidev, force) ) rc = ERROR_FAIL; } } @@ -1049,7 +1056,11 @@ int libxl_device_pci_shutdown(libxl_ctx if ( rc ) return rc; for (i = 0; i < num; i++) { - if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0) + /* Force remove on shutdown since, on HVM, qemu will not always + * respond to SCI interrupt because the guest kernel has shut down the + * devices by the time we even get here! + */ + if (libxl_device_pci_remove(ctx, domid, pcidevs + i, 1) < 0) return ERROR_FAIL; } free(pcidevs); diff -r 02e199c96ece -r 1385b15e168f tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Wed Oct 06 11:00:19 2010 +0100 +++ b/tools/libxl/xl_cmdimpl.c Wed Oct 06 17:38:15 2010 +0100 @@ -2262,7 +2262,7 @@ int main_pcilist(int argc, char **argv) return 0; } -static void pcidetach(char *dom, char *bdf) +static void pcidetach(char *dom, char *bdf, int force) { libxl_device_pci pcidev; @@ -2273,20 +2273,24 @@ static void pcidetach(char *dom, char *b fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf); exit(2); } - libxl_device_pci_remove(&ctx, domid, &pcidev); + libxl_device_pci_remove(&ctx, domid, &pcidev, force); libxl_device_pci_destroy(&pcidev); } int main_pcidetach(int argc, char **argv) { int opt; + int force = 0; char *domname = NULL, *bdf = NULL; - while ((opt = getopt(argc, argv, "h")) != -1) { + while ((opt = getopt(argc, argv, "hf")) != -1) { switch (opt) { case 'h': help("pci-detach"); return 0; + case 'f': + force = 1; + break; default: fprintf(stderr, "option not supported\n"); break; @@ -2300,7 +2304,7 @@ int main_pcidetach(int argc, char **argv domname = argv[optind]; bdf = argv[optind + 1]; - pcidetach(domname, bdf); + pcidetach(domname, bdf, force); return 0; } static void pciattach(char *dom, char *bdf, char *vs) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |