cpu: Prefer maximum mode for many emulated guests

The actual default CPU at the QEMU level is often a relatively
poor choice, which is stuck with just baseline functionality
and can sometimes not run modern guests at all.

Whenever possible, prefer maximum mode for a much nicer out of
the box experience.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
This commit is contained in:
Andrea Bolognani 2024-12-06 23:02:29 +01:00 committed by Pavel Hrdina
parent 11b70218d3
commit 8af438dd58
13 changed files with 40 additions and 11 deletions

View File

@ -18,9 +18,7 @@
<features> <features>
<acpi/> <acpi/>
</features> </features>
<cpu mode="custom" match="exact"> <cpu mode="maximum"/>
<model>cortex-a57</model>
</cpu>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-aarch64</emulator> <emulator>/usr/bin/qemu-system-aarch64</emulator>

View File

@ -18,9 +18,7 @@
<features> <features>
<acpi/> <acpi/>
</features> </features>
<cpu mode="custom" match="exact"> <cpu mode="maximum"/>
<model>cortex-a57</model>
</cpu>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-aarch64</emulator> <emulator>/usr/bin/qemu-system-aarch64</emulator>

View File

@ -15,6 +15,7 @@
<initrd>/f19-arm.initrd</initrd> <initrd>/f19-arm.initrd</initrd>
<cmdline>foo</cmdline> <cmdline>foo</cmdline>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-arm</emulator> <emulator>/usr/bin/qemu-system-arm</emulator>

View File

@ -15,6 +15,7 @@
<initrd>/f19-arm.initrd</initrd> <initrd>/f19-arm.initrd</initrd>
<cmdline>console=ttyAMA0,1234 rw root=/dev/vda3</cmdline> <cmdline>console=ttyAMA0,1234 rw root=/dev/vda3</cmdline>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-arm</emulator> <emulator>/usr/bin/qemu-system-arm</emulator>

View File

@ -14,6 +14,7 @@
<boot dev="cdrom"/> <boot dev="cdrom"/>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>
@ -92,6 +93,7 @@
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -12,6 +12,7 @@
<os firmware="efi"> <os firmware="efi">
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>
@ -87,6 +88,7 @@
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -13,6 +13,7 @@
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -13,6 +13,7 @@
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -15,6 +15,7 @@
<initrd>/initrd.img</initrd> <initrd>/initrd.img</initrd>
<cmdline>root=/dev/vda2</cmdline> <cmdline>root=/dev/vda2</cmdline>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -12,6 +12,7 @@
<os firmware="efi"> <os firmware="efi">
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>
@ -90,6 +91,7 @@
<type arch="riscv64" machine="virt">hvm</type> <type arch="riscv64" machine="virt">hvm</type>
<boot dev="hd"/> <boot dev="hd"/>
</os> </os>
<cpu mode="maximum"/>
<clock offset="utc"/> <clock offset="utc"/>
<devices> <devices>
<emulator>/usr/bin/qemu-system-riscv64</emulator> <emulator>/usr/bin/qemu-system-riscv64</emulator>

View File

