From d0bc68182b705c842b7245c37aa56f485e22051b Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Thu, 7 May 2026 08:00:49 +0000 Subject: [PATCH 1/7] lkl: use ARCH_HAS_DMA_OPS instead of DMA_OPS DMA_OPS was renamed to ARCH_HAS_DMA_OPS in Linux 6.12. This breaks DMA and PCI support. We did not catch this issue because we were using an older qemu in CI which did not route NVME requests through the iommu. Signed-off-by: Octavian Purdila --- arch/lkl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/lkl/Kconfig b/arch/lkl/Kconfig index 637b4beddb3b28..9b296fdbc06d06 100644 --- a/arch/lkl/Kconfig +++ b/arch/lkl/Kconfig @@ -124,7 +124,7 @@ config PCI select NO_GENERIC_PCI_IOPORT_MAP select GENERIC_PCI_IOMAP select HAS_DMA - select DMA_OPS + select ARCH_HAS_DMA_OPS default y config RAID6_PQ_BENCHMARK From b2395f120a19e918c97b1650ad5ef2a611fc24a8 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Thu, 7 May 2026 08:10:37 +0000 Subject: [PATCH 2/7] lkl: simplify PCI VFIO test Instead of mounting a filesystem to test PCI VFIO just open the NVME block device and read it. Signed-off-by: Octavian Purdila --- tools/lkl/tests/disk-vfio-pci.c | 93 ++++++++++++++------------------ tools/lkl/tests/disk-vfio-pci.sh | 57 ++++++++------------ tools/lkl/tests/run.py | 5 +- 3 files changed, 61 insertions(+), 94 deletions(-) diff --git a/tools/lkl/tests/disk-vfio-pci.c b/tools/lkl/tests/disk-vfio-pci.c index b8659d5f0e68fc..41d6b2bc9695af 100644 --- a/tools/lkl/tests/disk-vfio-pci.c +++ b/tools/lkl/tests/disk-vfio-pci.c @@ -1,14 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 #include #include -#include -#include -#include #include #include #include #include #include +#include #include "test.h" #include "cla.h" @@ -20,81 +18,68 @@ static struct { } cla; struct cl_arg args[] = { - { "type", 't', "filesystem type", 1, CL_ARG_STR, &cla.fstype }, { "pciname", 'n', "PCI device name (as %x:%x:%x.%x format)", 1, CL_ARG_STR, &cla.pciname }, { 0 }, }; -static char mnt_point[32]; static char bootparams[128]; -static int lkl_test_umount_dev(void) -{ - long ret, ret2; - - ret = lkl_sys_chdir("/"); - - ret2 = lkl_umount_blkdev(LKL_MKDEV(259, 0), 0, 1000); - - lkl_test_logf("%ld %ld", ret, ret2); - - if (!ret && !ret2) - return TEST_SUCCESS; - - return TEST_FAILURE; -} +#define min(a, b) (a < b ? a : b) -struct lkl_dir *dir; - -static int lkl_test_opendir(void) +static int lkl_test_blkdev(void) { + char dev_str[] = { "/dev/xxxxxxxx" }; + char buffer[64*1024]; + uint64_t size, read = 0; int err; + int fd; - dir = lkl_opendir(mnt_point, &err); + snprintf(dev_str, sizeof(dev_str), "/dev/%08x", LKL_MKDEV(259, 0)); - lkl_test_logf("lkl_opedir(%s) = %d %s\n", mnt_point, err, - lkl_strerror(err)); + err = lkl_sys_mknod(dev_str, LKL_S_IFBLK | 0600, LKL_MKDEV(259, 0)); + if (err < 0) { + lkl_test_logf("mknod failed: %s\n", lkl_strerror(err)); + return TEST_FAILURE; + } - if (err == 0) - return TEST_SUCCESS; + fd = lkl_sys_open(dev_str, LKL_O_RDONLY, 0); + if (fd < 0) { + lkl_test_logf("open failed: %s\n", lkl_strerror(fd)); + return TEST_FAILURE; + } - return TEST_FAILURE; -} + err = lkl_sys_ioctl(fd, LKL_BLKGETSIZE64, (unsigned long)&size); + if (err < 0) { + lkl_test_logf("BLKGETSIZE64 failed: %s\n", lkl_strerror(fd)); + lkl_sys_close(fd); + return TEST_FAILURE; + } -static int lkl_test_readdir(void) -{ - struct lkl_linux_dirent64 *de = lkl_readdir(dir); - int wr = 0; - - while (de) { - wr += lkl_test_logf("%s ", de->d_name); - if (wr >= 70) { - lkl_test_logf("\n"); - wr = 0; - break; + while (read < size) { + err = lkl_sys_read(fd, buffer, + min(sizeof(buffer), size - read)); + if (err <= 0) { + lkl_test_logf("read failed: %s\n", lkl_strerror(err)); + lkl_sys_close(fd); + return TEST_FAILURE; } - de = lkl_readdir(dir); + read += err; } - if (lkl_errdir(dir) == 0) - return TEST_SUCCESS; + lkl_sys_close(fd); + lkl_test_logf("read %" PRIu64 " bytes\n", read); - return TEST_FAILURE; + return TEST_SUCCESS; } -LKL_TEST_CALL(mount_dev, lkl_mount_blkdev, 0, LKL_MKDEV(259, 0), - cla.fstype, 0, NULL, mnt_point, sizeof(mnt_point)) -LKL_TEST_CALL(closedir, lkl_closedir, 0, dir); -LKL_TEST_CALL(chdir_mnt_point, lkl_sys_chdir, 0, mnt_point); LKL_TEST_CALL(start_kernel, lkl_start_kernel, 0, bootparams); LKL_TEST_CALL(stop_kernel, lkl_sys_halt, 0); struct lkl_test tests[] = { - LKL_TEST(start_kernel), LKL_TEST(mount_dev), - LKL_TEST(chdir_mnt_point), LKL_TEST(opendir), - LKL_TEST(readdir), LKL_TEST(closedir), - LKL_TEST(umount_dev), LKL_TEST(stop_kernel), + LKL_TEST(start_kernel), + LKL_TEST(blkdev), + LKL_TEST(stop_kernel), }; int main(int argc, const char **argv) @@ -115,7 +100,7 @@ int main(int argc, const char **argv) } ret = lkl_test_run(tests, sizeof(tests) / sizeof(struct lkl_test), - "disk-vfio-pci %s", cla.fstype); + "disk-vfio-pci"); lkl_cleanup(); diff --git a/tools/lkl/tests/disk-vfio-pci.sh b/tools/lkl/tests/disk-vfio-pci.sh index fc888e59d9a604..62e6ed85f50c9b 100755 --- a/tools/lkl/tests/disk-vfio-pci.sh +++ b/tools/lkl/tests/disk-vfio-pci.sh @@ -11,25 +11,25 @@ bin_name="disk-vfio-pci" function wait_guest() { for i in `seq 300`; do - if $MYSSH exit 2> /dev/null; then - break - fi - sleep 1 + if $MYSSH exit 2> /dev/null; then + break + fi + sleep 1 done } function init() { # initialize - dd if=/dev/zero of=/home/ubuntu/nvme.img bs=1024 count=102400 - yes | sudo mkfs.$fstype /home/ubuntu/nvme.img $MYSSH sudo modprobe vfio-pci + $MYSSH "sh -c 'echo vfio-pci | + sudo tee /sys/bus/pci/devices/$pciname/driver_override'" $MYSSH "sh -c 'echo $nvme_id | - sudo tee /sys/bus/pci/drivers/vfio-pci/new_id'" + sudo tee /sys/bus/pci/drivers/vfio-pci/new_id'" $MYSSH "sh -c 'echo $pciname | - sudo tee /sys/bus/pci/drivers/nvme/unbind'" + sudo tee /sys/bus/pci/drivers/nvme/unbind'" $MYSSH "sh -c 'echo $pciname | - sudo tee /sys/bus/pci/drivers/vfio-pci/bind'" + sudo tee /sys/bus/pci/drivers/vfio-pci/bind'" $MYSSH sudo chown lkl:lkl /dev/vfio/3 $MYSCP $script_dir/$bin_name lkl@localhost: } @@ -37,33 +37,18 @@ function init() function cleanup() { $MYSSH "sh -c 'echo $pciname | - sudo tee /sys/bus/pci/drivers/vfio-pci/unbind'" - $MYSSH "sh -c 'echo $pciname | - sudo tee /sys/bus/pci/drivers/nvme/bind'" -} - -function run() -{ - if [ -z "$LKL_QEMU_TEST" ]; then - lkl_test_plan 0 "disk-vfio-pci $fstype" - echo "vfio not supported" - else - lkl_test_plan 1 "disk-vfio-pci $fstype" - lkl_test_run 1 init - lkl_test_exec $MYSSH ./$bin_name -n 0000:00:03.0 -t $fstype - lkl_test_plan 1 "disk-vfio-pci $fstype" - lkl_test_run 1 cleanup - fi + sudo tee /sys/bus/pci/drivers/vfio-pci/unbind'" } -if [ "$1" = "-t" ]; then - shift - fstype=$1 - shift +if [ -z "$LKL_QEMU_TEST" ]; then + lkl_test_plan 0 "disk-vfio-pci" + echo "vfio not supported" +else + lkl_test_plan 1 "disk-vfio-pci" + lkl_test_run 1 wait_guest + lkl_test_plan 1 "disk-vfio-pci" + lkl_test_run 1 init + lkl_test_exec $MYSSH ./$bin_name -n $pciname + lkl_test_plan 1 "disk-vfio-pci" + lkl_test_run 1 cleanup fi - -if [ -z "$fstype" ]; then - fstype="ext4" -fi - -"$@" diff --git a/tools/lkl/tests/run.py b/tools/lkl/tests/run.py index a39b674be63ab5..ca16f98841b51f 100755 --- a/tools/lkl/tests/run.py +++ b/tools/lkl/tests/run.py @@ -65,10 +65,7 @@ def end(self, obj): 'config', 'hijack-test.sh', 'LKL_HIJACK_ZPOLINE=1 hijack-test.sh', - 'disk-vfio-pci.sh -t ext4 run', - 'disk-vfio-pci.sh -t btrfs run', - 'disk-vfio-pci.sh -t vfat run', - 'disk-vfio-pci.sh -t xfs run' + 'disk-vfio-pci.sh', ] parser = argparse.ArgumentParser(description='LKL test runner') From 99e6cd5aa5c54f1b6ab2344d05ddfcdb8b1230e0 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Thu, 7 May 2026 07:57:47 +0000 Subject: [PATCH 3/7] lkl/ci: run the PCI VFIO test on github Add support for running qemu on github and run the PCI VFIO test. Also add a couple of scripts to make it easier to run the test locally: ./tools/lkl/scripts/qemu-x86_64-make-images.sh . ./tools/lkl/scripts/qemu-x86_64-start-and-set-env.sh LKL_QEMU_TEST=1 make -C tools/lkl run-tests Signed-off-by: Octavian Purdila --- .github/workflows/ci.yml | 19 +++++++++++------- tools/lkl/scripts/qemu-x86_64-make-images.sh | 20 +++++++++++++++++++ .../scripts/qemu-x86_64-start-and-set-env.sh | 17 ++++++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100755 tools/lkl/scripts/qemu-x86_64-make-images.sh create mode 100644 tools/lkl/scripts/qemu-x86_64-start-and-set-env.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13c99313d61b2f..bfa7dd7454ae78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: include: - - displayTargetName: ubuntu-22.04 + - displayTargetName: linux os: unix runs_on: ubuntu-22.04 shell: bash @@ -109,12 +109,7 @@ jobs: if: runner.os == 'Linux' run: | sudo apt update -y - sudo apt install -y ccache libjsmn-dev libfuse3-dev - - name: Install clang toolchain - if: runner.os == 'Linux' - run: | - sudo apt update -y - sudo apt install -y clang lld llvm + sudo apt install -y ccache libjsmn-dev libfuse3-dev clang lld llvm qemu-system-x86 qemu-utils sshpass cloud-image-utils - name: Install patched binutils for Windows if: runner.os == 'Windows' run: | @@ -145,6 +140,16 @@ jobs: sudo sh -c "echo 0 > /proc/sys/vm/mmap_min_addr" echo "setting env variable (debug)" echo "ZPOLINE_DEBUG=0" >> "$GITHUB_ENV" + - name: Start QEMU + if: matrix.displayTargetName == 'linux' + run: | + ./tools/lkl/scripts/qemu-x86_64-make-images.sh + sudo chmod a+rw /dev/kvm + . tools/lkl/scripts/qemu-x86_64-start-and-set-env.sh + echo MYHOST="$HOST" >> $GITHUB_ENV + echo MYSSH="$MYSSH" >> $GITHUB_ENV + echo MYSCP="$MYSCP" >> $GITHUB_ENV + echo LKL_QEMU_TEST=1 >> $GITHUB_ENV - name: Build run: | make -j4 -C tools/lkl ${{ matrix.build_options }} diff --git a/tools/lkl/scripts/qemu-x86_64-make-images.sh b/tools/lkl/scripts/qemu-x86_64-make-images.sh new file mode 100755 index 00000000000000..4051e20b99624e --- /dev/null +++ b/tools/lkl/scripts/qemu-x86_64-make-images.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +wget -q https://cloud-images.ubuntu.com/releases/noble/release-20260321/ubuntu-24.04-server-cloudimg-amd64.img +wget -q https://cloud-images.ubuntu.com/releases/noble/release-20260321/unpacked/ubuntu-24.04-server-cloudimg-amd64-vmlinuz-generic +wget -q https://cloud-images.ubuntu.com/releases/noble/release-20260321/unpacked/ubuntu-24.04-server-cloudimg-amd64-initrd-generic + +dd if=/dev/zero of=nvme.img bs=1024 count=102400 +cat > cloud.txt < Date: Thu, 7 May 2026 10:11:51 +0000 Subject: [PATCH 4/7] lkl/ci: remove duplicated circleci jobs To simplify CI management remove circleci jobs that already exists on github. Signed-off-by: Octavian Purdila --- .circleci/config.yml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 59c821d2d1fcc1..10fb5046c74c27 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -91,14 +91,6 @@ do_steps: &do_steps ## Customize the test machine jobs: - x86_64: - docker: - - image: lkldocker/circleci-x86_64:v1.4 - environment: - CROSS_COMPILE: "" - MKARG: "dpdk=no" - <<: *do_steps - i386: docker: - image: lkldocker/circleci-i386:v1.4 @@ -106,13 +98,6 @@ jobs: CROSS_COMPILE: "" <<: *do_steps - mingw32: - docker: - - image: lkldocker/circleci-mingw:v1.4 - environment: - CROSS_COMPILE: "i686-w64-mingw32-" - <<: *do_steps - android-arm32: docker: - image: lkldocker/circleci-android-arm32:v1.4 @@ -147,22 +132,10 @@ jobs: VALGRIND: 1 <<: *do_steps - x86_64_qemu: - docker: - - image: lkldocker/circleci-qemu-x86_64:v1.4 - environment: - CROSS_COMPILE: "" - MKARG: "dpdk=no" - LKL_QEMU_TEST: 1 - <<: *do_steps - workflows: version: 2 build: jobs: - - x86_64 - - x86_64_qemu - - mingw32 - android-aarch64 - freebsd11_x86_64 - i386 From bba15fcf9c4dd155befd2bc0d19a1c0688c6b35d Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 8 May 2026 00:10:43 +0000 Subject: [PATCH 5/7] lkl tests: make yaml logging more robust Explicitly tell the yaml parser how many spaces to expect for indentation. This avoids issues when the kernel buffer is truncated (because it overflows) and the first line contains more spaces. Signed-off-by: Octavian Purdila --- tools/lkl/tests/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lkl/tests/test.c b/tools/lkl/tests/test.c index 1ff6abeac82eb8..a4938d7b8ff4c0 100644 --- a/tools/lkl/tests/test.c +++ b/tools/lkl/tests/test.c @@ -56,7 +56,7 @@ static void print_log(void) { char last; - printf(" log: |\n"); + printf(" log: |1\n"); last = '\n'; while (head != tail) { if (last == '\n') From d95ef31f9abedc74bd16059ed5b367b640205a83 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 8 May 2026 00:13:10 +0000 Subject: [PATCH 6/7] lkl: explicitly uses asan mem* functions when kasan is enabled Otherwise host memcpy can be used and bypasses kasan interceptors. Unclear why the tests are passing in CI most of the time without this fix. They do fail reliably on my local environment. Signed-off-by: Octavian Purdila --- arch/lkl/include/asm/string.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/lkl/include/asm/string.h b/arch/lkl/include/asm/string.h index 31157992bf6e69..8b7f3beed14e5c 100644 --- a/arch/lkl/include/asm/string.h +++ b/arch/lkl/include/asm/string.h @@ -51,9 +51,16 @@ static inline void *__memmove(void *dest, const void *src, size_t count) #else /* __SANITIZE_ADDRESS__ */ -#undef memcpy +void *__asan_memset(void *addr, int c, ssize_t len); +void *__asan_memmove(void *dest, const void *src, ssize_t len); +void *__asan_memcpy(void *dest, const void *src, ssize_t len); + #undef memset +#define memset(s, c, n) __asan_memset(s, c, n) #undef memmove +#define memmove(dst, src, len) __asan_memmove(dst, src, len) +#undef memcpy +#define memcpy(dst, src, len) __asan_memcpy(dst, src, len) #endif /* __SANITIZE_ADDRESS__ */ From 8b61f603155feb4ece1f51f2305a538368fa0b32 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 9 May 2026 06:03:46 +0000 Subject: [PATCH 7/7] lkl tests: avoid variable test names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variable test name such as "disk btrfs ‑ cleanfs disk-8XLW" confuses the test reporter: This pull request removes 81 and adds 87 tests. Note that renamed tests count towards both. Signed-off-by: Octavian Purdila --- tools/lkl/tests/disk.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/lkl/tests/disk.sh b/tools/lkl/tests/disk.sh index 6f8eec29087a81..b7b431a5650886 100755 --- a/tools/lkl/tests/disk.sh +++ b/tools/lkl/tests/disk.sh @@ -35,13 +35,13 @@ function cleanfs() set -e if ! [ -z $ANDROID_WDIR ]; then - adb shell rm $1 + adb shell rm $file adb shell rm $ANDROID_WDIR/disk elif ! [ -z $BSD_WDIR ]; then - $MYSSH rm $1 + $MYSSH rm $file $MYSSH rm $BSD_WDIR/disk else - rm $1 + rm $file fi } @@ -65,5 +65,5 @@ lkl_test_plan 1 "disk $fstype" lkl_test_run 1 prepfs $fstype lkl_test_exec $script_dir/disk -d $file -t $fstype $@ lkl_test_plan 1 "disk $fstype" -lkl_test_run 1 cleanfs $file +lkl_test_run 1 cleanfs