Linux kernel Virtio-net test research
-
./tools/testing/kunit/kunit.py run "virt*"- run all kunit tests that starts withvirt -
./tools/testing/kunit/kunit.py run --arch=x86_64- run on other architectures using qemu -
./tools/testing/kunit/kunit.py run --arch=s390 --cross_compile=s390x-linux-gnu- specify toolchain for compilation -
scripts/decode_stacktrace.sh .kunit/vmlinux .kunit < .kunit/test.log | tee .kunit/decoded.log | ./tools/testing/kunit/kunit.py parse- get more detailed, advantage is that stacktrace contains filenames of the functions -
qemu-system-x86_64 -kernel ./arch/x86_64/boot/bzImage -initrd ramdisk.img -m 4G- run kernel image in qemu -
mkinitramfs -o ramdiks.img- create ramfs -
unmkinitramfs <file> <target directory>- unwrap ramfs into a dircetory -
mount -t debugfs none /sys/kernel/debug- mount debugfs and get the coverage gdna gdno files -
lcov -t "virtio_test" -o coverage.info -c -d gcovFiles- get coverage from gcda & gcno files which lay in gcovFiles directory -
genhtml -o coverage.result coverage.info- generates coverage visualisation in directory coverage.results
-
To run kuint tests for
virtio_netadd configuration in filelinux/drivers/net/Kconfigconfig VIRTIO_NET_TEST tristate "Test for virtio_net" if !KUNIT_ALL_TESTS depends on KUNIT=y select NETDEVICES select NET_CORE select VIRTIO select VIRTIO_NET select NET default KUNIT_ALL_TESTS -
Selectwill add the dependencies and they will compile with ourVIRTIO_NET_TEST, also we add our file with test ot the configVIRTIO_NET_TESTinlinux/drivers/net/Makefileobj-$(CONFIG_VIRTIO_NET_TEST) += virtio_net.o -
Finally enable test configuration in
linux/.kunit/.configandlinux/.kunit/.config. Note that we should enable the configuration in both files because,kunit.pyscript parses both the existing.configand the.kunitconfigfiles to ensure that.configis a superset of.kunitconfigCONFIG_VIRTIO_NET_TEST=y -
Configs for kernel address sanitizer
CONFIG_KASAN=y CONFIG_KASAN_VMALLOC=y CONFIG_KASAN_INLINE=y CONFIG_KASAN_GENERIC=y CONFIG_STACKTRACE=y -
Configs for gdb debugger
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_KERNEL=y -
Confgis for gcov to get coverage data for kernel
CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y -
Configs for virtio-fs
CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y
-
Run test isolated using arg
--run_isolated "test" -
./tools/testing/kunit/kunit.py run --arch=x86_64 --run_isolated "test"
-
In order to get coverage .gcno .gcda files, we need to compile and run the kernel.
-
We can do it manually installing compiled kernel into our OS, or run a VM with compiled kernel using qemu.
-
We want virtio_net.c to be profiled with
gcov, so we add these line inlinux/drivers/net/MakefileGCOV_PROFILE_virtio_net.o := y -
Also to run with gcov we should add appropriate configs to
.config.CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y -
Compile the kernel and run in VM
-
In guest VM terminal run next command to get the appropiate files
mount -t debugfs none /sys/kernel/debug
-
After that you can find .gcda file in /sys/kernel/debug/gcov
-
The .gcno file must be available after compiling the kernel
-
Compile the kernel with required configs on
CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y -
After compilation finishes we can find bzImage with path
arch/x86/boot/bzImagewhich is a binary file -
Create ramfs
ramdisk.imgfile with commandmkinitramfs -o ramdiks.imgand keep it in one directory withbzImage -
Download, install and open Virtual Machine Manager
-
Click
Create new instanceand choose manual installaion -
As operating system choose Generic linux 2020
-
Memory 4096, and cpu 2 (recommended parameters)
-
Disable storage for this virtual machine
-
Name VM and enable option
Customize configuration before isntall -
In
Memorysection enable Shared Memory option -
In
Boot optionssection open kernel manual boot and clickBrowsefor Kernel Path -
In opened menu click
Add pooland choose the directory wherebzImageandramdisk.imgalready lay -
Then from your new pool choose file
bzImage, and click choose Volume -
Click
Browsefor initrd path, and chooseramdisk.imgfrom the same pool, clickapply -
Click
add Hardwarein the left bottom corner, choose sectionfilesystem, choosevirtiofs, choose path to the future shared directory, and also give it a name intarget pathfield -
Click start installation, after which you should see terminal of the VM
-
mount -t virtiofs <name> <path where you want to mount shared directory>- run this command to mount virtiofs shared folder -
Now we can transfer files from
host machinetoVMand vice versa
-
make menuconfig- creates .config file in linux directory -
Add next configs in order to compile with kunit test, gcov and virtiofs
CONFIG_KUNIT=y CONFIG_KUNIT_ALL_TESTS=y CONFIG_KUNIT_DEBUGFS=y CONFIG_KUNIT_TEST=y CONFIG_KUNIT_DEFAULT_ENABLED=y CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y CONFIG_GCOV_PROFILE_FTRACE=y -
If you have error like this on ubuntu
CC certs/system_keyring.o make[2]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop. make[1]: *** [scripts/Makefile.build:504: certs] Error 2 make: *** [Makefile:2021: .] Error 2
- Then this commands can help
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
- After running both commands above, run
makeand tabenterfor both new options
Classes
Classes are not a construct that is built into the C programming language; however, it is an easily derived concept. Accordingly, in most cases, every project that does not use a standardized object oriented library (like GNOME’s GObject) has their own slightly different way of doing object oriented programming; the Linux kernel is no exception.
The central concept in kernel object oriented programming is the class. In the kernel, a class is a struct that contains function pointers. This creates a contract between implementers and users since it forces them to use the same function signature without having to call the function directly. To be a class, the function pointers must specify that a pointer to the class, known as a class handle, be one of the parameters. Thus the member functions (also known as methods) have access to member variables (also known as fields) allowing the same implementation to have multiple instances.
A class can be overridden by child classes by embedding the parent class in the child class. Then when the child class method is called, the child implementation knows that the pointer passed to it is of a parent contained within the child. Thus, the child can compute the pointer to itself because the pointer to the parent is always a fixed offset from the pointer to the child. This offset is the offset of the parent contained in the child struct.
Introduction to virtio-networking and vhost-net
Booting custom linux kernel in qemu
List of maintainers and how to submit kernel changes
Kcov code coverage for fuzzing
Securely booting confidential VMs with encrypting disk
linux kernel testing and debugging
virtio net failover introduction
deep into vhost, virtio-networking
-
cd ~ -
mkdir workspace -
cd workspace -
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.3.tar.xz -
tar xvf linux-5.10.3.tar.xz -
wget https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/11.3.0/x86_64-gcc-11.3.0-nolibc-x86_64-linux.tar.xz -
tar xvf x86_64-gcc-11.3.0-nolibc-x86_64-linux.tar.xz -
cd linux-5.10.3 -
./tools/testing/kunit/kunit.py run -
cd drivers/net -
touch virtio_net_test.c virtio_net_test.h -
cd ../..