From: Fabian Freyer <fabian.freyer@xxxxxxxxxxxxxxxxxxx> bhyve supports 'gop' video device that allows clients to connect to VMs using VNC clients. This commit adds support for that to the bhyve driver: - Introducr 'gop' video device type - Add capabilities probing for the 'fbuf' device that's responsible for graphics - Update command builder routines to let users configure domain's VNC via gop graphics. Signed-off-by: Roman Bogorodskiy <bogorodskiy@xxxxxxxxx> --- docs/formatdomain.html.in | 3 +- docs/schemas/domaincommon.rng | 1 + po/POTFILES.in | 1 + src/bhyve/bhyve_capabilities.c | 40 +++++++++++++++ src/bhyve/bhyve_capabilities.h | 1 + src/bhyve/bhyve_command.c | 100 ++++++++++++++++++++++++++++++++++++ src/bhyve/bhyve_device.c | 11 ++++ src/conf/domain_conf.c | 5 +- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 9 ++-- src/qemu/qemu_domain_address.c | 1 + tests/domaincapsschemadata/full.xml | 1 + 12 files changed, 169 insertions(+), 5 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 0a115f5dc..b853a7245 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5812,8 +5812,9 @@ qemu-kvm -net nic,model=? /dev/null <p> The <code>model</code> element has a mandatory <code>type</code> attribute which takes the value "vga", "cirrus", "vmvga", "xen", - "vbox", "qxl" (<span class="since">since 0.8.6</span>) or + "vbox", "qxl" (<span class="since">since 0.8.6</span>), "virtio" (<span class="since">since 1.3.0</span>) + or "gop" (<span class="since">since 3.1.0</span>) depending on the hypervisor features available. </p> <p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d715bff29..3e3793ea0 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3152,6 +3152,7 @@ <value>xen</value> <value>vbox</value> <value>virtio</value> + <value>gop</value> </choice> </attribute> <group> diff --git a/po/POTFILES.in b/po/POTFILES.in index 365ea662f..c6d350da7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,6 +12,7 @@ gnulib/lib/getopt.c gnulib/lib/regcomp.c src/access/viraccessdriverpolkit.c src/access/viraccessmanager.c +src/bhyve/bhyve_capabilities.c src/bhyve/bhyve_command.c src/bhyve/bhyve_device.c src/bhyve/bhyve_domain.c diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c index 9dec66b11..5539d2978 100644 --- a/src/bhyve/bhyve_capabilities.c +++ b/src/bhyve/bhyve_capabilities.c @@ -117,6 +117,7 @@ virBhyveDomainCapsBuild(const char *emulatorbin, virDomainVirtType virttype) { virDomainCapsPtr caps = NULL; + unsigned int bhyve_caps = 0; DIR *dir; struct dirent *entry; const char *firmware_dir = "/usr/local/share/uefi-firmware"; @@ -125,6 +126,12 @@ virBhyveDomainCapsBuild(const char *emulatorbin, if (!(caps = virDomainCapsNew(emulatorbin, machine, arch, virttype))) goto cleanup; + if (virBhyveProbeCaps(&bhyve_caps)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed probing capabilities")); + goto cleanup; + } + caps->os.supported = true; caps->os.loader.supported = true; VIR_DOMAIN_CAPS_ENUM_SET(caps->os.loader.type, @@ -155,6 +162,12 @@ virBhyveDomainCapsBuild(const char *emulatorbin, VIR_DOMAIN_DISK_BUS_SATA, VIR_DOMAIN_DISK_BUS_VIRTIO); + if (bhyve_caps & BHYVE_CAP_FBUF) { + caps->graphics.supported = true; + caps->video.supported = true; + VIR_DOMAIN_CAPS_ENUM_SET(caps->graphics.type, VIR_DOMAIN_GRAPHICS_TYPE_VNC); + VIR_DOMAIN_CAPS_ENUM_SET(caps->video.modelType, VIR_DOMAIN_VIDEO_TYPE_GOP); + } cleanup: VIR_DIR_CLOSE(dir); return caps; @@ -289,6 +302,30 @@ bhyveProbeCapsLPC_Bootrom(unsigned int *caps, char *binary) return ret; } + +static int +bhyveProbeCapsFramebuffer(unsigned int *caps, char *binary) +{ + char *error; + virCommandPtr cmd = NULL; + int ret = -1, exit; + + cmd = virCommandNew(binary); + virCommandAddArgList(cmd, "-s", "0,fbuf", NULL); + virCommandSetErrorBuffer(cmd, &error); + if (virCommandRun(cmd, &exit) < 0) + goto cleanup; + + if (strstr(error, "pci slot 0:0: unknown device \"fbuf\"") == NULL) + *caps |= BHYVE_CAP_FBUF; + + ret = 0; + cleanup: + VIR_FREE(error); + virCommandFree(cmd); + return ret; +} + int virBhyveProbeCaps(unsigned int *caps) { @@ -313,6 +350,9 @@ virBhyveProbeCaps(unsigned int *caps) if ((ret = bhyveProbeCapsLPC_Bootrom(caps, binary))) goto out; + if ((ret = bhyveProbeCapsFramebuffer(caps, binary))) + goto out; + out: VIR_FREE(binary); return ret; diff --git a/src/bhyve/bhyve_capabilities.h b/src/bhyve/bhyve_capabilities.h index 746c77181..8fb97d730 100644 --- a/src/bhyve/bhyve_capabilities.h +++ b/src/bhyve/bhyve_capabilities.h @@ -41,6 +41,7 @@ typedef enum { BHYVE_CAP_AHCI32SLOT = 1 << 1, BHYVE_CAP_NET_E1000 = 1 << 2, BHYVE_CAP_LPC_BOOTROM = 1 << 3, + BHYVE_CAP_FBUF = 1 << 4, } virBhyveCapsFlags; int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps); diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index 450800920..ec7a71572 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -290,6 +290,94 @@ bhyveBuildLPCArgStr(const virDomainDef *def ATTRIBUTE_UNUSED, return 0; } +static int +bhyveBuildGraphicsArgStr(const virDomainDef *def ATTRIBUTE_UNUSED, + virDomainGraphicsDefPtr graphics, + virDomainVideoDefPtr video, + virConnectPtr conn, + virCommandPtr cmd) +{ + virBuffer opt = VIR_BUFFER_INITIALIZER; + virDomainGraphicsListenDefPtr glisten = NULL; + bool escapeAddr; + + if (!(bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM) || + def->os.bootloader || + !def->os.loader) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Graphics are only supported" + " when booting using UEFI")); + return -1; + } + + if (!(bhyveDriverGetCaps(conn) & BHYVE_CAP_FBUF)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Bhyve version does not support framebuffer")); + return -1; + } + + if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only VNC supported")); + return -1; + } + + if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing listen element")); + goto error; + } + + virBufferAsprintf(&opt, "%d:%d,fbuf", video->info.addr.pci.slot, video->info.addr.pci.function); + + switch (glisten->type) { + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS: + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK: + virBufferAddLit(&opt, ",tcp="); + + if (!graphics->data.vnc.autoport && + (graphics->data.vnc.port < 5900 || + graphics->data.vnc.port > 65535)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("vnc port must be in range [5900,65535]")); + goto error; + } + + if (graphics->data.vnc.auth.passwd) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("vnc password auth not supported")); + goto error; + } else { + /* Bhyve doesn't support VNC Auth yet, so print a warning about + * unauthenticated VNC sessions */ + VIR_WARN("%s", _("Security warning: currently VNC auth is not" + " supported.")); + } + + if (glisten->address) { + escapeAddr = strchr(glisten->address, ':') != NULL; + if (escapeAddr) + virBufferAsprintf(&opt, "[%s]", glisten->address); + else + virBufferAdd(&opt, glisten->address, -1); + } + + virBufferAsprintf(&opt, ":%d", graphics->data.vnc.port); + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unsupported listen type")); + } + + virCommandAddArg(cmd, "-s"); + virCommandAddArgBuffer(cmd, &opt); + return 0; + + error: + virBufferFreeAndReset(&opt); + return -1; +} + virCommandPtr virBhyveProcessBuildBhyveCmd(virConnectPtr conn, virDomainDefPtr def, bool dryRun) @@ -413,6 +501,18 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn, } } + if (def->ngraphics && def->nvideos) { + if (def->ngraphics == 1 && def->nvideos == 1) { + if (bhyveBuildGraphicsArgStr(def, def->graphics[0], def->videos[0], conn, cmd) < 0) + goto error; + add_lpc = true; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Multiple graphics devices are not supported")); + goto error; + } + } + if (add_lpc || def->nserials) bhyveBuildLPCArgStr(def, cmd); diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c index 55ce631ec..a3a263b7e 100644 --- a/src/bhyve/bhyve_device.c +++ b/src/bhyve/bhyve_device.c @@ -145,6 +145,17 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, goto error; } + for (i = 0; i < def->nvideos; i++) { + if (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info)) + continue; + if (virDomainPCIAddressReserveNextAddr(addrs, + &def->videos[i]->info, + VIR_PCI_CONNECT_TYPE_PCI_DEVICE, + -1) < 0) + goto error; + } + + return 0; error: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1bc72a4e9..77fe87582 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -545,7 +545,8 @@ VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, "vbox", "qxl", "parallels", - "virtio") + "virtio", + "gop") VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST, "mouse", @@ -13018,6 +13019,8 @@ virDomainVideoDefaultType(const virDomainDef *def) return VIR_DOMAIN_VIDEO_TYPE_VGA; else return VIR_DOMAIN_VIDEO_TYPE_PARALLELS; + case VIR_DOMAIN_VIRT_BHYVE: + return VIR_DOMAIN_VIDEO_TYPE_GOP; default: return -1; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index dd79206f6..0876eabbf 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1335,6 +1335,7 @@ typedef enum { VIR_DOMAIN_VIDEO_TYPE_QXL, VIR_DOMAIN_VIDEO_TYPE_PARALLELS, /* pseudo device for VNC in containers */ VIR_DOMAIN_VIDEO_TYPE_VIRTIO, + VIR_DOMAIN_VIDEO_TYPE_GOP, VIR_DOMAIN_VIDEO_TYPE_LAST } virDomainVideoType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c00a47a91..aabdcdcee 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -100,7 +100,8 @@ VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, "", /* don't support vbox */ "qxl", "", /* don't support parallels */ - "" /* no need for virtio */); + "", /* no need for virtio */ + "" /* don't support gop */); VIR_ENUM_DECL(qemuDeviceVideo) @@ -112,7 +113,8 @@ VIR_ENUM_IMPL(qemuDeviceVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, "", /* don't support vbox */ "qxl-vga", "", /* don't support parallels */ - "virtio-vga"); + "virtio-vga", + "" /* don't support gop */); VIR_ENUM_DECL(qemuDeviceVideoSecondary) @@ -124,7 +126,8 @@ VIR_ENUM_IMPL(qemuDeviceVideoSecondary, VIR_DOMAIN_VIDEO_TYPE_LAST, "", /* don't support vbox */ "qxl", "", /* don't support parallels */ - "virtio-gpu-pci"); + "virtio-gpu-pci", + "" /* don't support gop */); VIR_ENUM_DECL(qemuSoundCodec) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 70482f224..e22adacb2 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -741,6 +741,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: return pciFlags; + case VIR_DOMAIN_VIDEO_TYPE_GOP: case VIR_DOMAIN_VIDEO_TYPE_LAST: return 0; } diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml index 6abd4995a..6a676253c 100644 --- a/tests/domaincapsschemadata/full.xml +++ b/tests/domaincapsschemadata/full.xml @@ -70,6 +70,7 @@ <value>qxl</value> <value>parallels</value> <value>virtio</value> + <value>gop</value> </enum> </video> <hostdev supported='yes'> -- 2.11.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list