lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250731035341.2598127-2-davidgow@google.com>
Date: Thu, 31 Jul 2025 11:53:36 +0800
From: David Gow <davidgow@...gle.com>
To: Brendan Higgins <brendan.higgins@...ux.dev>, Rae Moar <rmoar@...gle.com>, 
	Shuah Khan <skhan@...uxfoundation.org>
Cc: David Gow <davidgow@...gle.com>, linux-kselftest@...r.kernel.org, 
	kunit-dev@...glegroups.com, linux-kernel@...r.kernel.org
Subject: [RFC PATCH 2/2] kunit: tool: Automatically pick a default
 architecture if none is specified

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 <davidgow@...gle.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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