diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index c7cb0c1d6..6ad067d41 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -137,6 +137,7 @@ usage(int code) " -H: vmexit from the guest on hlt\n" " -l: LPC device configuration\n" " -m: memory size in MB\n" + " -M: do not hide INTx link for MSI&INTx capable ptdev\n" " -p: pin 'vcpu' to 'hostcpu'\n" " -P: vmexit from the guest on pause\n" " -s: PCI slot config\n" @@ -618,6 +619,7 @@ static struct option long_options[] = { {"kernel", required_argument, 0, 'k' }, {"ramdisk", required_argument, 0, 'r' }, {"bootargs", required_argument, 0, 'B' }, + {"ptdev_msi", no_argument, 0, 'M' }, {"version", no_argument, 0, 'v' }, {"gvtargs", required_argument, 0, 'G' }, {"help", no_argument, 0, 'h' }, @@ -656,7 +658,7 @@ main(int argc, char *argv[]) if (signal(SIGINT, sig_handler_term) == SIG_ERR) fprintf(stderr, "cannot register handler for SIGINT\n"); - optstr = "abehuwxACHIPSTWYvk:r:B:p:g:c:s:m:l:U:G:i:"; + optstr = "abehuwxACHIMPSTWYvk:r:B:p:g:c:s:m:l:U:G:i:"; while ((c = getopt_long(argc, argv, optstr, long_options, &option_idx)) != -1) { switch (c) { @@ -772,6 +774,9 @@ main(int argc, char *argv[]) exit(1); } break; + case 'M': + ptdev_prefer_msi(false); + break; case 'v': print_version(); break; diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c index 3731d3a37..a6ef58a60 100644 --- a/devicemodel/hw/pci/passthrough.c +++ b/devicemodel/hw/pci/passthrough.c @@ -85,6 +85,9 @@ static int memfd = -1; static int pciaccess_ref_cnt; static pthread_mutex_t ref_cnt_mtx = PTHREAD_MUTEX_INITIALIZER; +/* Prefer MSI over INTx for ptdev */ +static bool prefer_msi = true; + /* Not check reset capability before assign ptdev. * Set false by default, that is, always check. */ @@ -109,6 +112,12 @@ struct passthru_dev { struct pci_device *phys_dev; }; +void +ptdev_prefer_msi(bool enable) +{ + prefer_msi = enable; +} + void ptdev_no_reset(bool enable) { no_reset = enable; @@ -925,28 +934,16 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) struct passthru_dev *ptdev; struct pci_device_iterator *iter; struct pci_device *phys_dev; - char *opt; - bool keep_gsi = false; ptdev = NULL; error = -EINVAL; - if (opts == NULL) { - warnx("Empty passthru options\n"); + if (opts == NULL || + sscanf(opts, "%x/%x/%x", &bus, &slot, &func) != 3) { + warnx("invalid passthru options, %s", opts); return -EINVAL; } - opt = strsep(&opts, ","); - if (sscanf(opt, "%x/%x/%x", &bus, &slot, &func) != 3) { - warnx("Invalid passthru options, %s", opt); - return -EINVAL; - } - - while ((opt = strsep(&opts, ",")) != NULL) { - if (!strncmp(opt, "keep_gsi", 8)) - keep_gsi = true; - } - if (vm_assign_ptdev(ctx, bus, slot, func) != 0) { warnx("PCI device at %x/%x/%x is not using the pt(4) driver", bus, slot, func); @@ -1011,7 +1008,7 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) * Forge Guest to use MSI/MSIX in this case to mitigate IRQ sharing * issue */ - if (error == IRQ_MSI && !keep_gsi) + if (error == IRQ_MSI && prefer_msi) return 0; /* Allocates the virq if ptdev only support INTx */ diff --git a/devicemodel/include/dm.h b/devicemodel/include/dm.h index e0a02035e..e9ea89959 100644 --- a/devicemodel/include/dm.h +++ b/devicemodel/include/dm.h @@ -48,5 +48,6 @@ int vmexit_task_switch(struct vmctx *ctx, struct vhm_request *vhm_req, void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); void *dm_gpa2hva(uint64_t gpa, size_t size); int virtio_uses_msix(void); +void ptdev_prefer_msi(bool enable); void ptdev_no_reset(bool enable); #endif