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

qemu: add a new video device model 'ramfb'

This device is a very simple framebuffer device supported by qemu that
is mostly intended to use as a boot framebuffer in conjunction with a
vgpu. However, there is also a standalone ramfb device that can be used
as a primary display device and is useful for e.g. aarch64 guests where
different memory mappings between the host and guest can prevent use of
other devices with framebuffers such as virtio-vga.

https://bugzilla.redhat.com/show_bug.cgi?id=1679680 describes the
issues in more detail.
Reviewed-by: NCole Robinson <crobinso@redhat.com>
Signed-off-by: NJonathon Jongsma <jjongsma@redhat.com>
上级 9bfcf0f6
...@@ -7032,9 +7032,10 @@ qemu-kvm -net nic,model=? /dev/null ...@@ -7032,9 +7032,10 @@ qemu-kvm -net nic,model=? /dev/null
"vbox", "qxl" (<span class="since">since 0.8.6</span>), "vbox", "qxl" (<span class="since">since 0.8.6</span>),
"virtio" (<span class="since">since 1.3.0</span>), "virtio" (<span class="since">since 1.3.0</span>),
"gop" (<span class="since">since 3.2.0</span>), "gop" (<span class="since">since 3.2.0</span>),
"none" (<span class="since">since 4.6.0</span>, or "bochs" "bochs" (<span class="since">since 5.6.0</span>), "ramfb"
(<span class="since">since 5.6.0</span>) (<span class="since">since 5.9.0</span>), or "none"
depending on the hypervisor features available. (<span class="since">since 4.6.0</span>, depending on the hypervisor
features available.
The purpose of the type <code>none</code> is to instruct libvirt not The purpose of the type <code>none</code> is to instruct libvirt not
to add a default video device in the guest (see the paragraph above). to add a default video device in the guest (see the paragraph above).
This legacy behaviour can be inconvenient in cases where GPU mediated This legacy behaviour can be inconvenient in cases where GPU mediated
......
...@@ -41,6 +41,15 @@ ...@@ -41,6 +41,15 @@
<libvirt> <libvirt>
<release version="v5.9.0" date="unreleased"> <release version="v5.9.0" date="unreleased">
<section title="New features"> <section title="New features">
<change>
<summary>
qemu: Introduce a new video model of type 'ramfb'
</summary>
<description>
Introduce a new video model type to the domain XML that supports the
<code>ramfb</code> standalone device in qemu.
</description>
</change>
</section> </section>
<section title="Improvements"> <section title="Improvements">
</section> </section>
......
...@@ -3598,6 +3598,7 @@ ...@@ -3598,6 +3598,7 @@
<value>gop</value> <value>gop</value>
<value>none</value> <value>none</value>
<value>bochs</value> <value>bochs</value>
<value>ramfb</value>
</choice> </choice>
</attribute> </attribute>
<group> <group>
......
...@@ -748,6 +748,7 @@ VIR_ENUM_IMPL(virDomainVideo, ...@@ -748,6 +748,7 @@ VIR_ENUM_IMPL(virDomainVideo,
"gop", "gop",
"none", "none",
"bochs", "bochs",
"ramfb",
); );
VIR_ENUM_IMPL(virDomainVideoVGAConf, VIR_ENUM_IMPL(virDomainVideoVGAConf,
...@@ -15299,6 +15300,7 @@ virDomainVideoDefaultRAM(const virDomainDef *def, ...@@ -15299,6 +15300,7 @@ virDomainVideoDefaultRAM(const virDomainDef *def,
case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
case VIR_DOMAIN_VIDEO_TYPE_GOP: case VIR_DOMAIN_VIDEO_TYPE_GOP:
case VIR_DOMAIN_VIDEO_TYPE_NONE: case VIR_DOMAIN_VIDEO_TYPE_NONE:
case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
case VIR_DOMAIN_VIDEO_TYPE_LAST: case VIR_DOMAIN_VIDEO_TYPE_LAST:
default: default:
return 0; return 0;
......
...@@ -1399,6 +1399,7 @@ typedef enum { ...@@ -1399,6 +1399,7 @@ typedef enum {
VIR_DOMAIN_VIDEO_TYPE_GOP, VIR_DOMAIN_VIDEO_TYPE_GOP,
VIR_DOMAIN_VIDEO_TYPE_NONE, VIR_DOMAIN_VIDEO_TYPE_NONE,
VIR_DOMAIN_VIDEO_TYPE_BOCHS, VIR_DOMAIN_VIDEO_TYPE_BOCHS,
VIR_DOMAIN_VIDEO_TYPE_RAMFB,
VIR_DOMAIN_VIDEO_TYPE_LAST VIR_DOMAIN_VIDEO_TYPE_LAST
} virDomainVideoType; } virDomainVideoType;
......
...@@ -114,6 +114,7 @@ VIR_ENUM_IMPL(qemuVideo, ...@@ -114,6 +114,7 @@ VIR_ENUM_IMPL(qemuVideo,
"" /* don't support gop */, "" /* don't support gop */,
"" /* 'none' doesn't make sense here */, "" /* 'none' doesn't make sense here */,
"bochs-display", "bochs-display",
"", /* ramfb can't be used with -vga */
); );
VIR_ENUM_DECL(qemuDeviceVideo); VIR_ENUM_DECL(qemuDeviceVideo);
...@@ -132,6 +133,7 @@ VIR_ENUM_IMPL(qemuDeviceVideo, ...@@ -132,6 +133,7 @@ VIR_ENUM_IMPL(qemuDeviceVideo,
"" /* don't support gop */, "" /* don't support gop */,
"" /* 'none' doesn't make sense here */, "" /* 'none' doesn't make sense here */,
"bochs-display", "bochs-display",
"ramfb",
); );
VIR_ENUM_DECL(qemuDeviceVideoSecondary); VIR_ENUM_DECL(qemuDeviceVideoSecondary);
...@@ -150,6 +152,7 @@ VIR_ENUM_IMPL(qemuDeviceVideoSecondary, ...@@ -150,6 +152,7 @@ VIR_ENUM_IMPL(qemuDeviceVideoSecondary,
"" /* don't support gop */, "" /* don't support gop */,
"" /* 'none' doesn't make sense here */, "" /* 'none' doesn't make sense here */,
"" /* no secondary device for bochs */, "" /* no secondary device for bochs */,
"" /* no secondary device for ramfb */,
); );
VIR_ENUM_DECL(qemuSoundCodec); VIR_ENUM_DECL(qemuSoundCodec);
......
...@@ -5725,6 +5725,7 @@ qemuDomainDeviceDefValidateVideo(const virDomainVideoDef *video) ...@@ -5725,6 +5725,7 @@ qemuDomainDeviceDefValidateVideo(const virDomainVideoDef *video)
case VIR_DOMAIN_VIDEO_TYPE_QXL: case VIR_DOMAIN_VIDEO_TYPE_QXL:
case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
case VIR_DOMAIN_VIDEO_TYPE_BOCHS: case VIR_DOMAIN_VIDEO_TYPE_BOCHS:
case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
case VIR_DOMAIN_VIDEO_TYPE_LAST: case VIR_DOMAIN_VIDEO_TYPE_LAST:
break; break;
} }
......
...@@ -936,6 +936,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, ...@@ -936,6 +936,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: case VIR_DOMAIN_VIDEO_TYPE_DEFAULT:
case VIR_DOMAIN_VIDEO_TYPE_GOP: case VIR_DOMAIN_VIDEO_TYPE_GOP:
case VIR_DOMAIN_VIDEO_TYPE_NONE: case VIR_DOMAIN_VIDEO_TYPE_NONE:
case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
case VIR_DOMAIN_VIDEO_TYPE_LAST: case VIR_DOMAIN_VIDEO_TYPE_LAST:
return 0; return 0;
} }
...@@ -1787,8 +1788,10 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, ...@@ -1787,8 +1788,10 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
return -1; return -1;
} }
/* ramfb is not a PCI device */
if (def->nvideos > 0 && if (def->nvideos > 0 &&
def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE) { def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE &&
def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_RAMFB) {
/* Because the PIIX3 integrated IDE/USB controllers are /* Because the PIIX3 integrated IDE/USB controllers are
* already at slot 1, when qemu looks for the first free slot * already at slot 1, when qemu looks for the first free slot
* to place the VGA controller (which is always the first * to place the VGA controller (which is always the first
...@@ -1971,8 +1974,10 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, ...@@ -1971,8 +1974,10 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
return -1; return -1;
} }
/* ramfb is not a PCI device */
if (def->nvideos > 0 && if (def->nvideos > 0 &&
def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE) { def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE &&
def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_RAMFB) {
/* NB: unlike the pc machinetypes, on q35 machinetypes the /* NB: unlike the pc machinetypes, on q35 machinetypes the
* integrated devices are at slot 0x1f, so when qemu looks for * integrated devices are at slot 0x1f, so when qemu looks for
* the first free slot for the first VGA, it will always be at * the first free slot for the first VGA, it will always be at
...@@ -2351,7 +2356,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, ...@@ -2351,7 +2356,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
/* Video devices */ /* Video devices */
for (i = 0; i < def->nvideos; i++) { for (i = 0; i < def->nvideos; i++) {
if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE) if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE ||
def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_RAMFB)
continue; continue;
if (!virDeviceInfoPCIAddressIsWanted(&def->videos[i]->info)) if (!virDeviceInfoPCIAddressIsWanted(&def->videos[i]->info))
......
...@@ -5273,7 +5273,9 @@ qemuProcessStartValidateVideo(virDomainObjPtr vm, ...@@ -5273,7 +5273,9 @@ qemuProcessStartValidateVideo(virDomainObjPtr vm,
video->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && video->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_GPU_CCW)) || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_GPU_CCW)) ||
(video->type == VIR_DOMAIN_VIDEO_TYPE_BOCHS && (video->type == VIR_DOMAIN_VIDEO_TYPE_BOCHS &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_BOCHS_DISPLAY))) { !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_BOCHS_DISPLAY)) ||
(video->type == VIR_DOMAIN_VIDEO_TYPE_RAMFB &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_RAMFB))) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("this QEMU does not support '%s' video device"), _("this QEMU does not support '%s' video device"),
virDomainVideoTypeToString(video->type)); virDomainVideoTypeToString(video->type));
......
LC_ALL=C \
PATH=/bin \
HOME=/tmp/lib/domain--1-QEMUGuest1 \
USER=test \
LOGNAME=test \
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
QEMU_AUDIO_DRV=none \
/usr/bin/qemu-system-i686 \
-name guest=QEMUGuest1,debug-threads=on \
-S \
-object secret,id=masterKey0,format=raw,\
file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
-machine pc,accel=tcg,usb=off,dump-guest-core=off \
-m 1024 \
-overcommit mem-lock=off \
-smp 1,sockets=1,cores=1,threads=1 \
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
-display none \
-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 \
-drive file=/var/lib/libvirt/images/QEMUGuest1,format=qcow2,if=none,\
id=drive-ide0-0-0,cache=none \
-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1,\
write-cache=on \
-device ramfb,id=video0 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
resourcecontrol=deny \
-msg timestamp=on
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu>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>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/var/lib/libvirt/images/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='ide' index='0'/>
<video>
<model type='ramfb' />
</video>
<memballoon model='virtio'/>
</devices>
</domain>
...@@ -2083,6 +2083,7 @@ mymain(void) ...@@ -2083,6 +2083,7 @@ mymain(void)
QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS); QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS);
DO_TEST_CAPS_LATEST("video-bochs-display-device"); DO_TEST_CAPS_LATEST("video-bochs-display-device");
DO_TEST_CAPS_LATEST("video-ramfb-display-device");
DO_TEST("video-none-device", DO_TEST("video-none-device",
QEMU_CAPS_VNC); QEMU_CAPS_VNC);
DO_TEST_PARSE_ERROR("video-invalid-multiple-devices", NONE); DO_TEST_PARSE_ERROR("video-invalid-multiple-devices", NONE);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册