-
Notifications
You must be signed in to change notification settings - Fork 3
/
gpu-pt-check.sh
executable file
·220 lines (189 loc) · 9.32 KB
/
gpu-pt-check.sh
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/bin/bash
DIR=$(cd "$(dirname "$0")"; pwd)
# Enable these to mock the lshw output and iommu groups of other computers for testing purposes
#MOCK_SET=5
#LSHW_MOCK="$DIR/mock-data/$MOCK_SET-lshw"
#LSIOMMU_MOCK="$DIR/mock-data/$MOCK_SET-lsiommu"
if [ -z ${LSIOMMU_MOCK+x} ]; then
IOMMU_GROUPS=$("$DIR/lsiommu.sh")
MOCK_MODE=false
else
IOMMU_GROUPS=$(cat "$LSIOMMU_MOCK")
MOCK_MODE=true
fi
if [ -z ${LSHW_MOCK+x} ]; then
GPU_INFO=$(sudo lshw -class display -businfo)
else
GPU_INFO=$(cat "$LSHW_MOCK")
fi
LOG_OUTPUT=""
function log() {
LOG_OUTPUT="${LOG_OUTPUT}$@\n"
}
NC='\033[0m' # No Color
RED='\033[0;31m'
GREEN='\033[0;32m'
ORANGE='\033[1;33m'
function log_red() {
echo -e "${RED}$@${NC}"
log "$@"
}
function log_green() {
echo -e "${GREEN}$@${NC}"
log "$@"
}
function log_orange() {
echo -e "${ORANGE}$@${NC}"
log "$@"
}
function log_white() {
echo -e "$@"
}
if [ "$MOCK_MODE" = true ]; then
log_red "[Warning] Using mock data! The following output has nothing to do with this system!"
fi
# Check if UEFI is configured correctly
if systool -m kvm_intel -v &> /dev/null || systool -m kvm_amd -v &> /dev/null ; then
UEFI_VIRTUALIZATION_ENABLED=true
log_green "[OK] VT-X / AMD-V virtualization is enabled in the UEFI."
else
UEFI_VIRTUALIZATION_ENABLED=false
log_orange "[Warning] VT-X / AMD-V virtualization is not enabled in the UEFI! This is required to run virtual machines!"
fi
if [ "$IOMMU_GROUPS" != "" ] ; then
UEFI_IOMMU_ENABLED=true
log_green "[OK] VT-D / IOMMU is enabled in the UEFI."
else
UEFI_IOMMU_ENABLED=false
log_red "[Error] VT-D / IOMMU is not enabled in the UEFI! This is required to check which devices are in which IOMMU group and to use GPU pass-through!"
fi
# Check if kernel is configured correctly
if cat /proc/cmdline | grep --quiet iommu ; then
KERNEL_IOMMU_ENABLED=true
log_green "[OK] The IOMMU kernel parameters are set."
else
KERNEL_IOMMU_ENABLED=false
log_red "[Error] The iommu kernel parameters are missing! You have to add them in roder to use GPU pass-through!"
fi
GPU_IDS=($(echo "$GPU_INFO" | grep "pci@" | cut -d " " -f 1 | cut -d ":" -f 2-))
GOOD_GPUS=()
BAD_GPUS=()
for GPU_ID in "${GPU_IDS[@]}"; do
GPU_IOMMU_GROUP=$(echo "$IOMMU_GROUPS" | grep $GPU_ID | cut -d " " -f 3)
if [ "$GPU_IOMMU_GROUP" == "" ] ; then
log_red "[Error] Failed to find the IOMMU group of the GPU with the ID $GPU_ID! Have you enabled iommu in the UEFI and kernel?"
else
OTHER_DEVICES_IN_GPU_GROUP=$(echo "$IOMMU_GROUPS" | grep "IOMMU Group $GPU_IOMMU_GROUP " | grep -v $GPU_ID | grep -v " Audio device " | grep -v " PCI bridge ")
OTHER_DEVICES_IN_GPU_GROUP_NO_GPUS=$(echo $OTHER_DEVICES_IN_GPU_GROUP | grep -v " VGA compatible controller " | grep -v " 3D controller ")
if [ "$OTHER_DEVICES_IN_GPU_GROUP" == "" ] ; then
log_green "[Success] GPU with ID '$GPU_ID' could be passed through to a virtual machine!"
GOOD_GPUS+=("$GPU_ID")
elif [ "$OTHER_DEVICES_IN_GPU_GROUP_NO_GPUS" = "" ] ; then
log_orange "[Warning] GPU with ID '$GPU_ID' could be passed through to a virtual machine, but only together with the following devices: "
log_orange "$OTHER_DEVICES_IN_GPU_GROUP"
GOOD_GPUS+=("$GPU_ID")
else
log_orange "[Problem] Other devices have been found in the IOMMU group of the GPU with the ID '$GPU_ID'. Depending on the devices, this could make GPU pass-through impossible to pass this GPU through to a virtual machine!"
log_orange "The devices found in this GPU's IOMMU Group are:"
log_red "$OTHER_DEVICES_IN_GPU_GROUP"
log_white "[Info] It might be possible to get it to work by putting the devices in different slots on the motherboard and or by using the ACS override patch. Otherwise you'll probably have to get a different motherboard. If you're on a laptop, there is nothing you can do as far as I'm aware. Although it would theoretically be possible for ACS support for laptops to exist. TODO: Find a way to check if the current machine has support for that."
BAD_GPUS+=("$GPU_ID")
fi
fi
done
GPU_LIST="Is Compatible?|Name|IOMMU_GROUP|PCI Address"
for GPU_ID in "${BAD_GPUS[@]}"; do
PCI_ADDRESS="pci@0000:${GPU_ID}"
NAME=$(echo "$GPU_INFO" | grep "$GPU_ID" | tr -s " " | cut -d " " -f 3-)
IOMMU_GROUP=$(echo "$IOMMU_GROUPS" | grep $GPU_ID | cut -d " " -f 3)
GPU_LIST="${GPU_LIST}\nNo|${NAME}|${IOMMU_GROUP}|${PCI_ADDRESS}"
done
for GPU_ID in "${GOOD_GPUS[@]}"; do
PCI_ADDRESS="pci@0000:${GPU_ID}"
NAME=$(echo "$GPU_INFO" | grep "$GPU_ID" | tr -s " " | cut -d " " -f 3-)
IOMMU_GROUP=$(echo "$IOMMU_GROUPS" | grep $GPU_ID | cut -d " " -f 3)
GPU_LIST="${GPU_LIST}\nYes|${NAME}|${IOMMU_GROUP}|${PCI_ADDRESS}"
done
IOMMU_COMPATIBILITY_LVL=0 # 0: no GPUs to pass through; 1: at least 1 GPU for pt, but no GPU for host left; 2: at least one GPU for pt and at least one GPU for host left
if [ "${#GOOD_GPUS[@]}" == "0" ] ; then
if [ "${#GPU_IDS[@]}" == "0" ] ; then
log_red "[Warning] Failed to find any GPUs! Assuning this is correct, GPU pass-through is obviously impossible on this system in the current configuration!"
else
log_red "[Warning] This script was not able to identify a GPU in this that could be passed through to a VM!"
fi
else
log_green "[Success] There are ${#GOOD_GPUS[@]} GPU(s) in this system that could be passed through to a VM!"
log_white ""
GPU_LIST=$(echo -e "$GPU_LIST" | column -t -s'|')
while read -r line; do
if echo "$line" | grep --quiet Yes ; then
log_green "$line"
elif echo "$line" | grep --quiet No ; then
log_red "$line"
else
log_orange "$line"
fi
done <<< "$GPU_LIST"
log_white ""
if [ ${#GOOD_GPUS[@]} != 1 ] && grep -qE '^([0-9]+)( \1)*$' <<< $(echo $(echo "$IOMMU_GROUPS" | grep -E $(echo "${GOOD_GPUS[@]}" | tr ' ' '|') | cut -d " " -f 3)) ; then
if [ ${#BAD_GPUS[@]} == 0 ] ; then
IOMMU_COMPATIBILITY_LVL=1
log_orange "[Warning] All GPUs in this system are in the same IOMMU group. This would make GPU pass-through difficult (not impossible) because your host machine would be left without a GPU!"
else
IOMMU_COMPATIBILITY_LVL=2
log_green "[Warning] Some of your GPUs are in the same IOMMU group. This means they could only be passed through together. You could still use a GPU that's in another group for your host system. (E.g. the one with the PCI adress 'pci@0000:'${BAD_GPUS[0]} "
fi
else
if [ "${#GPU_IDS[@]}" == "1" ] ; then
IOMMU_COMPATIBILITY_LVL=1
log_orange "[Warning] Only 1 GPU found! (Counting all GPUs, not just dedicated ones.) This would make GPU pass-thruogh difficult (not impossible) because your host machine would be left without a GPU!"
else
IOMMU_COMPATIBILITY_LVL=2
log_green "[OK] You have GPUs that are not in the same IOMMU group. At least one of these could be passed through to a VM and at least one of the remaining ones could be used for the host system."
fi
fi
fi
# If the device is a laptop
#if [ "$(sudo dmidecode --string chassis-type)" != "Desktop" ] ; then
DEVICE_NAME=$(sudo dmidecode -s system-product-name)
BIOS_VERSION=$(sudo dmidecode -s bios-version)
LOG_DIR="$DIR/logs/$DEVICE_NAME/$BIOS_VERSION"
DATE=`date +%Y-%m-%d`
mkdir -p "$LOG_DIR"
log_white "[Info] Device name: $DEVICE_NAME"
log_white "[Info] BIOS version: $BIOS_VERSION"
if echo $IOMMU_GROUPS | grep --quiet " VGA compatible controller " ; then
log_green "[OK] This system is probably MUXed. (The connection between the GPU(s) and the [internal display]/[display outputs] is multiplexed.)"
else
log_orange "[Warning] This system is probably MUX-less. (The connection between the GPU(s) and the [internal display]/[display outputs] is not multiplexed.)"
fi
echo $DATE > "$LOG_DIR/date.log"
echo "$IOMMU_GROUPS" > "$LOG_DIR/lsiommu.log"
sudo dmidecode > "$LOG_DIR/dmidecode.log"
sudo dmesg > "$LOG_DIR/dmesg.log"
sudo lshw > "$LOG_DIR/lshw.log"
sudo sudo lshw -short > "$LOG_DIR/lshw-short.log"
sudo lshw -class display -businfo > "$LOG_DIR/lshw-gpu-businfo.log"
sudo lspci > "$LOG_DIR/lspci.log"
sudo lsusb > "$LOG_DIR/lsusb.log"
sudo lsblk > "$LOG_DIR/lsblk.log"
sudo lscpu > "$LOG_DIR/lscpu.log"
sudo sudo dmidecode -t bios > "$LOG_DIR/bios.log"
sudo cat /proc/cpuinfo > "$LOG_DIR/cpuinfo.log"
sudo cat /proc/meminfo > "$LOG_DIR/meminfo.log"
log_green "[OK] Logs have been created in $LOG_DIR"
echo -e $LOG_OUTPUT > "$LOG_DIR/general.log"
#fi
if [ "$UEFI_VIRTUALIZATION_ENABLED" = true ] && [ "$UEFI_IOMMU_ENABLED" = true ] && [ "$KERNEL_IOMMU_ENABLED" = true ] && [ "$IOMMU_COMPATIBILITY_LVL" -gt "0" ] ; then
log_green "TODO: create a VM and pass a GPU through to it"
fi
#echo "Listing IOMMU Groups..."
#$DIR/lsiommu.sh
#echo "Listing GPU info with lshw..."
#sudo lshw -class display
#if [ -n ${MOCK_SET+x} ]; then
if [ "$MOCK_MODE" = true ]; then
log_red "[Warning] Remember, the above output has been generated using the given mock data and has nothing to do with this system!"
else
$SHELL # This is just to keep the shell running when the script is automatically executed on startup.
fi