summaryrefslogtreecommitdiffstats
path: root/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/includes/passthrough-mdev.inc
blob: f2e2942bf99dbf0c3c67e5c0b17ca3c935828ef6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# -----------------------------------------------------------------------------
#
# 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

		# 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
			return 2;
		fi

		echo "${pt_gpu_mdev_id}"
	fi

	return 0;
}