mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Gow <davidgow@google.com>
To: Brendan Higgins <brendan.higgins@linux.dev>,
	Rae Moar <rmoar@google.com>,
	 Shuah Khan <skhan@linuxfoundation.org>
Cc: David Gow <davidgow@google.com>,
	linux-kselftest@vger.kernel.org,  kunit-dev@googlegroups.com,
	linux-kernel@vger.kernel.org
Subject: [RFC PATCH 2/2] kunit: tool: Automatically pick a default architecture if none is specified
Date: Thu, 31 Jul 2025 11:53:36 +0800	[thread overview]
Message-ID: <20250731035341.2598127-2-davidgow@google.com> (raw)
In-Reply-To: <20250731035341.2598127-1-davidgow@google.com>

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@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	other threads:[~2025-07-31  3:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-31  3:53 [RFC PATCH 1/2] kunit: tool: Move qemu architecture dependency checks into a function David Gow
2025-07-31  3:53 ` David Gow [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250731035341.2598127-2-davidgow@google.com \
    --to=davidgow@google.com \
    --cc=brendan.higgins@linux.dev \
    --cc=kunit-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=rmoar@google.com \
    --cc=skhan@linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®