From 59c06daaf9abfec2fa258729dd3b22cb7c70a59c Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 20 Jul 2023 11:09:42 +0200 Subject: [qemu] Add workaround for weird qemu crash with edk2 on Alderlake ... at least one specific model with P and E cores ... --- .../qemu/data/usr/bin/qemu-system-x86_64.openslx | 73 ++++++++++++++++++++++ .../java/org/openslx/runvirt/plugin/qemu/App.java | 7 ++- .../TransformationGenericWrapperScript.java | 63 +++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100755 core/modules/qemu/data/usr/bin/qemu-system-x86_64.openslx create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericWrapperScript.java diff --git a/core/modules/qemu/data/usr/bin/qemu-system-x86_64.openslx b/core/modules/qemu/data/usr/bin/qemu-system-x86_64.openslx new file mode 100755 index 00000000..bc743f48 --- /dev/null +++ b/core/modules/qemu/data/usr/bin/qemu-system-x86_64.openslx @@ -0,0 +1,73 @@ +#!/bin/sh + +bin="${0%.openslx}" + +allflags="$( "$bin" -cpu help | sed -En '/^Recognized CPUID flags:/,/^$/s/ +/,+/gp' | tail -n+2 | tr -d '\n' )" + +replace_params () { + modelname= + model= + family= + stepping= + vendor= + for i; do + shift + case "$i" in + migratable=*) + continue + ;; + model=*) + model=1 + ;; + model-id=*) + modelname=1 + ;; + family=*) + family=1 + ;; + stepping=*) + stepping=1 + ;; + vendor=*) + vendor=1 + ;; + *) + ;; + esac + set -- "$@" "$i" + done + [ -z "$modelname" ] && set -- "$@" "model-id=$( awk '/^model name\s/ {print substr($0,index($0, ":")+2); exit}' /proc/cpuinfo )" + [ -z "$vendor" ] && set -- "$@" "vendor=$( awk '/^vendor_id\s/ {print substr($0,index($0, ":")+2); exit}' /proc/cpuinfo )" + [ -z "$model" ] && set -- "$@" "model=$( awk '$1$2 == "model:" {print $3; exit}' /proc/cpuinfo )" + [ -z "$family" ] && set -- "$@" "family=$( awk '$1$2$3 == "cpufamily:" {print $4; exit}' /proc/cpuinfo )" + [ -z "$stepping" ] && set -- "$@" "stepping=$( awk '$1$2 == "stepping:" {print $3; exit}' /proc/cpuinfo )" + printf "%s" "$*" +} + +i="$#" +while [ "$i" -gt 0 ]; do + case "$1" in + -cpu) + case "$2" in + host|max) + set -- "$@" -cpu "Cascadelake-Server$allflags" + : "$(( i -= 2 ))" + shift 2 + continue + ;; + host*|max*) + params="${2#*,}" + params="$( set -f ; IFS=, ; replace_params $params )" + set -- "$@" -cpu "Cascadelake-Server,$params$allflags" + : "$(( i -= 2 ))" + shift 2 + continue + ;; + esac + esac + set -- "$@" "$1" + : "$(( i -= 1 ))" + shift 1 +done + +exec "$bin" "$@" diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java index a5349316..6a0dc9cb 100644 --- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java +++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java @@ -27,6 +27,7 @@ import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericName; import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericParallelDevices; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuSerialDevices; import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericUuid; +import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericWrapperScript; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuArchitecture; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuFirmware; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGpuPassthroughNvidia; @@ -162,6 +163,9 @@ public class App transformationManager.register( new TransformationSpecificQemuGpuPassthroughNvidia( hypervisorQemu ), false ); } + // Needs to be last one since TransformationSpecificQemuArchitecture sets this too + transformationManager.register( new TransformationGenericWrapperScript(), true ); + // finalize Libvirt VM configuration template try { transformationManager.transform(); @@ -202,9 +206,8 @@ public class App final File xmlOutputFile = new File( xmlOutputFileName ); config.toXml( xmlOutputFile ); } catch ( NullPointerException | LibvirtXmlSerializationException e ) { + // We only call this for debugging purposes, don't bail out but log LOGGER.error( "Failed to write VM output configuration file: " + e.getLocalizedMessage() ); - hypervisor.close(); - System.exit( 5 ); } } diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericWrapperScript.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericWrapperScript.java new file mode 100644 index 00000000..60c98d47 --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericWrapperScript.java @@ -0,0 +1,63 @@ +package org.openslx.runvirt.plugin.qemu.configuration; + +import java.io.File; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.openslx.libvirt.domain.Domain; +import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs; +import org.openslx.util.Util; +import org.openslx.virtualization.configuration.transformation.TransformationException; +import org.openslx.virtualization.configuration.transformation.TransformationGeneric; + +/** + * Use openslx wrapper script for launching the emulator (virtualizer) + * + * @author sr + */ +public class TransformationGenericWrapperScript extends TransformationGeneric +{ + /** + * Instance of a logger to log messages. + */ + private static final Logger LOGGER = LogManager.getLogger( TransformationGenericWrapperScript.class ); + + /** + * Name of the configuration transformation. + */ + private static final String NAME = "Use wrapper script for emulator if found"; + + /** + * Extension for the wrapper we look for + */ + private static final String WRAPPER_EXT = ".openslx"; + + public TransformationGenericWrapperScript() + { + super( TransformationGenericWrapperScript.NAME ); + } + + /** + * Validates a virtualization configuration and input arguments for this transformation. + */ + private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException + { + if ( config == null || args == null ) { + throw new TransformationException( "Virtualization configuration or input arguments are missing!" ); + } + } + + @Override + public void transform( Domain config, CommandLineArgs args ) throws TransformationException + { + // validate configuration and input arguments + this.validateInputs( config, args ); + + // Use our wrapper if it exists + String emu = config.getDevicesEmulator(); + if ( !Util.isEmptyString( emu ) && new File( emu + WRAPPER_EXT ).canExecute() ) { + LOGGER.info( "Using emulator wrapper " + emu + WRAPPER_EXT ); + config.setDevicesEmulator( emu + WRAPPER_EXT ); + } + } +} -- cgit v1.2.3-55-g7522