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 $@