Currently, kunit.py will default to 'um' (User-Mode Linux) if no specific
--arch option is given. However, UML is only available on x86-based
architectures, so kunit.py fails by default on anything else.

Instead, for non-x86 architectures, enumerate the qemu configs looking
for one which matches the current architecture. This currently uses
`uname -m`, which doesn't always match the kernel/kunit's architecture
name (e.g., aarch64 versus arm64), so look at both the kernel and qemu
architecture names in the qemu config until one matches.

With this change `./tools/testing/kunit/kunit.py run` should function
out-of-the-box on most non-x86 architectures, assuming qemu is installed.

Signed-off-by: David Gow <david...@google.com>
---
 tools/testing/kunit/kunit.py           |  2 +-
 tools/testing/kunit/kunit_kernel.py    | 43 ++++++++++++++++++++------
 tools/testing/kunit/kunit_tool_test.py | 10 +++---
 3 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 7f9ae55fd6d5..188bb7f2802f 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -351,7 +351,7 @@ def add_common_opts(parser: argparse.ArgumentParser) -> 
None:
                                  'string passed to the ARCH make param, '
                                  'e.g. i386, x86_64, arm, um, etc. Non-UML '
                                  'architectures run on QEMU.'),
-                           type=str, default='um', metavar='ARCH')
+                           type=str, metavar='ARCH')
 
        parser.add_argument('--cross_compile',
                            help=('Sets make\'s CROSS_COMPILE variable; it 
should '
diff --git a/tools/testing/kunit/kunit_kernel.py 
b/tools/testing/kunit/kunit_kernel.py
index c3201a76da24..7042e44e3a88 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -211,6 +211,31 @@ def _default_qemu_config_path(arch: str) -> str:
 
        raise ConfigError(arch + ' is not a valid arch, options are ' + 
str(sorted(options)))
 
+def _detect_default_architecture() -> str:
+       uname_arch = os.uname().machine
+
+       options = [f[:-3] for f in os.listdir(QEMU_CONFIGS_DIR) if 
f.endswith('.py')]
+
+       if uname_arch == 'x86_64' or uname_arch == 'i486' or uname_arch == 
'i586' or uname_arch == 'i686':
+               return 'um'
+
+       for option in options:
+               config_path = os.path.join(QEMU_CONFIGS_DIR, option + '.py')
+               module_path = '.' + 
os.path.join(os.path.basename(QEMU_CONFIGS_DIR), os.path.basename(config_path))
+               spec = importlib.util.spec_from_file_location(module_path, 
config_path)
+               assert spec is not None
+               config = importlib.util.module_from_spec(spec)
+               # See https://github.com/python/typeshed/pull/2626 for context.
+               assert isinstance(spec.loader, importlib.abc.Loader)
+               spec.loader.exec_module(config)
+
+               if config.QEMU_ARCH.linux_arch == uname_arch:
+                       return option
+               if config.QEMU_ARCH.qemu_arch == uname_arch:
+                       return option
+
+       raise ConfigError('Could not find a valid config for ' + uname_arch + 
', options are ' + str(sorted(options)))
+
 def _get_qemu_ops(config_path: str,
                  extra_qemu_args: Optional[List[str]],
                  cross_compile: Optional[str]) -> Tuple[str, 
LinuxSourceTreeOperations]:
@@ -247,19 +272,19 @@ class LinuxSourceTree:
        """Represents a Linux kernel source tree with KUnit tests."""
 
        def __init__(
-             self,
-             build_dir: str,
-             kunitconfig_paths: Optional[List[str]]=None,
-             kconfig_add: Optional[List[str]]=None,
-             arch: Optional[str]=None,
-             cross_compile: Optional[str]=None,
-             qemu_config_path: Optional[str]=None,
-             extra_qemu_args: Optional[List[str]]=None) -> None:
+                 self,
+                 build_dir: str,
+                 kunitconfig_paths: Optional[List[str]]=None,
+                 kconfig_add: Optional[List[str]]=None,
+                 arch: Optional[str]=None,
+                 cross_compile: Optional[str]=None,
+                 qemu_config_path: Optional[str]=None,
+                 extra_qemu_args: Optional[List[str]]=None) -> None:
                signal.signal(signal.SIGINT, self.signal_handler)
                if qemu_config_path:
                        self._arch, self._ops = _get_qemu_ops(qemu_config_path, 
extra_qemu_args, cross_compile)
                else:
-                       self._arch = 'um' if arch is None else arch
+                       self._arch = _detect_default_architecture() if arch is 
None else arch
                        if self._arch == 'um':
                                self._ops = 
LinuxSourceTreeOperationsUml(cross_compile=cross_compile)
                        else:
diff --git a/tools/testing/kunit/kunit_tool_test.py 
b/tools/testing/kunit/kunit_tool_test.py
index bbba921e0eac..a3dd456d62cd 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -747,7 +747,7 @@ class KUnitMainTest(unittest.TestCase):
                self.mock_linux_init.assert_called_once_with('.kunit',
                                                
kunitconfig_paths=['mykunitconfig'],
                                                kconfig_add=None,
-                                               arch='um',
+                                               arch=None,
                                                cross_compile=None,
                                                qemu_config_path=None,
                                                extra_qemu_args=[])
@@ -758,7 +758,7 @@ class KUnitMainTest(unittest.TestCase):
                self.mock_linux_init.assert_called_once_with('.kunit',
                                                
kunitconfig_paths=['mykunitconfig'],
                                                kconfig_add=None,
-                                               arch='um',
+                                               arch=None,
                                                cross_compile=None,
                                                qemu_config_path=None,
                                                extra_qemu_args=[])
@@ -769,7 +769,7 @@ class KUnitMainTest(unittest.TestCase):
                self.mock_linux_init.assert_called_once_with('.kunit',
                                                
kunitconfig_paths=[kunit_kernel.ALL_TESTS_CONFIG_PATH, 'mykunitconfig'],
                                                kconfig_add=None,
-                                               arch='um',
+                                               arch=None,
                                                cross_compile=None,
                                                qemu_config_path=None,
                                                extra_qemu_args=[])
@@ -783,7 +783,7 @@ class KUnitMainTest(unittest.TestCase):
                mock_linux_init.assert_called_once_with('.kunit',
                                                        
kunitconfig_paths=['mykunitconfig', 'other'],
                                                        kconfig_add=None,
-                                                       arch='um',
+                                                       arch=None,
                                                        cross_compile=None,
                                                        qemu_config_path=None,
                                                        extra_qemu_args=[])
@@ -794,7 +794,7 @@ class KUnitMainTest(unittest.TestCase):
                self.mock_linux_init.assert_called_once_with('.kunit',
                                                kunitconfig_paths=[],
                                                kconfig_add=['CONFIG_KASAN=y', 
'CONFIG_KCSAN=y'],
-                                               arch='um',
+                                               arch=None,
                                                cross_compile=None,
                                                qemu_config_path=None,
                                                extra_qemu_args=[])
-- 
2.50.1.552.g942d659e1b-goog


Reply via email to