github.com/kata-containers/tests@v0.0.0-20240307153542-772105b56064/functional/vfio-ap/run.sh (about) 1 #!/bin/bash 2 # 3 # Copyright (c) 2023 IBM Corp. 4 # 5 # SPDX-License-Identifier: Apache-2.0 6 # 7 8 [ -n "$DEBUG" ] && set -x 9 set -o nounset 10 set -o pipefail 11 set -o errtrace 12 13 script_path=$(dirname "$0") 14 source "${script_path}/../../lib/common.bash" 15 16 registry_port="${REGISTRY_PORT:-5000}" 17 registry_name="kata-registry" 18 container_engine="${container_engine:-docker}" 19 dev_base="/dev/vfio" 20 sys_bus_base="/sys/bus/ap" 21 sys_device_base="/sys/devices/vfio_ap/matrix" 22 command_file="mdev_supported_types/vfio_ap-passthrough/create" 23 test_image_name="localhost:${registry_port}/vfio-ap-test:latest" 24 25 test_category="[kata][vfio-ap][containerd]" 26 27 trap cleanup EXIT 28 29 # Check if the given function exists. 30 function_exists() { 31 [[ "$(type -t $1)" == "function" ]] 32 } 33 34 if ! function_exists get_test_version; then 35 source "${script_path}/../../.ci/lib.sh" 36 fi 37 38 # Prevent the program from exiting on error 39 trap - ERR 40 image_version=$(get_test_version "docker_images.registry_ibm.version") 41 registry_image=$(get_test_version "docker_images.registry_ibm.registry_url"):"${image_version}" 42 43 setup_config_file() { 44 local target_item=$1 45 local action=$2 46 local replacement=${3:-} 47 local kata_config_file=$(kata-runtime env --json | jq -r '.Runtime.Config.Path') 48 49 if [ "${action}" == "comment_out" ]; then 50 sudo sed -i -e 's/.*\('${target_item}'.*\)/#\1/g' ${kata_config_file} 51 else 52 sudo sed -i -e 's/.*\('${target_item}'\s*=\).*/\1 "'${replacement}'"/g' ${kata_config_file} 53 fi 54 } 55 56 show_config_file() { 57 local kata_config_file=$(kata-runtime env --json | jq -r '.Runtime.Config.Path') 58 echo "Show kata configuration" 59 # Print out the configuration by excluding comments and empty lines 60 cat "${kata_config_file}" | grep -v '^\s*$\|^\s*\#' 61 } 62 63 setup_hotplug() { 64 echo "Set up the configuration file for Hotplug" 65 setup_config_file "vfio_mode" "replace" "vfio" 66 setup_config_file "cold_plug_vfio" "comment_out" 67 setup_config_file "hot_plug_vfio" "replace" "bridge-port" 68 show_config_file 69 } 70 71 setup_coldplug() { 72 echo "Set up the configuration file for Coldplug" 73 setup_config_file "vfio_mode" "replace" "guest-kernel" 74 setup_config_file "hot_plug_vfio" "comment_out" 75 setup_config_file "cold_plug_vfio" "replace" "bridge-port" 76 show_config_file 77 } 78 79 cleanup() { 80 # Clean up container images 81 sudo ctr image rm $(sudo ctr image list -q) || : 82 ${container_engine} rmi -f ${test_image_name} > /dev/null 2>&1 83 84 # Destroy mediated devices 85 IFS=$'\n' read -r -d '' -a arr_dev < <( ls -1 /sys/bus/mdev/devices && printf '\0' ) 86 for item in ${arr_dev[@]}; do 87 if [[ ${item//-/} =~ ^[[:xdigit:]]{32}$ ]]; then 88 echo 1 | sudo tee /sys/bus/mdev/devices/${item}/remove > /dev/null 89 fi 90 done 91 92 # Release devices from vfio-ap 93 echo 0x$(printf -- 'f%.0s' {1..64}) | sudo tee /sys/bus/ap/apmask > /dev/null 94 echo 0x$(printf -- 'f%.0s' {1..64}) | sudo tee /sys/bus/ap/aqmask > /dev/null 95 } 96 97 validate_env() { 98 necessary_commands=( "${container_engine}" "ctr" "lszcrypt" ) 99 for cmd in ${necessary_commands[@]}; do 100 if ! which ${cmd} > /dev/null 2>&1; then 101 echo "${cmd} not found" >&2 102 exit 1 103 fi 104 done 105 106 if ! ${container_engine} ps | grep -q "${registry_name}"; then 107 echo "Docker registry not found. Installing..." 108 ${container_engine} run -d -p ${registry_port}:5000 --restart=always --name "${registry_name}" "${registry_image}" 109 # wait for registry container 110 waitForProcess 15 3 "curl http://localhost:${registry_port}" 111 fi 112 113 sudo modprobe vfio 114 sudo modprobe vfio_ap 115 } 116 117 build_test_image() { 118 ${container_engine} rmi -f ${test_image_name} > /dev/null 2>&1 119 ${container_engine} build -t ${test_image_name} ${script_path} 120 ${container_engine} push ${test_image_name} 121 } 122 123 create_mediated_device() { 124 # a device lastly listed is chosen 125 APQN=$(lszcrypt | tail -1 | awk '{ print $1}') 126 if [[ ! $APQN =~ [[:xdigit:]]{2}.[[:xdigit:]]{4} ]]; then 127 echo "Incorrect format for APQN" >&2 128 exit 1 129 fi 130 _APID=${APQN//.*} 131 _APQI=${APQN#*.} 132 APID=$(echo ${_APID} | sed 's/^0*//') 133 APQI=$(echo ${_APQI} | sed 's/^0*//') 134 135 # Release the device from the host 136 pushd ${sys_bus_base} 137 echo -0x${APID} | sudo tee apmask 138 echo -0x${APQI} | sudo tee aqmask 139 popd 140 lszcrypt --verbose 141 142 # Create a mediated device (mdev) for the released device 143 echo "Status before creation of mediated device" 144 ls ${dev_base} 145 146 pushd ${sys_device_base} 147 if [ ! -f ${command_file} ]; then 148 echo "${command_file} not found}" >&2 149 exit 1 150 fi 151 152 mdev_uuid=$(uuidgen) 153 echo "${mdev_uuid}" | sudo tee ${command_file} 154 155 echo "Status after creation of mediated device" 156 ls ${dev_base} 157 158 [ -n "${mdev_uuid}" ] && cd ${mdev_uuid} 159 if [ ! -L iommu_group ]; then 160 echo "${mdev_uuid}/iommu_group not found" >&2 161 exit 1 162 fi 163 dev_index=$(readlink iommu_group | xargs -i{} basename {}) 164 if [ ! -n "${dev_index}" ]; then 165 echo "No dev_index from 'readlink ${sys_device_base}/${mdev_uuid}/iommu_group'" >&2 166 exit 1 167 fi 168 cat matrix 169 echo 0x${APID} | sudo tee assign_adapter 170 echo 0x${APQI} | sudo tee assign_domain 171 cat matrix 172 popd 173 } 174 175 run_test() { 176 local run_index=$1 177 local test_message=$2 178 local start_time=$(date +"%Y-%m-%d %H:%M:%S") 179 # Set time granularity to a second for capturing the log 180 sleep 1 181 # Check if the APQN is identified in a container 182 sudo ctr image pull --plain-http ${test_image_name} 183 184 [ -n "${dev_index}" ] && \ 185 sudo ctr run --runtime io.containerd.run.kata.v2 --rm \ 186 --device ${dev_base}/${dev_index} ${test_image_name} test \ 187 bash -c "lszcrypt ${_APID}.${_APQI} | grep ${APQN}" 188 if [ $? -eq 0 ]; then 189 echo "ok ${run_index} ${test_category} ${test_message}" 190 else 191 echo "not ok ${run_index} ${test_category} ${test_message}" 192 echo "Logging the journal..." 193 sudo journalctl --no-pager --since "${start_time}" 194 fi 195 } 196 197 run_tests() { 198 setup_hotplug 199 run_test "1" "Test can assign a CEX device inside the guest via VFIO-AP Hotplug" 200 201 setup_coldplug 202 run_test "2" "Test can assign a CEX device inside the guest via VFIO-AP Coldplug" 203 } 204 205 main() { 206 validate_env 207 cleanup 208 build_test_image 209 create_mediated_device 210 run_tests 211 } 212 213 main $@