diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 578a33b284..89dec91ed1 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -533,6 +533,18 @@ qemuAssignDeviceInputAlias(virDomainDefPtr def, } +static int +qemuAssignDeviceVsockAlias(virDomainVsockDefPtr vsock) +{ + if (vsock->info.alias) + return 0; + if (VIR_STRDUP(vsock->info.alias, "vsock0") < 0) + return -1; + + return 0; +} + + int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { @@ -629,6 +641,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (qemuAssignDeviceMemoryAlias(NULL, def->mems[i], false) < 0) return -1; } + if (def->vsock) { + if (qemuAssignDeviceVsockAlias(def->vsock) < 0) + return -1; + } return 0; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c7ff074e29..0b5ec4f2ba 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9912,6 +9912,42 @@ qemuBuildSeccompSandboxCommandLine(virCommandPtr cmd, } +static int +qemuBuildVsockCommandLine(virCommandPtr cmd, + virDomainDefPtr def, + virDomainVsockDefPtr vsock, + virQEMUCapsPtr qemuCaps) +{ + qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData; + const char *device = "vhost-vsock-pci"; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *devstr = NULL; + int ret = -1; + + virBufferAsprintf(&buf, "%s", device); + virBufferAsprintf(&buf, ",id=%s", vsock->info.alias); + virBufferAsprintf(&buf, ",guest-cid=%u", vsock->guest_cid); + virBufferAsprintf(&buf, ",vhostfd=%u", priv->vhostfd); + if (qemuBuildDeviceAddressStr(&buf, def, &vsock->info, qemuCaps) < 0) + goto cleanup; + + if (virBufferCheckError(&buf) < 0) + goto cleanup; + + devstr = virBufferContentAndReset(&buf); + + virCommandPassFD(cmd, priv->vhostfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT); + priv->vhostfd = -1; + virCommandAddArgList(cmd, "-device", devstr, NULL); + + ret = 0; + cleanup: + virBufferFreeAndReset(&buf); + VIR_FREE(devstr); + return ret; +} + + /* * Constructs a argv suitable for launching qemu with config defined * for a given virtual machine. @@ -10161,6 +10197,10 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, goto error; } + if (def->vsock && + qemuBuildVsockCommandLine(cmd, def, def->vsock, qemuCaps) < 0) + goto error; + /* In some situations, eg. VFIO passthrough, QEMU might need to lock a * significant amount of memory, so we need to set the limit accordingly */ virCommandSetMaxMemLock(cmd, qemuDomainGetMemLockLimitBytes(def)); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 10f22b1cc2..2c51e4c0d8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1160,6 +1160,8 @@ qemuDomainVsockPrivateNew(void) if (!(priv = virObjectNew(qemuDomainVsockPrivateClass))) return NULL; + priv->vhostfd = -1; + return (virObjectPtr) priv; } @@ -1167,6 +1169,9 @@ qemuDomainVsockPrivateNew(void) static void qemuDomainVsockPrivateDispose(void *obj ATTRIBUTE_UNUSED) { + qemuDomainVsockPrivatePtr priv = obj; + + VIR_FORCE_CLOSE(priv->vhostfd); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index f298ebf785..2e0f4df0fb 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -447,7 +447,7 @@ typedef qemuDomainVsockPrivate *qemuDomainVsockPrivatePtr; struct _qemuDomainVsockPrivate { virObject parent; - virTristateBool maybe; + int vhostfd; }; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5f5759c9c8..30cc5904e0 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -79,6 +79,7 @@ #include "nwfilter_conf.h" #include "netdev_bandwidth_conf.h" #include "virresctrl.h" +#include "virvsock.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -5947,6 +5948,36 @@ qemuProcessPrepareHostStorage(virQEMUDriverPtr driver, } +static int +qemuProcessOpenVhostVsock(virDomainVsockDefPtr vsock) +{ + qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData; + const char *vsock_path = "/dev/vhost-vsock"; + int fd; + + if ((fd = open(vsock_path, O_RDWR)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("unable to open vhost-vsock device")); + return -1; + } + + if (vsock->auto_cid == VIR_TRISTATE_BOOL_YES) { + if (virVsockAcquireGuestCid(fd, &vsock->guest_cid) < 0) + goto error; + } else { + if (virVsockSetGuestCid(fd, vsock->guest_cid) < 0) + goto error; + } + + priv->vhostfd = fd; + return 0; + + error: + VIR_FORCE_CLOSE(fd); + return -1; +} + + /** * qemuProcessPrepareHost: * @driver: qemu driver @@ -5972,6 +6003,10 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver, if (qemuPrepareNVRAM(cfg, vm) < 0) goto cleanup; + if (vm->def->vsock) { + if (qemuProcessOpenVhostVsock(vm->def->vsock) < 0) + goto cleanup; + } /* network devices must be "prepared" before hostdevs, because * setting up a network device might create a new hostdev that * will need to be setup. diff --git a/tests/qemuxml2argvdata/vhost-vsock-auto.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-vsock-auto.x86_64-latest.args new file mode 100644 index 0000000000..dd9b60ba3e --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-vsock-auto.x86_64-latest.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=test,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-test/master-key.aes \ +-machine pc-i440fx-2.9,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid bba65c0e-c049-934f-b6aa-4e2c0582acdf \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-test/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot menu=on,strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-device vhost-vsock-pci,id=vsock0,guest-cid=42,vhostfd=6789,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args new file mode 100644 index 0000000000..907af8bb99 --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=test,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-test/master-key.aes \ +-machine pc-0.13,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid bba65c0e-c049-934f-b6aa-4e2c0582acdf \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-test/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot menu=on,strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-device vhost-vsock-pci,id=vsock0,guest-cid=4,vhostfd=6789,bus=pci.0,addr=0x7 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2fe4390104..ddd2b88c0a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -532,6 +532,17 @@ testCompareXMLToArgv(const void *data) } } + if (vm->def->vsock) { + virDomainVsockDefPtr vsock = vm->def->vsock; + qemuDomainVsockPrivatePtr vsockPriv = + (qemuDomainVsockPrivatePtr)vsock->privateData; + + if (vsock->auto_cid == VIR_TRISTATE_BOOL_YES) + vsock->guest_cid = 42; + + vsockPriv->vhostfd = 6789; + } + if (!(cmd = qemuProcessCreatePretendCmd(&driver, vm, migrateURI, (flags & FLAG_FIPS), false, VIR_QEMU_PROCESS_START_COLD))) { @@ -2856,6 +2867,9 @@ mymain(void) QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW, QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW); + DO_TEST_CAPS_LATEST("vhost-vsock"); + DO_TEST_CAPS_LATEST("vhost-vsock-auto"); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir);