mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-27 20:14:27 +01:00
polish testing a bit further
This commit is contained in:
14
README.adoc
14
README.adoc
@@ -3172,11 +3172,17 @@ Result on <<p51>> at bad30f513c46c1b0995d3a10c0d9bc2a33dc4fa0:
|
|||||||
Automatically run non-interactive userland tests that can be run in user mode simulation:
|
Automatically run non-interactive userland tests that can be run in user mode simulation:
|
||||||
|
|
||||||
....
|
....
|
||||||
./build-userland --all-archs --all-emulators
|
./build --all-archs test-user-mode
|
||||||
./build-userland --all-archs --all-emulators --static --userland-build-id static
|
|
||||||
./test-user-mode --all-archs --all-emulators
|
./test-user-mode --all-archs --all-emulators
|
||||||
....
|
....
|
||||||
|
|
||||||
|
Or just for QEMU:
|
||||||
|
|
||||||
|
....
|
||||||
|
./build --all-archs test-user-mode-qemu
|
||||||
|
./test-user-mode --all-archs --emulator qemu
|
||||||
|
....
|
||||||
|
|
||||||
Source: link:test-user-mode[]
|
Source: link:test-user-mode[]
|
||||||
|
|
||||||
This testing excludes notably kernel module tests which depend on a full running kernel.
|
This testing excludes notably kernel module tests which depend on a full running kernel.
|
||||||
@@ -6695,6 +6701,8 @@ Bibliography:
|
|||||||
|
|
||||||
==== Count boot instructions
|
==== Count boot instructions
|
||||||
|
|
||||||
|
TODO: didn't port during refactor after 3b0a343647bed577586989fb702b760bd280844a. Reimplementing should not be hard.
|
||||||
|
|
||||||
* https://www.quora.com/How-many-instructions-does-a-typical-Linux-kernel-boot-take
|
* https://www.quora.com/How-many-instructions-does-a-typical-Linux-kernel-boot-take
|
||||||
* https://github.com/cirosantilli/chat/issues/31
|
* https://github.com/cirosantilli/chat/issues/31
|
||||||
* https://rwmj.wordpress.com/2016/03/17/tracing-qemu-guest-execution/
|
* https://rwmj.wordpress.com/2016/03/17/tracing-qemu-guest-execution/
|
||||||
@@ -10975,6 +10983,8 @@ make CROSS_COMPILE_DIR=/usr/bin
|
|||||||
|
|
||||||
== Benchmark this repo
|
== Benchmark this repo
|
||||||
|
|
||||||
|
TODO: didn't fully port during refactor after 3b0a343647bed577586989fb702b760bd280844a. Reimplementing should not be hard.
|
||||||
|
|
||||||
In this section document how benchmark builds and runs of this repo, and how to investigate what the bottleneck is.
|
In this section document how benchmark builds and runs of this repo, and how to investigate what the bottleneck is.
|
||||||
|
|
||||||
Ideally, we should setup an automated build server that benchmarks those things continuously for us, but our <<travis>> attempt failed.
|
Ideally, we should setup an automated build server that benchmarks those things continuously for us, but our <<travis>> attempt failed.
|
||||||
|
|||||||
55
build
55
build
@@ -73,6 +73,36 @@ This is equivalent to:
|
|||||||
....
|
....
|
||||||
./%(prog)s --arch x86_64 qemu-buildroot
|
./%(prog)s --arch x86_64 qemu-buildroot
|
||||||
....
|
....
|
||||||
|
|
||||||
|
Another important target is `all`:
|
||||||
|
|
||||||
|
....
|
||||||
|
./%(prog)s all
|
||||||
|
....
|
||||||
|
|
||||||
|
This does not trully build ALL configurations: that would be impractical.
|
||||||
|
But more precisely: build the reference configuration of each major component.
|
||||||
|
|
||||||
|
So e.g.: one config of Linux kenrel, Buildroot, gem5 and qemu.
|
||||||
|
Don't do for example all possible gem5 configs: debug, opt and fast,
|
||||||
|
as that would be huge. This ensures that every piece of software
|
||||||
|
builds in at least one config.
|
||||||
|
|
||||||
|
TODO looping over emulators is not currently supported by this script, e.g.:
|
||||||
|
|
||||||
|
....
|
||||||
|
./%(prog)s --arch x86_64 --arch aarch64 all
|
||||||
|
....
|
||||||
|
|
||||||
|
Instead, for the targets that are emulator dependent, you must select the
|
||||||
|
taret version for the desired emulatore, e.g.:
|
||||||
|
|
||||||
|
....
|
||||||
|
./build --arch aarch64 baremetal-qemu baremetal-gem5
|
||||||
|
....
|
||||||
|
|
||||||
|
The reason is that some targets depend on emulator, while others don't,
|
||||||
|
so looping over all of them would waste time.
|
||||||
''',
|
''',
|
||||||
)
|
)
|
||||||
buildroot_component = _Component(
|
buildroot_component = _Component(
|
||||||
@@ -131,8 +161,9 @@ This is equivalent to:
|
|||||||
|
|
||||||
self.name_to_component_map = {
|
self.name_to_component_map = {
|
||||||
'all': _Component(dependencies=[
|
'all': _Component(dependencies=[
|
||||||
'all-linux',
|
'qemu-gem5-buildroot',
|
||||||
'all-baremetal',
|
'all-baremetal',
|
||||||
|
'user-mode-qemu',
|
||||||
]),
|
]),
|
||||||
'all-baremetal': _Component(dependencies=[
|
'all-baremetal': _Component(dependencies=[
|
||||||
'qemu-baremetal',
|
'qemu-baremetal',
|
||||||
@@ -141,12 +172,6 @@ This is equivalent to:
|
|||||||
],
|
],
|
||||||
supported_archs=common.consts['crosstool_ng_supported_archs'],
|
supported_archs=common.consts['crosstool_ng_supported_archs'],
|
||||||
),
|
),
|
||||||
'all-linux': _Component(dependencies=[
|
|
||||||
'qemu-gem5-buildroot',
|
|
||||||
'gem5-debug',
|
|
||||||
'gem5-fast',
|
|
||||||
'qemu-user',
|
|
||||||
]),
|
|
||||||
'baremetal': _Component(dependencies=[
|
'baremetal': _Component(dependencies=[
|
||||||
'baremetal-gem5',
|
'baremetal-gem5',
|
||||||
'baremetal-qemu',
|
'baremetal-qemu',
|
||||||
@@ -282,6 +307,18 @@ This is equivalent to:
|
|||||||
],
|
],
|
||||||
supported_archs=common.consts['crosstool_ng_supported_archs'],
|
supported_archs=common.consts['crosstool_ng_supported_archs'],
|
||||||
),
|
),
|
||||||
|
'test-user-mode': _Component(dependencies=[
|
||||||
|
'test-user-mode-qemu',
|
||||||
|
'test-user-mode-gem5',
|
||||||
|
]),
|
||||||
|
'test-user-mode-qemu': _Component(dependencies=[
|
||||||
|
'user-mode-qemu',
|
||||||
|
'userland',
|
||||||
|
]),
|
||||||
|
'test-user-mode-gem5': _Component(dependencies=[
|
||||||
|
'gem5',
|
||||||
|
'userland-gem5',
|
||||||
|
]),
|
||||||
'user-mode-qemu': _Component(
|
'user-mode-qemu': _Component(
|
||||||
dependencies=['qemu-user', 'userland'],
|
dependencies=['qemu-user', 'userland'],
|
||||||
),
|
),
|
||||||
@@ -289,6 +326,10 @@ This is equivalent to:
|
|||||||
self._build_file('build-userland'),
|
self._build_file('build-userland'),
|
||||||
dependencies=['buildroot'],
|
dependencies=['buildroot'],
|
||||||
),
|
),
|
||||||
|
'userland-gem5': _Component(
|
||||||
|
self._build_file('build-userland', static=True, userland_build_id='static'),
|
||||||
|
dependencies=['buildroot'],
|
||||||
|
),
|
||||||
}
|
}
|
||||||
self.component_to_name_map = {self.name_to_component_map[key]:key for key in self.name_to_component_map}
|
self.component_to_name_map = {self.name_to_component_map[key]:key for key in self.name_to_component_map}
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ usually extra Buildroot targets.
|
|||||||
extra_make_args = self.sh.add_newlines(self.env['extra_make_args'])
|
extra_make_args = self.sh.add_newlines(self.env['extra_make_args'])
|
||||||
if self.env['build_linux']:
|
if self.env['build_linux']:
|
||||||
extra_make_args.extend(['linux-reconfigure', LF])
|
extra_make_args.extend(['linux-reconfigure', LF])
|
||||||
if self.env['emulator'] == 'gem5':
|
|
||||||
extra_make_args.extend(['gem5-reconfigure', LF])
|
|
||||||
if self.env['arch'] == 'x86_64':
|
if self.env['arch'] == 'x86_64':
|
||||||
defconfig = 'qemu_x86_64_defconfig'
|
defconfig = 'qemu_x86_64_defconfig'
|
||||||
elif self.env['arch'] == 'arm':
|
elif self.env['arch'] == 'arm':
|
||||||
@@ -151,7 +149,6 @@ usually extra Buildroot targets.
|
|||||||
self.sh.run_cmd(
|
self.sh.run_cmd(
|
||||||
[
|
[
|
||||||
'make', LF,
|
'make', LF,
|
||||||
'LKMC_GEM5_SRCDIR="{}"'.format(self.env['gem5_source_dir']), LF,
|
|
||||||
'LKMC_PARSEC_BENCHMARK_SRCDIR="{}"'.format(self.env['parsec_benchmark_source_dir']), LF,
|
'LKMC_PARSEC_BENCHMARK_SRCDIR="{}"'.format(self.env['parsec_benchmark_source_dir']), LF,
|
||||||
'O={}'.format(self.env['buildroot_build_dir']), LF,
|
'O={}'.format(self.env['buildroot_build_dir']), LF,
|
||||||
'V={}'.format(int(self.env['verbose'])), LF,
|
'V={}'.format(int(self.env['verbose'])), LF,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Build just enough to run ./test:
|
||||||
|
# https://github.com/cirosantilli/linux-kernel-module-cheat#automated-tests
|
||||||
set -eu
|
set -eu
|
||||||
test_size=1
|
test_size=1
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
@@ -10,4 +12,4 @@ while [ $# -gt 0 ]; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
./build-test-boot --size "$test_size"
|
./build-test-boot --size "$test_size"
|
||||||
./build --all-archs test-gdb
|
./build --all-archs test-gdb test-user-mode
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ while [ $# -gt 0 ]; do
|
|||||||
done
|
done
|
||||||
./build --all-archs qemu-gem5-buildroot
|
./build --all-archs qemu-gem5-buildroot
|
||||||
if [ "$test_size" -ge 3 ]; then
|
if [ "$test_size" -ge 3 ]; then
|
||||||
./build --arch aarch64 all-linux
|
./build-gem5 --arch aarch64 --gem5-build-type debug
|
||||||
|
./build-gem5 --arch aarch64 --gem5-build-type fast
|
||||||
fi
|
fi
|
||||||
|
|||||||
16
common.py
16
common.py
@@ -802,6 +802,9 @@ Valid emulators: {}
|
|||||||
'''
|
'''
|
||||||
return self.import_path(path).Main()
|
return self.import_path(path).Main()
|
||||||
|
|
||||||
|
def is_arch_supported(self, arch):
|
||||||
|
return self.supported_archs is None or arch in self.supported_archs
|
||||||
|
|
||||||
def log_error(self, msg):
|
def log_error(self, msg):
|
||||||
print('error: {}'.format(msg), file=sys.stdout)
|
print('error: {}'.format(msg), file=sys.stdout)
|
||||||
|
|
||||||
@@ -831,7 +834,7 @@ Valid emulators: {}
|
|||||||
for arch in real_archs:
|
for arch in real_archs:
|
||||||
if arch in env['arch_short_to_long_dict']:
|
if arch in env['arch_short_to_long_dict']:
|
||||||
arch = env['arch_short_to_long_dict'][arch]
|
arch = env['arch_short_to_long_dict'][arch]
|
||||||
if self.supported_archs is None or arch in self.supported_archs:
|
if self.is_arch_supported(arch):
|
||||||
if not env['dry_run']:
|
if not env['dry_run']:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
env['arch'] = arch
|
env['arch'] = arch
|
||||||
@@ -1075,7 +1078,7 @@ Stop running at the first failed test.
|
|||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
def run_test(self, run_obj, run_args, test_id=None):
|
def run_test(self, run_obj, run_args=None, test_id=None):
|
||||||
'''
|
'''
|
||||||
This is a setup / run / teardown setup for simple tests that just do a single run.
|
This is a setup / run / teardown setup for simple tests that just do a single run.
|
||||||
|
|
||||||
@@ -1086,9 +1089,12 @@ Stop running at the first failed test.
|
|||||||
:param run_args: arguments to be passed to the runnable object
|
:param run_args: arguments to be passed to the runnable object
|
||||||
:param test_id: test identifier, to be added in addition to of arch and emulator ids
|
:param test_id: test identifier, to be added in addition to of arch and emulator ids
|
||||||
'''
|
'''
|
||||||
test_id_string = self.test_setup(test_id)
|
if run_obj.is_arch_supported(self.env['arch']):
|
||||||
exit_status = run_obj(**run_args)
|
if run_args is None:
|
||||||
self.test_teardown(run_obj, exit_status, test_id_string)
|
run_args = {}
|
||||||
|
test_id_string = self.test_setup(test_id)
|
||||||
|
exit_status = run_obj(**run_args)
|
||||||
|
self.test_teardown(run_obj, exit_status, test_id_string)
|
||||||
|
|
||||||
def test_setup(self, test_id):
|
def test_setup(self, test_id):
|
||||||
test_id_string = '{} {}'.format(self.env['emulator'], self.env['arch'])
|
test_id_string = '{} {}'.format(self.env['emulator'], self.env['arch'])
|
||||||
|
|||||||
55
test
55
test
@@ -1,16 +1,39 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env python3
|
||||||
set -eu
|
|
||||||
test_size=1
|
import common
|
||||||
while [ $# -gt 0 ]; do
|
import shell_helpers
|
||||||
case "$1" in
|
from shell_helpers import LF
|
||||||
--size)
|
|
||||||
test_size="$2"
|
class Main(common.TestCliFunction):
|
||||||
shift 2
|
def __init__(self):
|
||||||
;;
|
super().__init__(
|
||||||
esac
|
description='''\
|
||||||
done
|
Run all tests in one go.
|
||||||
./test-boot --size "$test_size"
|
'''
|
||||||
./test-userland --all-archs --all-emulators
|
)
|
||||||
./test-gdb --all-archs --all-emulators
|
self.add_argument(
|
||||||
./test-baremetal --all-archs --all-emulators
|
'--size',
|
||||||
./test-user-mode --all-archs --all-emulators
|
default=1,
|
||||||
|
type=int,
|
||||||
|
help='''\
|
||||||
|
Size of the tests to run. Scale:
|
||||||
|
|
||||||
|
* 1: a few seconds and important
|
||||||
|
* 2: < 5 minutes and important or a few seconds and not too important
|
||||||
|
* 3: all
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
|
def timed_main(self):
|
||||||
|
run_args = self.get_common_args()
|
||||||
|
test_boot_args = run_args.copy()
|
||||||
|
test_boot_args['size'] = self.env['size']
|
||||||
|
self.run_test(self.import_path_main('test-boot'), test_boot_args, 'test-boot')
|
||||||
|
self.run_test(self.import_path_main('test-userland-full-system'), run_args, 'test-userland')
|
||||||
|
self.run_test(self.import_path_main('test-baremetal'), run_args, 'test-baremetal')
|
||||||
|
self.run_test(self.import_path_main('test-user-mode'), run_args, 'test-user-mode')
|
||||||
|
self.run_test(self.import_path_main('test-gdb'), run_args, 'test-gdb')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
Main().cli_exit()
|
||||||
|
|
||||||
|
|||||||
16
test-boot
16
test-boot
@@ -8,7 +8,7 @@ class Main(common.TestCliFunction):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
description='''\
|
description='''\
|
||||||
Run Linux kernel boot tests and benchmarks.
|
Test and benchmark the Linux kernel boot. Use inits that exit immediately.
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
self.add_argument(
|
self.add_argument(
|
||||||
@@ -16,11 +16,7 @@ Run Linux kernel boot tests and benchmarks.
|
|||||||
default=1,
|
default=1,
|
||||||
type=int,
|
type=int,
|
||||||
help='''\
|
help='''\
|
||||||
Size of the tests to run. Scale:
|
See ./test --help for --size.
|
||||||
|
|
||||||
* 1: a few seconds and important
|
|
||||||
* 2: < 5 minutes and important or a few seconds and not too important
|
|
||||||
* 3: all
|
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,7 +60,10 @@ Size of the tests to run. Scale:
|
|||||||
self._bench(trace='exec_tb')
|
self._bench(trace='exec_tb')
|
||||||
if self.env['emulator'] == 'gem5' and self.env['size'] >= 3:
|
if self.env['emulator'] == 'gem5' and self.env['size'] >= 3:
|
||||||
if self.env['arch'] == 'x86_64':
|
if self.env['arch'] == 'x86_64':
|
||||||
cpu_types = ['DerivO3CPU']
|
cpu_types = [
|
||||||
|
# TODO segfault
|
||||||
|
#'DerivO3CPU'
|
||||||
|
]
|
||||||
elif self.env['is_arm']:
|
elif self.env['is_arm']:
|
||||||
cpu_types = [
|
cpu_types = [
|
||||||
'DerivO3CPU',
|
'DerivO3CPU',
|
||||||
@@ -86,7 +85,8 @@ Size of the tests to run. Scale:
|
|||||||
# Do a fuller testing for aarch64.
|
# Do a fuller testing for aarch64.
|
||||||
for build_type in ['debug', 'fast']:
|
for build_type in ['debug', 'fast']:
|
||||||
self._bench(gem5_build_type=build_type)
|
self._bench(gem5_build_type=build_type)
|
||||||
self._bench(gem5_script='biglittle')
|
# Requires patching the executable.
|
||||||
|
# self._bench(gem5_script='biglittle')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
Main().cli_exit()
|
Main().cli_exit()
|
||||||
|
|||||||
Reference in New Issue
Block a user