diff options
Diffstat (limited to 'fdio.infra.ansible/roles/aws/files/get-vfio-with-wc.sh')
-rw-r--r-- | fdio.infra.ansible/roles/aws/files/get-vfio-with-wc.sh | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/fdio.infra.ansible/roles/aws/files/get-vfio-with-wc.sh b/fdio.infra.ansible/roles/aws/files/get-vfio-with-wc.sh new file mode 100644 index 0000000000..02a3139b66 --- /dev/null +++ b/fdio.infra.ansible/roles/aws/files/get-vfio-with-wc.sh @@ -0,0 +1,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 |