@@ -25,20 +25,33 @@ HYPERVISOR=
25
25
MACHINE_TYPE=
26
26
IMAGE_TYPE=
27
27
28
+ # Option to choose an alternative PCI device for the VFIO test
29
+ VFIO_PCI_CLASS=${VFIO_PCI_CLASS:- " Ethernet controller" }
30
+ VFIO_PCI_NAME=${VFIO_PCI_NAME:- " Virtio.*network device" }
31
+ VFIO_CHECK_GUEST_KERNEL=${VFIO_CHECK_GUEST_KERNEL:- " ip a | grep \" eth\" || die \" Missing VFIO network interface\" " }
32
+ VFIO_PORT=${VFIO_PORT:- " bridge-port" }
33
+ VFIO_CHECK_NUM_DEVICES=${VFIO_CHECK_NUM_DEVICES:- " 2" }
34
+
28
35
cleanup () {
29
36
clean_env_ctr
30
37
sudo rm -rf " ${tmp_data_dir} "
31
-
32
- [ -n " ${host_pci} " ] && sudo driverctl unset-override " ${host_pci} "
38
+ # some devices fail if no previous driver being bound
39
+ [ -n " ${host_pci} " ] && sudo driverctl --noprobe unset-override " ${host_pci} "
33
40
}
34
41
35
42
host_pci_addr () {
36
- lspci -D | grep " Ethernet controller " | grep " Virtio.*network device " | tail -1 | cut -d' ' -f1
43
+ lspci -D | grep " ${VFIO_PCI_CLASS} " | grep " ${VFIO_PCI_NAME} " | tail -1 | cut -d' ' -f1
37
44
}
38
45
39
46
get_vfio_path () {
40
47
local addr=" $1 "
41
- echo " /dev/vfio/$( basename $( realpath /sys/bus/pci/drivers/vfio-pci/${host_pci} /iommu_group) ) "
48
+ local iommu_group_path
49
+ local iommu_group
50
+
51
+ iommu_group_path=$( realpath /sys/bus/pci/drivers/vfio-pci/" ${addr} " /iommu_group)
52
+ iommu_group=$( basename " ${iommu_group_path} " )
53
+
54
+ echo " /dev/vfio/${iommu_group} "
42
55
}
43
56
44
57
pull_rootfs () {
@@ -55,12 +68,19 @@ create_bundle() {
55
68
mkdir -p " ${bundle_dir} "
56
69
57
70
# extract busybox rootfs
58
- local rootfs_dir=" ${bundle_dir} /rootfs"
71
+ local rootfs_dir
72
+ local layers_dir
73
+
74
+ rootfs_dir=" ${bundle_dir} /rootfs"
59
75
mkdir -p " ${rootfs_dir} "
60
- local layers_dir=" $( mktemp -d) "
76
+
77
+ layers_dir=" $( mktemp -d) "
61
78
tar -C " ${layers_dir} " -pxf " ${rootfs_tar} "
79
+
62
80
for (( i= 0 ;i< $(cat ${layers_dir} / manifest.json | jq - r ".[].Layers | length");i++ )) ; do
63
- tar -C ${rootfs_dir} -xf ${layers_dir} /$( cat ${layers_dir} /manifest.json | jq -r " .[].Layers[${i} ]" )
81
+ local layer
82
+ layer=$( cat ${layers_dir} /manifest.json | jq -r " .[].Layers[${i} ]" )
83
+ tar -C " ${rootfs_dir} " -xf " ${layers_dir} /${layer} "
64
84
done
65
85
sync
66
86
@@ -87,7 +107,7 @@ check_guest_kernel() {
87
107
# For vfio_mode=guest-kernel, the device should be bound to
88
108
# the guest kernel's native driver. To check this has worked,
89
109
# we look for an ethernet device named 'eth*'
90
- get_ctr_cmd_output " ${container_id} " ip a | grep " eth " || die " Missing VFIO network interface "
110
+ get_ctr_cmd_output " ${container_id} " ash -c " ${VFIO_CHECK_GUEST_KERNEL} "
91
111
}
92
112
93
113
check_vfio () {
@@ -113,8 +133,8 @@ check_vfio() {
113
133
# There should be two devices in the IOMMU group: the ethernet
114
134
# device we care about, plus the PCIe to PCI bridge device
115
135
devs=" $( get_ctr_cmd_output " ${cid} " ls /sys/kernel/iommu_groups/" ${group} " /devices) "
116
- if [ $( echo " ${devs} " | wc -w) != " 2 " ] ; then
117
- die " Expected exactly two devices got: ${devs} "
136
+ if [ $( echo " ${devs} " | wc -w) != ${VFIO_CHECK_NUM_DEVICES} ] ; then
137
+ die " Expected exactly ${VFIO_CHECK_NUM_DEVICES} device(s) got: ${devs} "
118
138
fi
119
139
120
140
# The bridge device will always sort first, because it is on
155
175
}
156
176
157
177
setup_configuration_file () {
178
+ local hot_or_cold_plug_vfio=${$1 :- " hot_plug_vfio" }
179
+ local vfio_port=${$2 :- " bridge-port" }
158
180
local qemu_config_file=" configuration-qemu.toml"
159
181
local clh_config_file=" configuration-clh.toml"
160
182
local image_file=" /opt/kata/share/kata-containers/kata-containers.img"
@@ -188,13 +210,28 @@ setup_configuration_file() {
188
210
if [ -n " $MACHINE_TYPE " ]; then
189
211
if [ " $HYPERVISOR " = " qemu" ]; then
190
212
sed -i ' s|^machine_type.*|machine_type = "' ${MACHINE_TYPE} ' "|g' " ${kata_config_file} "
191
- # Make sure we have set hot_plug_vfio to a reasonable value
192
- 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} "
193
213
else
194
214
warn " Variable machine_type only applies to qemu. It will be ignored"
195
215
fi
196
216
fi
197
217
218
+ # Make sure the configuration file has the values available
219
+ # otherwise sed will fail to update it. sed will not throw an error.
220
+ grep -q -e ' ^#*.*hot_plug_vfio' " ${kata_config_file} " || echo ' hot_plug_vfio="bridge-port"' >> " ${kata_config_file} "
221
+ grep -q -e ' ^#*.*cold_plug_vfio' " ${kata_config_file} " || echo ' cold_plug_vfio="bridge-port"' >> " ${kata_config_file} "
222
+
223
+
224
+ if [ $hot_or_cold_plug_vfio == " hot_plug_vfio" ]; then
225
+ sed -i -e " s|^#*.*hot_plug_vfio =.*|hot_plug_vfio = \" ${VFIO_PORT} \" |" " ${kata_config_file} "
226
+ sed -i -e " s|^#*.*cold_plug_vfio =.*|cold_plug_vfio = \" no-port\" |" " ${kata_config_file} "
227
+ fi
228
+
229
+ if [ $hot_or_cold_plug_vfio == " cold_plug_vfio" ]; then
230
+ sed -i -e " s|^#*.*cold_plug_vfio =.*|cold_plug_vfio = \" ${VFIO_PORT} \" |" " ${kata_config_file} "
231
+ sed -i -e " s|^#*.*hot_plug_vfio =.*|hot_plug_vfio = \" no-port\" |" " ${kata_config_file} "
232
+ fi
233
+
234
+
198
235
if [ -n " ${SANDBOX_CGROUP_ONLY} " ]; then
199
236
sed -i ' s|^sandbox_cgroup_only.*|sandbox_cgroup_only=' ${SANDBOX_CGROUP_ONLY} ' |g' " ${kata_config_file} "
200
237
fi
@@ -228,6 +265,8 @@ setup_configuration_file() {
228
265
# enable VFIO relevant hypervisor annotations
229
266
sed -i -e ' s/^\(enable_annotations\).*=.*$/\1 = ["enable_iommu"]/' \
230
267
" ${kata_config_file} "
268
+
269
+ cat ${kata_config_file} | grep -v ' #' | grep -v ' ^$'
231
270
}
232
271
233
272
run_test_container () {
@@ -288,8 +327,6 @@ main() {
288
327
#
289
328
# Get the device ready on the host
290
329
#
291
- setup_configuration_file
292
-
293
330
restart_containerd_service
294
331
sudo modprobe vfio
295
332
sudo modprobe vfio-pci
@@ -307,7 +344,11 @@ main() {
307
344
vfio_major=" $( printf ' %d' $( stat -c ' 0x%t' ${vfio_device} ) ) "
308
345
vfio_minor=" $( printf ' %d' $( stat -c ' 0x%T' ${vfio_device} ) ) "
309
346
310
- [ -n " /dev/vfio/vfio" ] || die " vfio control device not found"
347
+ # check if /dev/vfio/vfio exists
348
+ local vfio_control_device
349
+ vfio_control_device=$( ls /dev/vfio/vfio)
350
+
351
+ [ -n " ${vfio_control_device} " ] || die " vfio control device not found"
311
352
vfio_ctl_major=" $( printf ' %d' $( stat -c ' 0x%t' /dev/vfio/vfio) ) "
312
353
vfio_ctl_minor=" $( printf ' %d' $( stat -c ' 0x%T' /dev/vfio/vfio) ) "
313
354
@@ -318,6 +359,36 @@ main() {
318
359
# Run the tests
319
360
#
320
361
362
+ # First test hot_plug_vfio="bridge-port"
363
+ # the default is VFIO_PORT="bridge-port" if not overriden
364
+ setup_configuration_file " hot_plug_vfio" " ${VFIO_PORT} "
365
+
366
+ # test for guest-kernel mode
367
+ guest_kernel_cid=" vfio-guest-kernel-${RANDOM} "
368
+ run_test_container " ${guest_kernel_cid} " \
369
+ " ${tmp_data_dir} /vfio-guest-kernel" \
370
+ " ${script_path} /guest-kernel.json.in" \
371
+ " ${host_pci} "
372
+ check_guest_kernel " ${guest_kernel_cid} "
373
+
374
+ # Remove the container so we can re-use the device for the next test
375
+ clean_env_ctr
376
+
377
+ # test for vfio mode
378
+ vfio_cid=" vfio-vfio-${RANDOM} "
379
+ run_test_container " ${vfio_cid} " \
380
+ " ${tmp_data_dir} /vfio-vfio" \
381
+ " ${script_path} /vfio.json.in" \
382
+ " ${host_pci} "
383
+ check_vfio " ${vfio_cid} "
384
+
385
+ # Remove the container so we can re-use the device for the next test
386
+ clean_env_ctr
387
+
388
+ # Mpw test cold_plug_vfio="bridge-port"
389
+ # the default is VFIO_PORT="bridge-port" if not overriden
390
+ setup_configuration_file " cold_plug_vfio" " ${VFIO_PORT} "
391
+
321
392
# test for guest-kernel mode
322
393
guest_kernel_cid=" vfio-guest-kernel-${RANDOM} "
323
394
run_test_container " ${guest_kernel_cid} " \
@@ -338,4 +409,4 @@ main() {
338
409
check_vfio " ${vfio_cid} "
339
410
}
340
411
341
- main $@
412
+ main " $@ "
0 commit comments