提交 4b95738c 编写于 作者: J Jonathon Jongsma 提交者: Cole Robinson

qemu: add 'ramfb' attribute for mediated devices

The 'ramfb' attribute provides a framebuffer to the guest that can be
used as a boot display for the vgpu

For example, the following configuration can be used to provide a vgpu
with a boot display:

    <hostdev mode='subsystem' type='mdev' model='vfio-pci' display='on' ramfb='on'>
        <source>
            <address uuid='$UUID'/>
        </source>
    </hostdev>
Reviewed-by: NCole Robinson <crobinso@redhat.com>
Signed-off-by: NJonathon Jongsma <jjongsma@redhat.com>
上级 c66f2be6
...@@ -4847,6 +4847,14 @@ ...@@ -4847,6 +4847,14 @@
<a href="#elementsGraphics">graphical framebuffer</a> in order to <a href="#elementsGraphics">graphical framebuffer</a> in order to
use this attribute, currently only supported with VNC, Spice and use this attribute, currently only supported with VNC, Spice and
egl-headless graphics devices. egl-headless graphics devices.
<span class="since">Since version 5.10.0</span>, there is an optional
<code>ramfb</code> attribute for devices with
<code>model='vfio-pci'</code>. Supported values are either
<code>on</code> or <code>off</code> (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.
<p> <p>
Note: There are also some implications on the usage of guest's Note: There are also some implications on the usage of guest's
address type depending on the <code>model</code> attribute, address type depending on the <code>model</code> attribute,
......
...@@ -4779,6 +4779,11 @@ ...@@ -4779,6 +4779,11 @@
<value>vfio-ap</value> <value>vfio-ap</value>
</choice> </choice>
</attribute> </attribute>
<optional>
<attribute name="ramfb">
<ref name="virOnOff"/>
</attribute>
</optional>
<optional> <optional>
<attribute name="display"> <attribute name="display">
<ref name="virOnOff"/> <ref name="virOnOff"/>
......
...@@ -8135,6 +8135,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, ...@@ -8135,6 +8135,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
g_autofree char *backendStr = NULL; g_autofree char *backendStr = NULL;
g_autofree char *model = NULL; g_autofree char *model = NULL;
g_autofree char *display = NULL; g_autofree char *display = NULL;
g_autofree char *ramfb = NULL;
/* @managed can be read from the xml document - it is always an /* @managed can be read from the xml document - it is always an
* attribute of the toplevel element, no matter what type of * attribute of the toplevel element, no matter what type of
...@@ -8148,6 +8149,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, ...@@ -8148,6 +8149,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
rawio = virXMLPropString(node, "rawio"); rawio = virXMLPropString(node, "rawio");
model = virXMLPropString(node, "model"); model = virXMLPropString(node, "model");
display = virXMLPropString(node, "display"); display = virXMLPropString(node, "display");
ramfb = virXMLPropString(node, "ramfb");
/* @type is passed in from the caller rather than read from the /* @type is passed in from the caller rather than read from the
* xml document, because it is specified in different places for * xml document, because it is specified in different places for
...@@ -8256,6 +8258,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, ...@@ -8256,6 +8258,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
display); display);
return -1; return -1;
} }
if (ramfb &&
(mdevsrc->ramfb = virTristateSwitchTypeFromString(ramfb)) <= 0) {
virReportError(VIR_ERR_XML_ERROR,
_("unknown value '%s' for <hostdev> attribute "
"'ramfb'"),
ramfb);
return -1;
}
} }
switch (def->source.subsys.type) { switch (def->source.subsys.type) {
......
...@@ -262,6 +262,7 @@ struct _virDomainHostdevSubsysMediatedDev { ...@@ -262,6 +262,7 @@ struct _virDomainHostdevSubsysMediatedDev {
int model; /* enum virMediatedDeviceModelType */ int model; /* enum virMediatedDeviceModelType */
int display; /* virTristateSwitch */ int display; /* virTristateSwitch */
char uuidstr[VIR_UUID_STRING_BUFLEN]; /* mediated device's uuid string */ char uuidstr[VIR_UUID_STRING_BUFLEN]; /* mediated device's uuid string */
int ramfb; /* virTristateSwitch */
}; };
typedef enum { typedef enum {
......
...@@ -5329,6 +5329,19 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, ...@@ -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 * char *
qemuBuildHostdevMediatedDevStr(const virDomainDef *def, qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
virDomainHostdevDefPtr dev, virDomainHostdevDefPtr dev,
...@@ -5342,7 +5355,7 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def, ...@@ -5342,7 +5355,7 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
if (!(mdevPath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr))) if (!(mdevPath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr)))
return NULL; return NULL;
dev_str = virMediatedDeviceModelTypeToString(mdevsrc->model); dev_str = qemuBuildHostdevMdevModelTypeString(mdevsrc);
if (!dev_str) if (!dev_str)
return NULL; return NULL;
...@@ -5360,6 +5373,10 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def, ...@@ -5360,6 +5373,10 @@ qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
if (dev->info->bootIndex) if (dev->info->bootIndex)
virBufferAsprintf(&buf, ",bootindex=%u", 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); return virBufferContentAndReset(&buf);
} }
......
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
<domain type='qemu'>
<name>QEMUGuest2</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-i686</emulator>
<controller type='usb' index='0'>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
</controller>
<graphics type='vnc'/>
<hostdev mode='subsystem' type='mdev' model='vfio-pci' display='on' ramfb='on'>
<source>
<address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
</source>
</hostdev>
<video>
<model type='qxl' heads='1'/>
</video>
<memballoon model='none'/>
</devices>
</domain>
...@@ -1605,6 +1605,7 @@ mymain(void) ...@@ -1605,6 +1605,7 @@ mymain(void)
DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics", DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics",
QEMU_CAPS_DEVICE_VFIO_PCI, QEMU_CAPS_DEVICE_VFIO_PCI,
QEMU_CAPS_VFIO_PCI_DISPLAY); QEMU_CAPS_VFIO_PCI_DISPLAY);
DO_TEST_CAPS_LATEST("hostdev-mdev-display-ramfb");
DO_TEST_PARSE_ERROR("hostdev-vfio-zpci-wrong-arch", DO_TEST_PARSE_ERROR("hostdev-vfio-zpci-wrong-arch",
QEMU_CAPS_DEVICE_VFIO_PCI); QEMU_CAPS_DEVICE_VFIO_PCI);
DO_TEST("hostdev-vfio-zpci", DO_TEST("hostdev-vfio-zpci",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册