diff options
-rw-r--r-- | tools/libxl/libxl.h | 2 | ||||
-rw-r--r-- | tools/libxl/libxl_pci.c | 29 | ||||
-rw-r--r-- | tools/libxl/xl_cmdimpl.c | 12 |
3 files changed, 29 insertions, 14 deletions
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 21030e4d70..b93ef2e97e 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -406,7 +406,7 @@ int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid); 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 --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c index 67df77eefd..a11faa6171 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -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, uint32_t domid, libxl_device_pci *pcidev } } - 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, uint32_t domid, libxl_device_pci *pcidev 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); + 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 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 *ctx, uint32_t domid, libxl_device_pci *pc }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 *ctx, uint32_t domid) 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 --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 7444d2b8aa..0fb65d5696 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -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 *bdf) 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) |