From a6360d5c6d56532314500d6a3d6f7e1e15a5a92d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 29 Aug 2024 21:51:50 +1000 Subject: [PATCH 1/9] scripts: Add script to apply configs to a source tree --- scripts/misc/apply-configs.py | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 scripts/misc/apply-configs.py diff --git a/scripts/misc/apply-configs.py b/scripts/misc/apply-configs.py new file mode 100755 index 0000000..eb59086 --- /dev/null +++ b/scripts/misc/apply-configs.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# +# Apply configs from etc/configs/ to the local kernel tree. +# +# eg. +# $ cd ~/linux +# $ make ppc64le_defconfig +# $ ~/ci-scripts/scripts/misc/apply-configs.py 4k-pages compat-y +# $ make olddefconfig +# +# Or a group of configs defined in configs.py: +# +# $ ~/ci-scripts/scripts/misc/apply-configs.py guest_configs + + +from subprocess import run +import os, sys + +base_dir = os.path.realpath(f'{os.path.dirname(os.path.realpath(sys.argv[0]))}/../..') +sys.path.append(f'{base_dir}/lib') + +import configs + + +def main(args): + if len(args) == 0: + print('Usage: apply-configs.py (config group|config file)+') + return False + + names = [] + for arg in args: + try: + group = getattr(configs, arg) + except AttributeError: + names.append(arg) + else: + names.extend(group) + + src_dir = os.getcwd() + paths = [] + for name in names: + # Look in source tree first, which must be current directory + full_path = f'{src_dir}/{name}' + if os.path.exists(full_path): + paths.append((name, full_path)) + continue + + full_path = f'{base_dir}/etc/configs/{name}' + if not name.endswith('.config'): + full_path += '.config' + + if not os.path.exists(full_path): + print(f'Error: unable to find {name}') + return False + + paths.append((name, full_path)) + + kbuild_output = os.environ.get('KBUILD_OUTPUT', None) + if kbuild_output: + # merge_config.sh writes its TMP files to $PWD, so change into KBUILD_OUTPUT + os.chdir(kbuild_output) + + for name, path in paths: + print(f'Merging {name} ...') + rc = run([f'{src_dir}/scripts/kconfig/merge_config.sh', '-m', '.config', path]) + if rc.returncode != 0: + print(f'Error: failed merging {name}') + return False + + return True + + +sys.exit(0 if main(sys.argv[1:]) else 1) From bb835950b2226fba90abb5edca2b261d0e899aad Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 16 Aug 2024 14:21:43 +1000 Subject: [PATCH 2/9] Add some instructions for using the debian image --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/README.md b/README.md index 63ce7dd..648caca 100644 --- a/README.md +++ b/README.md @@ -228,3 +228,59 @@ More than one selftest can be run by passing multiple arguments to From there the bisection can either be run by hand, or fully automated by creating a script to build the kernel and run the qemu test. + +Using the powerpc debian image +------------------------------ + +The debian powerpc image in `root-disks` can be used to test big endian kernels. +It also exercises COMPAT, which is not tested on ppc64le these days. + +The kernel needs virtio drivers as well as 9PFS built-in. For example to get it +booting with `g5_defconfig`: + +``` +$ cd linux +$ ~/ci-scripts/scripts/misc/apply-configs.py 9p guest_configs cgroups-y +$ make g5_defconfig vmlinux +$ ~/ci-scripts/boot/qemu-g5+debian +``` + +To do interactive testing, run the boot script with `--interactive`, the login +is `root/linuxppc`. + +Once logged in, to install packages a few steps are needed. + +If the network doesn't come up by default: +``` +dhclient $(basename $(ls -1d /sys/class/net/en*)) +``` + +If you need to use a http proxy: +``` +echo 'Acquire::http::Proxy "http://proxy.org:3128";' > /etc/apt/apt.conf.d/00proxy +``` + +Tell apt to update package lists while ignoring missing GPG keys: +``` +apt -o Acquire::AllowInsecureRepositories=true -o Acquire::AllowDowngradeToInsecureRepositories=true update +``` + +At that point you should be able to install the updated keyring: +``` +apt install -y --allow-unauthenticated debian-ports-archive-keyring +``` + +And update package lists again: +``` +apt update +``` + +Then you should be able to install packages, eg: +``` +apt install gcc +``` + +If you still can't install packages due to GPG errors, you can disable package authentication with: +``` +echo 'APT::Get::AllowUnauthenticated "true";' > /etc/apt/apt.conf.d/00allow-unauth +``` From d228243f83ef1029d2dca0b09e2df455ac980987 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 26 Jul 2024 22:38:42 +1000 Subject: [PATCH 3/9] lib: Import logic to selectively ignore warnings in boot logs --- etc/filters.ini | 4 ++++ lib/utils.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/etc/filters.ini b/etc/filters.ini index abe78cc..5124d63 100644 --- a/etc/filters.ini +++ b/etc/filters.ini @@ -1,3 +1,7 @@ +[ignore] +start=#@@@ ignore warnings @@@# +stop=#@@@ detect warnings @@@# + [patterns] v1=detected stall(s)? on CPU v2=WARNING:.*\s(un)?lock(s|ing)?\s diff --git a/lib/utils.py b/lib/utils.py index 2e2293c..0612d68 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -161,6 +161,8 @@ def filter_log_warnings(infile, outfile): parser = ConfigParser() parser.read_file(open(path)) + ignore_start = parser['ignore']['start'] + ignore_stop = parser['ignore']['stop'] suppressions = [t[1] for t in parser.items('suppressions', [])] suppression_patterns = [t[1] for t in parser.items('suppression_patterns', [])] suppression_patterns = [re.compile(p) for p in suppression_patterns] @@ -180,11 +182,20 @@ def suppress(line): return False found = False + ignoring = False while True: line = infile.readline() if len(line) == 0: break + if ignore_stop in line: + ignoring = False + elif not ignoring and ignore_start in line: + ignoring = True + + if ignoring: + continue + if suppress(line): continue From 1a1c688aff543ea1f5867e874b7c0e12951c5e11 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 31 Jul 2024 17:12:13 +1000 Subject: [PATCH 4/9] pexpect: Add ignore_warnings() --- lib/pexpect_utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/pexpect_utils.py b/lib/pexpect_utils.py index 5b7acfc..75b1c58 100644 --- a/lib/pexpect_utils.py +++ b/lib/pexpect_utils.py @@ -198,3 +198,11 @@ def xmon_di(p, addr): return result + +def ignore_warnings(p, f): + p.cmd('echo "#@@@ ignore warnings @@@#"') + bug_patterns = p.bug_patterns + p.bug_patterns = [] + f(p) + p.bug_patterns = bug_patterns + p.cmd('echo "#@@@ detect warnings @@@#"') From 989a520a1c0f39d90717a69709f08acc39cf636a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 26 Jul 2024 22:39:05 +1000 Subject: [PATCH 5/9] qemu: Add kasan_kunit callback --- lib/qemu_callbacks.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/qemu_callbacks.py b/lib/qemu_callbacks.py index f28b557..361bd47 100644 --- a/lib/qemu_callbacks.py +++ b/lib/qemu_callbacks.py @@ -1,5 +1,6 @@ import logging from utils import setup_timeout +from pexpect_utils import ignore_warnings ######################################## # Callbacks that can run once the VM has booted @@ -71,6 +72,12 @@ def run_selftests_nocheck(qconf, p, arg=None): return run_selftests(qconf, p, arg, check=False) +# KASAN Kunit test, needs modules +def kasan_kunit(qconf, p): + ignore_warnings(p, lambda p: p.cmd('modprobe kasan_test')) + return True + + # Invoke lkdtm via sysfs # eg. --callback "lkdtm(BUG WARNING)" def lkdtm(qconf, p, arg): From 0fa9122914268c1784e91626ebfdd3da616f0ab0 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 26 Jul 2024 17:11:25 +1000 Subject: [PATCH 6/9] configs: Add kasan-y.config --- etc/configs/kasan-y.config | 1 + 1 file changed, 1 insertion(+) create mode 100644 etc/configs/kasan-y.config diff --git a/etc/configs/kasan-y.config b/etc/configs/kasan-y.config new file mode 100644 index 0000000..4d92099 --- /dev/null +++ b/etc/configs/kasan-y.config @@ -0,0 +1 @@ +CONFIG_KASAN=y From b0b0a4e98ae6162b508b1723790a30f4214ff167 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 26 Jul 2024 22:38:58 +1000 Subject: [PATCH 7/9] ngci: Add QemuTestConfig --- lib/ngci.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/ngci.py b/lib/ngci.py index 66bc852..ded6b2e 100644 --- a/lib/ngci.py +++ b/lib/ngci.py @@ -291,6 +291,25 @@ def setup(self, state, boot, test_dir): boot.args.append('--net-tests') +class QemuTestConfig(TestConfig): + def __init__(self, name, callbacks=[]): + super().__init__(f'qemu-test-{name}') + self.callbacks = callbacks + + def setup(self, state, boot, test_dir): + start_marker = f'starting-{self.name}' + end_marker = f'end-{self.name}' + + # Script doesn't run the tests, just greps the qemu console.log + gen_script(f'{test_dir}/run.sh', + f"awk '/{start_marker}/, /{end_marker}/' ../console.log | tee extracted.log") + + boot.callbacks.append(f'sh(# {start_marker})') + for callback in self.callbacks: + boot.callbacks.append(callback) + boot.callbacks.append(f'sh(# {end_marker})') + + class QemuSelftestsConfig(TestConfig): def __init__(self, selftest_build, collection=None, exclude=[], extra_callbacks=[]): name = 'qemu-selftests' From 7b9884c199d8150d187dcc894a2d0be729afc29b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 26 Jul 2024 16:50:35 +1000 Subject: [PATCH 8/9] ngci/tests: Add qemu_kasan() --- etc/tests.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/etc/tests.py b/etc/tests.py index df20000..bb14819 100644 --- a/etc/tests.py +++ b/etc/tests.py @@ -1,4 +1,4 @@ -from ngci import TestSuite, SelftestsBuild, SelftestsConfig, QemuSelftestsConfig, TestConfig, QemuNetTestConfig +from ngci import * from configs import * from defaults import * from qemu import kvm_present @@ -359,3 +359,31 @@ def full_compile_and_qemu(args): full_compile_test(args, suite) qemu_coverage(args, suite) return suite + + +def qemu_kasan(args, suite=None): + images = std_images(args) + if suite is None: + suite = TestSuite('qemu-kasan', qemus=args.qemus) + + k = suite.add_kernel + b = suite.add_qemu_boot + + for image in images: + k('ppc64le_guest_defconfig', image, merge_config=guest_configs + ['kasan-y']) + + # Just a plain boot + b('qemu-pseries+p9+kvm+radix+fedora34', 'ppc64le_guest_defconfig', image, + script='qemu-pseries+p9+kvm+fedora34') + b('qemu-pseries+p9+kvm+hpt+fedora34', 'ppc64le_guest_defconfig', image, + script='qemu-pseries+p9+kvm+fedora34', cmdline='disable_radix') + + # Now boot and test KASAN + test = QemuTestConfig('kasan-kunit', ['kasan_kunit']) + b('qemu-pseries+p9+kvm+radix+fedora34+kasan', 'ppc64le_guest_defconfig', image, + script='qemu-pseries+p9+kvm+fedora34', tests=[test]) + # FIXME currently broken - some missing kasan_arch_is_ready() or similar + #b('qemu-pseries+p9+kvm+hpt+fedora34+kasan', 'ppc64le_guest_defconfig', image, + # script='qemu-pseries+p9+kvm+fedora34', tests=[test], cmdline='disable_radix') + + return suite From cc9ae226038088c592f177568bad3751d6bab8c7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 6 Nov 2024 22:52:17 +1100 Subject: [PATCH 9/9] build: Pass V=1 to selftests build if VERBOSE is set The selftests build now uses V=1 to show the actual command being run, since kernel commit 6fc6d7f59376 ("selftests: adopt BPF's approach to quieter builds"). --- build/scripts/container-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/container-build.sh b/build/scripts/container-build.sh index f673989..029dd6d 100755 --- a/build/scripts/container-build.sh +++ b/build/scripts/container-build.sh @@ -179,7 +179,7 @@ else # Workaround 303e6218ecec ("selftests: Fix O= and KBUILD_OUTPUT handling for relative paths") export abs_objtree=$KBUILD_OUTPUT - cmd="make -k $quiet -j $JFACTOR -C tools/testing/selftests" + cmd="make -k $quiet $verbose -j $JFACTOR -C tools/testing/selftests" if [[ "$1" == "ppctests" ]]; then TARGETS="powerpc"