From 97540f012b0b18bf12d27ff314b2faad875fda22 Mon Sep 17 00:00:00 2001 From: Zvonko Kaiser Date: Fri, 21 Jul 2023 08:45:18 +0000 Subject: [PATCH] vfio: Fix default port assignment Fix default port assignment with an explicit value in the TOML It was implicit before and now the runtime will bail out if we did not set it explicitly. Update the configuration and set it. This will make the intent more clear. Fixes: #5726 Signed-off-by: Zvonko Kaiser --- functional/vfio/run.sh | 107 +++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 15 deletions(-) diff --git a/functional/vfio/run.sh b/functional/vfio/run.sh index ed4111e6c..80feb2a5f 100755 --- a/functional/vfio/run.sh +++ b/functional/vfio/run.sh @@ -25,20 +25,34 @@ HYPERVISOR= MACHINE_TYPE= IMAGE_TYPE= +# Option to choose an alternative PCI device for the VFIO test +VFIO_PCI_CLASS=${VFIO_PCI_CLASS:-"Ethernet controller"} +VFIO_PCI_NAME=${VFIO_PCI_NAME:-"Virtio.*network device"} +VFIO_CHECK_GUEST_KERNEL=${VFIO_CHECK_GUEST_KERNEL:-"ip a | grep \"eth\" || die \"Missing VFIO network interface\""} +VFIO_HOTPLUG=${VFIO_HOTPLUG:-"bridge-port"} +VFIO_COLDPLUG=${VFIO_COLDPLUG:-"no-port"} +VFIO_CHECK_NUM_DEVICES=${VFIO_CHECK_NUM_DEVICES:-"2"} + cleanup() { clean_env_ctr sudo rm -rf "${tmp_data_dir}" - - [ -n "${host_pci}" ] && sudo driverctl unset-override "${host_pci}" + # some devices fail if no previous driver being bound + [ -n "${host_pci}" ] && sudo driverctl --noprobe unset-override "${host_pci}" } host_pci_addr() { - lspci -D | grep "Ethernet controller" | grep "Virtio.*network device" | tail -1 | cut -d' ' -f1 + lspci -D | grep "${VFIO_PCI_CLASS}" | grep "${VFIO_PCI_NAME}" | tail -1 | cut -d' ' -f1 } get_vfio_path() { local addr="$1" - echo "/dev/vfio/$(basename $(realpath /sys/bus/pci/drivers/vfio-pci/${host_pci}/iommu_group))" + local iommu_group_path + local iommu_group + + iommu_group_path=$(realpath /sys/bus/pci/drivers/vfio-pci/"${addr}"/iommu_group) + iommu_group=$(basename "${iommu_group_path}") + + echo "/dev/vfio/${iommu_group}" } pull_rootfs() { @@ -55,12 +69,19 @@ create_bundle() { mkdir -p "${bundle_dir}" # extract busybox rootfs - local rootfs_dir="${bundle_dir}/rootfs" + local rootfs_dir + local layers_dir + + rootfs_dir="${bundle_dir}/rootfs" mkdir -p "${rootfs_dir}" - local layers_dir="$(mktemp -d)" + + layers_dir="$(mktemp -d)" tar -C "${layers_dir}" -pxf "${rootfs_tar}" + for ((i=0;i<$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers | length");i++)); do - tar -C ${rootfs_dir} -xf ${layers_dir}/$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers[${i}]") + local layer + layer=$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers[${i}]") + tar -C "${rootfs_dir}" -xf "${layers_dir}/${layer}" done sync @@ -87,7 +108,7 @@ check_guest_kernel() { # For vfio_mode=guest-kernel, the device should be bound to # the guest kernel's native driver. To check this has worked, # we look for an ethernet device named 'eth*' - get_ctr_cmd_output "${container_id}" ip a | grep "eth" || die "Missing VFIO network interface" + get_ctr_cmd_output "${container_id}" ash -c "${VFIO_CHECK_GUEST_KERNEL}" } check_vfio() { @@ -113,8 +134,8 @@ check_vfio() { # There should be two devices in the IOMMU group: the ethernet # device we care about, plus the PCIe to PCI bridge device devs="$(get_ctr_cmd_output "${cid}" ls /sys/kernel/iommu_groups/"${group}"/devices)" - if [ $(echo "${devs}" | wc -w) != "2" ] ; then - die "Expected exactly two devices got: ${devs}" + if [ $(echo "${devs}" | wc -w) != ${VFIO_CHECK_NUM_DEVICES} ] ; then + die "Expected exactly ${VFIO_CHECK_NUM_DEVICES} device(s) got: ${devs}" fi # The bridge device will always sort first, because it is on @@ -189,12 +210,21 @@ setup_configuration_file() { if [ "$HYPERVISOR" = "qemu" ]; then sed -i 's|^machine_type.*|machine_type = "'${MACHINE_TYPE}'"|g' "${kata_config_file}" # Make sure we have set hot_plug_vfio to a reasonable value - sudo sed -i -e 's|^#hot_plug_vfio =.*$|hot_plug_vfio = "bridge-port"|' -e 's|^hot_plug_vfio = .*$|hot_plug_vfio = "bridge-port"|' "${kata_config_file}" + sed -i -e 's|^#hot_plug_vfio =.*$|hot_plug_vfio = "bridge-port"|' -e 's|^hot_plug_vfio =.*$|hot_plug_vfio = "bridge-port"|' "${kata_config_file}" else warn "Variable machine_type only applies to qemu. It will be ignored" fi fi + if [ "${VFIO_HOTPLUG}" != "bridge-port" ]; then + sed -i -e "s|^#?hot_plug_vfio =.*$|hot_plug_vfio = \"${VFIO_HOTPLUG}\"|" -e "s|^hot_plug_vfio =.*$|hot_plug_vfio = \"${VFIO_HOTPLUG}\"|" "${kata_config_file}" + fi + + if [ "${VFIO_COLDPLUG}" != "bridge-port" ]; then + sed -i -e "s|^#?cold_plug_vfio =.*$|cold_plug_vfio = \"${VFIO_COLDPLUG}\"|" -e "s|^cold_plug_vfio =.*$|cold_plug_vfio = \"${VFIO_COLDPLUG}\"|" "${kata_config_file}" + fi + + if [ -n "${SANDBOX_CGROUP_ONLY}" ]; then sed -i 's|^sandbox_cgroup_only.*|sandbox_cgroup_only='${SANDBOX_CGROUP_ONLY}'|g' "${kata_config_file}" fi @@ -228,6 +258,8 @@ setup_configuration_file() { # enable VFIO relevant hypervisor annotations sed -i -e 's/^\(enable_annotations\).*=.*$/\1 = ["enable_iommu"]/' \ "${kata_config_file}" + + cat ${kata_config_file} | grep -v '#' | grep -v '^$' } run_test_container() { @@ -285,11 +317,17 @@ main() { done shift $((OPTIND-1)) + # We cannot hot and cold-plug a device, bail out if both are set to the + # same value but not "no-port" + if [ "$VFIO_HOTPLUG" == "$VFIO_COLDPLUG" ]; then + if [ "$VFIO_HOTPLUG" == "no-port" ]; then + die "VFIO_HOTPLUG and VFIO_COLDPLUG cannot both be set to no-port" + fi + die "VFIO_HOTPLUG and VFIO_COLDPLUG cannot be the same" + fi # # Get the device ready on the host # - setup_configuration_file - restart_containerd_service sudo modprobe vfio sudo modprobe vfio-pci @@ -307,7 +345,11 @@ main() { vfio_major="$(printf '%d' $(stat -c '0x%t' ${vfio_device}))" vfio_minor="$(printf '%d' $(stat -c '0x%T' ${vfio_device}))" - [ -n "/dev/vfio/vfio" ] || die "vfio control device not found" + # check if /dev/vfio/vfio exists + local vfio_control_device + vfio_control_device=$(ls /dev/vfio/vfio) + + [ -n "${vfio_control_device}" ] || die "vfio control device not found" vfio_ctl_major="$(printf '%d' $(stat -c '0x%t' /dev/vfio/vfio))" vfio_ctl_minor="$(printf '%d' $(stat -c '0x%T' /dev/vfio/vfio))" @@ -318,6 +360,41 @@ main() { # Run the tests # + # First test hot_plug_vfio="bridge-port" + # the default is VFIO_HOTPLUG="bridge-port" if not overriden + setup_configuration_file + + # test for guest-kernel mode + guest_kernel_cid="vfio-guest-kernel-${RANDOM}" + run_test_container "${guest_kernel_cid}" \ + "${tmp_data_dir}/vfio-guest-kernel" \ + "${script_path}/guest-kernel.json.in" \ + "${host_pci}" + check_guest_kernel "${guest_kernel_cid}" + + # Remove the container so we can re-use the device for the next test + clean_env_ctr + + # test for vfio mode + vfio_cid="vfio-vfio-${RANDOM}" + run_test_container "${vfio_cid}" \ + "${tmp_data_dir}/vfio-vfio" \ + "${script_path}/vfio.json.in" \ + "${host_pci}" + check_vfio "${vfio_cid}" + + # Remove the container so we can re-use the device for the next test + clean_env_ctr + + # Now test cold_plug_vfio="bridge-port" + # the default is no-port override it if "no-port" is still set + if [ "${VFIO_COLDPLUG}" == "no-port" ]; then + export VFIO_HOTPLUG="no-port" + export VFIO_COLDPLUG="bridge-port" + fi + + setup_configuration_file + # test for guest-kernel mode guest_kernel_cid="vfio-guest-kernel-${RANDOM}" run_test_container "${guest_kernel_cid}" \ @@ -338,4 +415,4 @@ main() { check_vfio "${vfio_cid}" } -main $@ +main "$@"