blob: 02a3139b66480c9b86d48998e08969cb7a6746a0 (
plain)
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
|
#!/usr/bin/env bash
# Enable WC in VFIO-PCI driver
# Tested on:
# * Amazon Linux 2 AMI (HVM), SSD Volume Type - ami-0bb3fad3c0286ebd5
# * Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type - ami-015232c01a82b847b
# * Red Hat Enterprise Linux 8 (HVM), SSD Volume Type - ami-08f4717d06813bf00
# * Ubuntu Server 20.04 LTS (HVM), SSD Volume Type - ami-06fd8a495a537da8b
# * Ubuntu Server 18.04 LTS (HVM), SSD Volume Type - ami-0823c236601fef765
set -e
TMP_DIR="tmp"
# Kernel modules location:
P1="/usr/lib/modules/`uname -r`/kernel/drivers/vfio"
P2="/lib/modules/`uname -r`/kernel/drivers/vfio"
# This may return an error if executed from inside the script
set +e
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
set -e
function bold {
echo -e "${BOLD}${@}${NORMAL}"
}
function err {
bold "${RED}ERROR: ${@}"
}
function green {
bold "${GREEN}${@}"
}
function get_kernel_version {
local ver=$(uname -r | cut -f 1 -d '-')
local ver_major=$(echo $ver | cut -f1 -d '.')
local ver_minor=$(echo $ver | cut -f2 -d '.')
local ver_subminor=$(echo $ver | cut -f3 -d '.')
printf "%d%02d%04d" "${ver_major}" "${ver_minor}" "${ver_subminor}"
}
function download_kernel_src_yum {
echo "Use yum to get the kernel sources"
bold "\nInstall required applications and kernel headers"
yum install -y gcc "kernel-$(uname -r)" "kernel-devel-$(uname -r)" \
git make elfutils-libelf-devel patch yum-utils
green Done
# Download kernel source
bold "\nDownload kernel source with vfio"
yumdownloader --source "kernel-devel-$(uname -r)"
rpm2cpio kernel*.src.rpm | cpio -idmv
green Done
rm -f *patches.tar
tar xf linux-*.tar*
rm -f linux-*.tar* linux-*.patch
}
function download_kernel_src_apt {
echo "Use apt-get to get the kernel sources"
apt-get -q -y update
green Done
bold "\nInstall required applications"
apt-get -q -y install dpkg-dev build-essential git
green Done
bold "\nDownload Linux kernel source with vfio"
if ! apt-get -q -y source -t focal linux-image-$(uname -r); then
err "Cannot download Linux kernel source.\nPlease uncomment appropriate 'deb-src' line in the /etc/apt/sources.list file"
exit 1
fi
green Done
rm -f linux-*.dsc linux-*.gz
}
function download_kernel_src {
bold "[1] Downloading prerequisites..."
rm -rf "${TMP_DIR}"
mkdir -p "${TMP_DIR}"
cd "${TMP_DIR}"
if apt-get -v >/dev/null 2>/dev/null; then
download_kernel_src_apt
else
download_kernel_src_yum
fi
cd linux-*
}
function apply_wc_patch {
echo "Using patch for kernel version 4.10"
local wc_patch="${BASE_PATH}/patches/linux-4.10-vfio-wc.patch"
if ! patch --ignore-whitespace -p1 < "${wc_patch}"; then
err "Cannot apply patch: ${wc_patch}!"
exit 1
fi
}
function compile_vfio_driver {
bold "\n[2] Patch and build the vfio driver"
# Adjust VFIO-PCI driver
bold "Apply patch for the write combining to the vfio-pci"
apply_wc_patch
green Done
cd drivers/vfio
# Configure Makefile - build VFIO with support for NOIOMMU mode
bold "\nConfigure Makefile for standalone vfio build and noiommu mode support"
echo "ccflags-y := -DCONFIG_VFIO_NOIOMMU=1" >> Makefile
echo 'all:' >> Makefile
echo ' make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules' >> Makefile
green Done
bold "\nBuild the driver"
if ! make; then
err "Compilation error."
exit 1
fi
green Done
}
function get_module_location {
for p in ${P1} ${P2}; do
if find "${p}" -name "vfio.*" >/dev/null 2>/dev/null; then
MOD_PATH="${p}"
break
fi
done
if [ -z "${MOD_PATH}" ]; then
err "Cannot find kernel modules location..."
exit
fi
}
function get_module_compression {
if ls "${MOD_PATH}/vfio.ko.xz" >/dev/null 2>/dev/null; then
XZ=".xz"
else
XZ=""
fi
}
function replace_module {
local installed=0
bold "\n[3] Install module"
get_module_location
get_module_compression
for name in "pci/vfio-pci.ko" "pci/vfio-pci-core.ko" "vfio.ko"; do
if test -e "${MOD_PATH}/${name}${XZ}"; then
if [ -n "${XZ}" ]; then
xz "${name}" -c > "${name}${XZ}"
fi
mv "${MOD_PATH}/${name}${XZ}" "${MOD_PATH}/${name}${XZ}_no_wc"
cp "${name}${XZ}" "${MOD_PATH}/${name}${XZ}"
bold "Installing: ${MOD_PATH}/${name}${XZ}"
installed=1
fi
done
if [ "${installed}" -eq 1 ]; then
green "Module installed at: ${MOD_PATH}"
else
err "Failure during vfio-pci module installation. Prehaps it's not provided as a kernel module!"
exit 1
fi
}
###############################################
# Main script code
###############################################
if [ "$(id -u)" -ne 0 ]; then
err 'Please execute script as a root'
exit 1
fi
cd $(dirname ${0})
BASE_PATH=$(pwd)
KERNEL_VERSION=$(get_kernel_version)
if [ "${KERNEL_VERSION}" -lt 4100000 ]; then
err "Kernel version: $(uname -r) is not supported by the script. Please upgrade kernel to at least v4.10."
exit 1
fi
download_kernel_src
compile_vfio_driver
replace_module
|