aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxl/libxl.h2
-rw-r--r--tools/libxl/libxl_pci.c29
-rw-r--r--tools/libxl/xl_cmdimpl.c12
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)