@ -1247,7 +1247,7 @@ c.add_compare("--connect %(URI-KVM-ARMV7L)s --disk %(EXISTIMG1)s --import --os-v
c.add_valid("--arch aarch64 --osinfo fedora19 --nodisks --pxe --connect " + utils.URIs.kvm_x86_nodomcaps, grep="Libvirt version does not support UEFI") # attempt to default to aarch64 UEFI, but it fails, but should only print warnings c.add_valid("--arch aarch64 --osinfo fedora19 --nodisks --pxe --connect " + utils.URIs.kvm_x86_nodomcaps, grep="Libvirt version does not support UEFI") # attempt to default to aarch64 UEFI, but it fails, but should only print warnings
c.add_invalid("--arch aarch64 --nodisks --pxe --connect " + utils.URIs.kvm_x86, grep="OS name is required") # catch missing osinfo for non-x86 c.add_invalid("--arch aarch64 --nodisks --pxe --connect " + utils.URIs.kvm_x86, grep="OS name is required") # catch missing osinfo for non-x86
c.add_compare("--arch aarch64 --osinfo fedora19 --machine virt --boot kernel=/f19-arm.kernel,initrd=/f19-arm.initrd,kernel_args=\"console=ttyAMA0,1234 rw root=/dev/vda3\" --disk %(EXISTIMG1)s", "aarch64-machvirt") c.add_compare("--arch aarch64 --osinfo fedora19 --machine virt --cpu default --boot kernel=/f19-arm.kernel,initrd=/f19-arm.initrd,kernel_args=\"console=ttyAMA0,1234 rw root=/dev/vda3\" --disk %(EXISTIMG1)s", "aarch64-machvirt")
c.add_compare("--arch aarch64 --osinfo fedora19 --boot kernel=/f19-arm.kernel,initrd=/f19-arm.initrd,kernel_args=\"console=ttyAMA0,1234 rw root=/dev/vda3\" --disk %(EXISTIMG1)s", "aarch64-machdefault") c.add_compare("--arch aarch64 --osinfo fedora19 --boot kernel=/f19-arm.kernel,initrd=/f19-arm.initrd,kernel_args=\"console=ttyAMA0,1234 rw root=/dev/vda3\" --disk %(EXISTIMG1)s", "aarch64-machdefault")
c.add_compare("--arch aarch64 --cdrom %(ISO-F26-NETINST)s --boot loader=CODE.fd,nvram.template=VARS.fd --disk %(EXISTIMG1)s --cpu none --events on_crash=preserve,on_reboot=destroy,on_poweroff=restart", "aarch64-cdrom") # cdrom test, but also --cpu none override, --events override, and headless c.add_compare("--arch aarch64 --cdrom %(ISO-F26-NETINST)s --boot loader=CODE.fd,nvram.template=VARS.fd --disk %(EXISTIMG1)s --cpu none --events on_crash=preserve,on_reboot=destroy,on_poweroff=restart", "aarch64-cdrom") # cdrom test, but also --cpu none override, --events override, and headless
c.add_compare("--connect %(URI-KVM-AARCH64)s --disk %(EXISTIMG1)s --import --os-variant fedora21 --panic default --graphics vnc", "aarch64-kvm-import") # --import test, but also test --panic no-op, and --graphics c.add_compare("--connect %(URI-KVM-AARCH64)s --disk %(EXISTIMG1)s --import --os-variant fedora21 --panic default --graphics vnc", "aarch64-kvm-import") # --import test, but also test --panic no-op, and --graphics

View File

@ -275,11 +275,26 @@ class DomainCpu(XMLBuilder):
SPECIAL_MODE_HOST_PASSTHROUGH, SPECIAL_MODE_MAXIMUM, SPECIAL_MODE_HOST_PASSTHROUGH, SPECIAL_MODE_MAXIMUM,
SPECIAL_MODE_CLEAR, SPECIAL_MODE_APP_DEFAULT] SPECIAL_MODE_CLEAR, SPECIAL_MODE_APP_DEFAULT]
def _should_use_maximum_cpu_mode(self, guest, domcaps):
if (domcaps.supports_maximum_cpu_mode() and
guest.type == "qemu" and
(guest.os.is_x86() or
guest.os.is_arm_machvirt() or
guest.os.is_riscv_virt() or
guest.os.is_loongarch64())):
return True
return False
def _get_app_default_mode(self, guest): def _get_app_default_mode(self, guest):
# Depending on if libvirt+qemu is new enough, we prefer # Depending on if libvirt+qemu is new enough, we prefer
# host-passthrough, then host-model, and finally host-model-only # host-passthrough, then host-model, and finally host-model-only
# Emulated guests use maximum mode if available
domcaps = guest.lookup_domcaps() domcaps = guest.lookup_domcaps()
if (self._should_use_maximum_cpu_mode(guest, domcaps)):
return self.SPECIAL_MODE_MAXIMUM
if domcaps.supports_safe_host_passthrough(): if domcaps.supports_safe_host_passthrough():
return self.SPECIAL_MODE_HOST_PASSTHROUGH return self.SPECIAL_MODE_HOST_PASSTHROUGH
@ -460,9 +475,12 @@ class DomainCpu(XMLBuilder):
if guest.os.is_arm_machvirt() and guest.type == "kvm": if guest.os.is_arm_machvirt() and guest.type == "kvm":
self.mode = self.SPECIAL_MODE_HOST_PASSTHROUGH self.mode = self.SPECIAL_MODE_HOST_PASSTHROUGH
elif guest.os.is_arm64() and guest.os.is_arm_machvirt():
# -M virt defaults to a 32bit CPU, even if using aarch64
self.set_model(guest, "cortex-a57")
elif guest.os.is_x86() and guest.type == "kvm": elif guest.os.is_x86() and guest.type == "kvm":
self._set_cpu_x86_kvm_default(guest) self._set_cpu_x86_kvm_default(guest)
else:
domcaps = guest.lookup_domcaps()
# Prefer to emulate a feature-rich CPU instead of a basic one
if (self._should_use_maximum_cpu_mode(guest, domcaps)):
self.set_special_mode(guest, self.SPECIAL_MODE_MAXIMUM)

View File

@ -382,6 +382,10 @@ class DomainCapabilities(XMLBuilder):
return (m and m.supported and return (m and m.supported and
"on" in m.get_enum("hostPassthroughMigratable").get_values()) "on" in m.get_enum("hostPassthroughMigratable").get_values())
def supports_maximum_cpu_mode(self):
m = self.cpu.get_mode("maximum")
return (m and m.supported)
def get_cpu_models(self): def get_cpu_models(self):
models = [] models = []