From b49ebb1c8ae30849ec94e83928d93646da29b217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Sun, 5 May 2019 00:00:00 +0000 Subject: [PATCH] userland: get a bit closer to perfection --- README.adoc | 4 ++- common.py | 25 +++++++++----- example_properties.py | 17 ++++++++- run | 80 ++++++++++++++++++++++++++++++++----------- test-user-mode | 1 + 5 files changed, 97 insertions(+), 30 deletions(-) diff --git a/README.adoc b/README.adoc index 4ba1a61..9f5dfe4 100644 --- a/README.adoc +++ b/README.adoc @@ -3811,7 +3811,9 @@ Result on <> at bad30f513c46c1b0995d3a10c0d9bc2a33dc4fa0: * QEMU user: 45 seconds * QEMU full system: 223 seconds -=== QEMU user mode does not show stdout immediately +=== QEMU user mode quirks + +==== QEMU user mode does not show stdout immediately At 8d8307ac0710164701f6e14c99a69ee172ccbb70 + 1, I noticed that if you run link:userland/posix/count.c[]: diff --git a/common.py b/common.py index 19fdfc3..dc125b9 100644 --- a/common.py +++ b/common.py @@ -1372,11 +1372,13 @@ class TestResult: self, test_id: str ='', status : TestStatus =TestStatus.PASS, - ellapsed_seconds : float =0 + ellapsed_seconds : float =0, + reason : str ='' ): self.test_id = test_id self.status = status self.ellapsed_seconds = ellapsed_seconds + self.reason = reason def __eq__(self, other): return self.test_id == other.test_id @@ -1385,12 +1387,13 @@ class TestResult: return self.test_id < other.test_id def __str__(self): - out = [] - if self.status is not None: - out.append(self.status.name) - if self.ellapsed_seconds is not None: - out.append(LkmcCliFunction.seconds_to_hms(self.ellapsed_seconds)) - out.append(self.test_id) + out = [ + self.status.name, + LkmcCliFunction.seconds_to_hms(self.ellapsed_seconds), + repr(self.test_id), + ] + if self.status is TestStatus.FAIL: + out.append(repr(self.reason)) return ' '.join(out) class TestCliFunction(LkmcCliFunction): @@ -1455,11 +1458,16 @@ class TestCliFunction(LkmcCliFunction): ): if expected_exit_status is None: expected_exit_status = 0 + reason = '' if not self.env['dry_run']: if exit_status == expected_exit_status: test_result = TestStatus.PASS else: test_result = TestStatus.FAIL + reason = 'wrong exit status, got {} expected {}'.format( + exit_status, + expected_exit_status + ) ellapsed_seconds = run_obj.ellapsed_seconds else: test_result = TestStatus.PASS @@ -1467,7 +1475,8 @@ class TestCliFunction(LkmcCliFunction): test_result = TestResult( test_id_string, test_result, - ellapsed_seconds + ellapsed_seconds, + reason ) self.log_info(test_result) self.test_results.put(test_result) diff --git a/example_properties.py b/example_properties.py index fb1cabf..eaa99f1 100644 --- a/example_properties.py +++ b/example_properties.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +import os + class ExecutableProperties: ''' Encodes properties of userland and baremetal examples. @@ -11,26 +13,39 @@ class ExecutableProperties: exit_status=0, interactive=False, more_than_1s=False, + receives_signal=False, + requires_kernel_modules=False, ): + ''' + :param receives_signal: the test receives a signal. We skip those tests for now, + on userland because we are lazy to figure out the exact semantics + of how Python + QEMU + gem5 determine the exit status of signals. + ''' self.exit_status = exit_status self.interactive = interactive self.more_than_1s = more_than_1s + self.receives_signal = receives_signal + self.requires_kernel_modules = requires_kernel_modules def should_be_tested(self): return \ not self.interactive and \ - not self.more_than_1s + not self.more_than_1s and \ + not self.receives_signal executable_properties = { + 'arch/x86_64/c/ring0.c': ExecutableProperties(receives_signal=True), 'c/assert_fail.c': ExecutableProperties(exit_status=1), 'c/false.c': ExecutableProperties(exit_status=1), 'c/infinite_loop.c': ExecutableProperties(more_than_1s=True), + 'kernel_modules': ExecutableProperties(requires_kernel_modules=True), 'posix/count.c': ExecutableProperties(more_than_1s=True), 'posix/sleep_forever.c': ExecutableProperties(more_than_1s=True), 'posix/virt_to_phys_test.c': ExecutableProperties(more_than_1s=True), } def get(test_path): + test_path_components = test_path.split(os.sep) if test_path in executable_properties: return executable_properties[test_path] else: diff --git a/run b/run index f1c5dcd..5e6b2d5 100755 --- a/run +++ b/run @@ -99,7 +99,20 @@ timestamps. ''' ) self.add_argument( - '--kdb', default=False, + '--graphic', + default=False, + help='''\ +Run in graphic mode. +See: http://github.com/cirosantilli/linux-kernel-module-cheat#graphics +''' + ) + self.add_argument( + '--kdb', + default=False, + help='''\ +Setup KDB kernel CLI options. +See: http://github.com/cirosantilli/linux-kernel-module-cheat#kdb +''' ) self.add_argument( '--kernel-cli', @@ -136,14 +149,26 @@ See: http://github.com/cirosantilli/linux-kernel-module-cheat#fatal-kernel-too-o ''' ) self.add_argument( - '--kgdb', default=False, + '--kgdb', + default=False, + help='''\ +Setup KGDB kernel CLI options. +See: http://github.com/cirosantilli/linux-kernel-module-cheat#kgdb +''' ) self.add_argument( - '-K', '--kvm', default=False, - help='Use KVM. Only works if guest arch == host arch' + '-K', + '--kvm', + default=False, + help='''\ +Use KVM. Only works if guest arch == host arch. +See: http://github.com/cirosantilli/linux-kernel-module-cheat#kvm +''' ) self.add_argument( - '-m', '--memory', default='256M', + '-m', + '--memory', + default='256M', help='''\ Set the memory size of the guest. E.g.: `-m 512M`. We try to keep the default at the minimal ammount amount that boots all archs. Anything lower could lead @@ -159,19 +184,25 @@ Setup a kernel init parameter that makes the emulator quit immediately after boo ''' ) self.add_argument( - '-R', '--replay', default=False, + '-R', + '--replay', + default=False, help='Replay a QEMU run record deterministically' ) self.add_argument( - '-r', '--record', default=False, + '-r', + '--record', + default=False, help='Record a QEMU run record for later replay with `-R`' ) self.add_argument( - '--show-stdout', default=True, + '--show-stdout', + default=True, help='''Show emulator stdout and stderr on the host terminal.''' ) self.add_argument( - '--terminal', default=False, + '--terminal', + default=False, help='''\ Output to the terminal, don't pipe to tee as the default. Does not save the output to a file, but allows you to use debuggers. @@ -180,13 +211,15 @@ gem5 Python scripts with pdb. ''' ) self.add_argument( - '-T', '--trace', + '-T', + '--trace', help='''\ Set trace events to be enabled. If not given, gem5 tracing is completely disabled, while QEMU tracing is enabled but uses default traces that are very rare and don't affect performance, because `./configure --enable-trace-backends=simple` seems to enable some traces by default, e.g. `pr_manager_run`, and I don't know how to get rid of them. +See: http://github.com/cirosantilli/linux-kernel-module-cheat#tracing ''' ) self.add_argument( @@ -204,7 +237,9 @@ Trace instructions run to stdout. Shortcut for --trace --trace-stdout. ''' ) self.add_argument( - '-t', '--tmux', default=False, + '-t', + '--tmux', + default=False, help='''\ Create a tmux split the window. You must already be inside of a `tmux` session to use this option: @@ -222,23 +257,28 @@ Parameters to pass to the program running on the tmux split. Implies --tmux. ''' ) self.add_argument( - '-w', '--wait-gdb', default=False, - help='Wait for GDB to connect before starting execution' + '--wait-gdb', + default=False, + help='''\ +Wait for GDB to connect before starting execution +See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb +''' ) self.add_argument( - '-x', '--graphic', default=False, - help='Run in graphic mode. Mnemonic: X11' - ) - self.add_argument( - '-V', '--vnc', default=False, + '--vnc', + default=False, help='''\ Run QEMU with VNC instead of the default SDL. Connect to it with: `vinagre localhost:5900`. ''' ) self.add_argument( - 'extra_emulator_args', nargs='*', default=[], - help='Extra options to append at the end of the emulator command line' + 'extra_emulator_args', + nargs='*', + default=[], + help='''\ +Extra options to append at the end of the emulator command line. +''' ) def timed_main(self): diff --git a/test-user-mode b/test-user-mode index f178b7e..6feee14 100755 --- a/test-user-mode +++ b/test-user-mode @@ -12,6 +12,7 @@ class Main(common.TestCliFunction): super().__init__( description='''\ https://github.com/cirosantilli/linux-kernel-module-cheat#user-mode-tests +TODO: expose all userland relevant ./run args here as well somehow. ''', ) self.add_argument(