diff options
author | Manuel Bentele | 2021-08-23 12:00:17 +0200 |
---|---|---|
committer | Manuel Bentele | 2021-08-23 12:00:17 +0200 |
commit | 5f9ff0a607985298e1a51f45f37110d88466ec3b (patch) | |
tree | e09908d2696d4e7b5f36ade9ccabe9c303c868b9 | |
parent | [qemu] Replace spaces with tabs in PCI passthrough include (diff) | |
download | mltk-5f9ff0a607985298e1a51f45f37110d88466ec3b.tar.gz mltk-5f9ff0a607985298e1a51f45f37110d88466ec3b.tar.xz mltk-5f9ff0a607985298e1a51f45f37110d88466ec3b.zip |
[qemu] Add setup of a global Intel GVT-g instance if GVT-g is enabled
3 files changed, 212 insertions, 0 deletions
diff --git a/core/modules/qemu/data/opt/openslx/scripts/systemd-qemu_env b/core/modules/qemu/data/opt/openslx/scripts/systemd-qemu_env index b71919de..ffa54ce1 100755 --- a/core/modules/qemu/data/opt/openslx/scripts/systemd-qemu_env +++ b/core/modules/qemu/data/opt/openslx/scripts/systemd-qemu_env @@ -44,3 +44,46 @@ if [ ! -e /dev/kvm ]; then slxlog "qemu" "/dev/kvm not found! Missing kvm kernel module(s)?" exit 1 fi + +# +# create and setup Intel GVT-g mediated device instance for passthrough if Intel GVT-g is enabled +# +source /opt/openslx/vmchooser/plugins/qemukvm/includes/kernel-cmdln.inc +source /opt/openslx/vmchooser/plugins/qemukvm/includes/passthrough-mdev.inc + +if passthrough_mdev_enabled; then + # check if passthrough is configured properly + if ! passthrough_mdev_check; then + slxlog "qemu" "mediated device passthrough is enabled but not setup properly!" + exit 2; + fi + + # load required kernel modules for mediated device passthrough + modprobe "vfio-mdev" || { slxlog "qemu" "Could not load 'vfio-mdev' kernel modul!"; exit 3; } + modprobe "kvmgt" || { slxlog "qemu" "Could not load 'kvmgt' kernel modul!"; exit 4; } + + # get Intel integrated GPU mediated device for passthrough + local pt_mdev_device="$(passthrough_mdev_device_get_intel_igd)" + if [ -z "${pt_mdev_device}" ]; then + slxlog "qemu" "Could find any Intel integrated GPU with mediated device (Intel GVT-g) support!" + exit 5; + fi + + # get Intel GVT-g mediated device instance type + local pt_mdev_device_type="$(passthrough_mdev_type_get "${pt_mdev_device}")" + if [ -z "${pt_mdev_device_type}" ]; then + slxlog "qemu" "Could obtain the mediated device instance type of the Intel integrated GPU (${pt_mdev_device})" + exit 6; + fi + + # generate UUID for Intel GVT-g mediated device instance + local pt_mdev_uuid="$(uuidgen)" + + # create Intel GVT-g mediated device instance + passthrough_mdev_instance_create "${pt_mdev_device}" "${pt_mdev_device_type}" "${pt_mdev_uuid}" + if [ "${?}" -eq 0 ]; then + slxlog "qemu" "Successfully created Intel GVT-g mediated device instance (${pt_mdev_uuid})" + else + slxlog "qemu" "Failed to create Intel GVT-g mediated device instance!" + fi +fi diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/includes/passthrough-mdev.inc b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/includes/passthrough-mdev.inc new file mode 100644 index 00000000..067cc35d --- /dev/null +++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/includes/passthrough-mdev.inc @@ -0,0 +1,163 @@ +# ----------------------------------------------------------------------------- +# +# Copyright (c) 2009..2021 bwLehrpool-Projektteam +# +# This program/file is free software distributed under the GPL version 2. +# See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +# +# If you have any feedback please consult https://bwlehrpool.de and +# send your feedback to support@bwlehrpool.de. +# +# General information about bwLehrpool can be found at https://bwlehrpool.de +# +# ----------------------------------------------------------------------------- +# Utils and functions to setup mediated device passthrough (Intel GVT-g) +# ----------------------------------------------------------------------------- + +# Function to get state of passthrough +# Return : 0 (true) if passthrough is enabled, otherwise 1 (false) +function passthrough_mdev_enabled() { + local passthrough_iommu="$(kernel_cmdln_parse_option "iommu")" + local intel_gvt="$(kernel_cmdln_parse_option "i915.enable_gvt")" + if [ "${passthrough_iommu}" == "pt" ] && [ "${intel_gvt}" -eq 1 ]; then + return 0 + else + return 1 + fi +} + +# Function to check validitiy of the passthrough configuration +# Return : 0 (true) if passthrough is configured properly, otherwise 1 (false) +function passthrough_mdev_check() { + local passthrough_iommu_intel="$(kernel_cmdln_parse_option "intel_iommu")" + local passthrough_iommu_amd="$(kernel_cmdln_parse_option "amd_iommu")" + if [ "${passthrough_iommu_intel}" != "on" ] && [ "${passthrough_iommu_amd}" != "on" ]; then + return 1 + else + return 0 + fi +} + +# Function to list all physical devices that support mediated device passthrough +# Return : list of PCI addresses from devices that support mediated device passthrough +function passthrough_mdev_devices() { + mdevctl types --dumpjson | jq -r ".[] | keys | .[]" +} + +# Function to check if a physical device, that supports mediated device passthrough, is an Intel integrated GPU +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Return : 0 (true) if physical device is an Intel integrated GPU, otherwise 1 (false) +function passthrough_mdev_device_is_intel_igd() { + local pt_mdev_device_pci_info="$(lspci -vmm -n -s "${1}")" + local pt_mdev_device_pci_vendor="$(awk '$1 = /^Vendor:/ {print $2}' <<< "${pt_mdev_device_pci_info}")" + local pt_mdev_device_pci_class="$(awk '$1 = /^Class:/ {print $2}' <<< "${pt_mdev_device_pci_info}")" + if [ "${pt_mdev_device_pci_vendor}" = "8086" ] && [ "${pt_mdev_device_pci_class}" = "0300" ]; then + return 0; + else + return 1; + fi +} + +# Function to get the first physical device that supports mediated device passthrough and is an Intel integrated GPU +# Return : PCI address of the physical device that supports mediated device passthrough and is an Intel integrated GPU +function passthrough_mdev_device_get_intel_igd() { + local pt_mdev_devices_addresses=($(passthrough_mdev_devices)) + for pt_mdev_device_address in ${pt_mdev_devices_addresses[@]}; do + # check if device is an Intel integrated GPU + if passthrough_mdev_device_is_intel_igd "${pt_mdev_device_address}"; then + echo "${pt_mdev_device_address}" + return 0; + fi + done + + return 1; +} + +# Function to list all mediated device instance types of a specified physical device +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Return : list of mediated device instance types supported by the specified physical device +function passthrough_mdev_types() { + mdevctl types --dumpjson | jq -r ".[] | .\"${1}\" | .[] | keys | .[]" +} + +# Function to get the first mediated device instance type of a specified physical device +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Return : first mediated device instance type supported by the specified physical device +function passthrough_mdev_type_get() { + local pt_mdev_device_types=($(passthrough_mdev_types "${1}")) + if [ "${#pt_mdev_device_types[@]}" -gt 0 ]; then + echo "${pt_mdev_device_types[0]}" + return 0; + else + return 1; + fi +} + +# Function to get the description of a specified mediated device instance type +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Parameter 2: mediated device instance type supported by the specified physical device +# Return : description of the mediated device instance type supported by the specified physical device +function passthrough_mdev_type_description() { + mdevctl types --dumpjson | jq -r ".[] | .\"${1}\" | .[] | select(.\"${2}\") | .[] | .\"description\"" +} + +# Function to get the available instance count of a specified mediated device instance type +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Parameter 2: mediated device instance type supported by the specified physical device +# Return : available instances of the mediated device instance type supported by the specified physical device +function passthrough_mdev_type_num_instances() { + mdevctl types --dumpjson | jq -r ".[] | .\"${1}\" | .[] | select(.\"${2}\") | .[] | .\"available_instances\"" +} + +# Function to create a new mediated device instance +# Parameter 1: PCI address of the physical device that supports mediated device passthrough +# Parameter 2: mediated device instance type supported by the specified physical device +# Parameter 3: UUID for the created mediated device instance +function passthrough_mdev_instance_create() { + mdevctl start --parent "${1}" --type "${2}" --uuid "${3}" +} + +# Function to delete an existing mediated device instance +# Parameter 1: UUID of the existing mediated device instance +function passthrough_mdev_instance_delete() { + mdevctl stop --uuid "${1}" +} + +# Function to obtain mediated device UUID of a globally created mediated device (Intel GVT-g) instance for passthrough +# Return : mediated device UUID of a globally created mediated device (Intel GVT-g) instance +function passthrough_mdev_instance_get() { + local passthrough_mdev_instances=($(mdevctl list | cut -d ' ' -f 1)) + if [ "${#passthrough_mdev_instances[@]}" -eq 1 ]; then + echo "${passthrough_mdev_instances[0]}" + return 0; + else + return 1; + fi +} + +# Function to setup mediated device passthrough +# Return : mediated device ID of the specified and configured mediated device (Intel GVT-g instance) for passthrough +function passthrough_mdev_setup() { + # check if passthrough is enabled + if passthrough_mdev_enabled; then + # check if passthrough is configured properly + if ! passthrough_mdev_check; then + return 1; + fi + + writelog "Passthrough of mediated devices (mdev) is enabled successfully" + + # obtain created mediated device for passthrough + local pt_gpu_mdev_id="$(passthrough_mdev_instance_get)" + + # check if mediated device ID could be obtained + if [ -z "${pt_gpu_mdev_id}" ]; then + writelog "Failed to obtain created mediated device UUID" + return 2; + fi + + echo "${pt_gpu_mdev_id}" + fi + + return 0; +} diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include index e497dda2..12239b4e 100644 --- a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include +++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include @@ -27,6 +27,8 @@ run_plugin() { $(safesource "${QEMU_INCLUDE_DIR}/kernel-cmdln.inc") # include PCI passthrough utils and functions $(safesource "${QEMU_INCLUDE_DIR}/passthrough-pci.inc") + # include mediated device passthrough utils and functions + $(safesource "${QEMU_INCLUDE_DIR}/passthrough-mdev.inc") # setup RW image access for operation local vm_diskfile @@ -43,6 +45,9 @@ run_plugin() { # setup GPU passthrough and obtain PCI addresses and IDs if passthrough is enabled local pt_gpu_pci_ids=($(passthrough_pci_setup)) + # setup GPU mediated device passthrough and obtain mediated device address + local pt_gpu_mdev_id=($(passthrough_mdev_setup)) + # write finalized config in debug mode to temporary folder for debugging purposes if [ "${DEBUG}" = "true" ]; then local vm_final_config="/tmp/qemu-last-config.xml" @@ -69,6 +74,7 @@ run_plugin() { notempty CDROM_1 && VIRTCMDOPTS+=( "-vmcdrom1" "${CDROM_1}" ) notempty SERIAL0 && VIRTCMDOPTS+=( "-vmserial0" "${SERIAL0}" ) notempty PARALLEL0 && VIRTCMDOPTS+=( "-vmparallel0" "${PARALLEL0}" ) + notempty pt_gpu_mdev_id && VIRTCMDOPTS+=( "-vmilmdevid0" "${pt_gpu_mdev_id}" ) if [ "${SHARE_REMAP_MODE}" -gt 1 ]; then notempty HOME_SHARE_PATH && VIRTCMDOPTS+=( "-vmfssrc0" "${HOME_SHARE_PATH}" ) |