diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4c60392a08d847b2a89ea8fa5d49705b1b94a1a5..a1042a314c6b2e19000b6910f9f043f4fe3f22a7 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4847,6 +4847,14 @@ graphical framebuffer in order to use this attribute, currently only supported with VNC, Spice and egl-headless graphics devices. + + Since version 5.10.0, there is an optional + ramfb attribute for devices with + model='vfio-pci'. Supported values are either + on or off (default is 'off'). When + enabled, this attribute provides a memory framebuffer device to the + guest. This framebuffer will be used as a boot display when a vgpu + device is the primary display.

Note: There are also some implications on the usage of guest's address type depending on the model attribute, diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e06f892da3931375bd32f118382713bbe7541d37..a83c9ae7a53bcc2563e611ad48d1c4bc94343168 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4779,6 +4779,11 @@ vfio-ap + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f825e521ec87d98b8ef38aeede2fd3b28e3f829c..561e25ff6e4a45d9e91c5d59535377131fc30c40 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8135,6 +8135,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, g_autofree char *backendStr = NULL; g_autofree char *model = NULL; g_autofree char *display = NULL; + g_autofree char *ramfb = NULL; /* @managed can be read from the xml document - it is always an * attribute of the toplevel element, no matter what type of @@ -8148,6 +8149,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, rawio = virXMLPropString(node, "rawio"); model = virXMLPropString(node, "model"); display = virXMLPropString(node, "display"); + ramfb = virXMLPropString(node, "ramfb"); /* @type is passed in from the caller rather than read from the * xml document, because it is specified in different places for @@ -8256,6 +8258,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, display); return -1; } + + if (ramfb && + (mdevsrc->ramfb = virTristateSwitchTypeFromString(ramfb)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("unknown value '%s' for attribute " + "'ramfb'"), + ramfb); + return -1; + } } switch (def->source.subsys.type) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2f7a006711f6d06d8cbab1e9003aada1d5c783f9..39fb42e29dff861ebfbedf165f837abadfbdd9f1 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -262,6 +262,7 @@ struct _virDomainHostdevSubsysMediatedDev { int model; /* enum virMediatedDeviceModelType */ int display; /* virTristateSwitch */ char uuidstr[VIR_UUID_STRING_BUFLEN]; /* mediated device's uuid string */ + int ramfb; /* virTristateSwitch */ }; typedef enum { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 0f0d9c434f3386ad3fbb5bf6680aceacc1679286..ca1bd125940f265a7c9a42882d249188176a50fa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5329,6 +5329,19 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, } +static const char * +qemuBuildHostdevMdevModelTypeString(virDomainHostdevSubsysMediatedDevPtr mdev) +{ + /* when the 'ramfb' attribute is set, we must use the nohotplug variant + * rather than 'vfio-pci' */ + if (mdev->model == VIR_MDEV_MODEL_TYPE_VFIO_PCI && + mdev->ramfb == VIR_TRISTATE_SWITCH_ON) + return "vfio-pci-nohotplug"; + + return virMediatedDeviceModelTypeToString(mdev->model); +} + + char * qemuBuildHostdevMediatedDevStr(const virDomainDef *def, virDomainHostdevDefPtr dev, @@ -5342,7 +5355,7 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def, if (!(mdevPath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr))) return NULL; - dev_str = virMediatedDeviceModelTypeToString(mdevsrc->model); + dev_str = qemuBuildHostdevMdevModelTypeString(mdevsrc); if (!dev_str) return NULL; @@ -5360,6 +5373,10 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def, if (dev->info->bootIndex) virBufferAsprintf(&buf, ",bootindex=%u", dev->info->bootIndex); + if (mdevsrc->ramfb == VIR_TRISTATE_SWITCH_ON) + virBufferAsprintf(&buf, ",ramfb=%s", + virTristateSwitchTypeToString(mdevsrc->ramfb)); + return virBufferContentAndReset(&buf); } diff --git a/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.x86_64-latest.args b/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.x86_64-latest.args new file mode 100644 index 0000000000000000000000000000000000000000..30d2f83318d41c20661017df0104bba6f7a34b3b --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.x86_64-latest.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest2 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest2/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest2/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest2/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name guest=QEMUGuest2,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest2/master-key.aes \ +-machine pc,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-vnc 127.0.0.1:0 \ +-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,\ +vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pci.0,addr=0x2 \ +-device vfio-pci-nohotplug,id=hostdev0,\ +sysfsdev=/sys/bus/mdev/devices/53764d0e-85a0-42b4-af5c-2046b460b1dc,display=on,\ +bus=pci.0,addr=0x3,ramfb=on \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.xml b/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e7851b2b0d311fd627bccc59a7767c028c96246 --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-mdev-display-ramfb.xml @@ -0,0 +1,33 @@ + + QEMUGuest2 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + +

+ + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 09a7254907bb428684d6bdd1b30ae117e9d83a8a..f839d77e8e8d6fd7947476928b4d53f824e3053b 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1605,6 +1605,7 @@ mymain(void) DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics", QEMU_CAPS_DEVICE_VFIO_PCI, QEMU_CAPS_VFIO_PCI_DISPLAY); + DO_TEST_CAPS_LATEST("hostdev-mdev-display-ramfb"); DO_TEST_PARSE_ERROR("hostdev-vfio-zpci-wrong-arch", QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("hostdev-vfio-zpci",