From 482d7adf4b673941780040b849a81b2b57c82b82 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Thu, 13 Jul 2023 10:13:51 -0700 Subject: [PATCH 1/3] boot_cheribsd: Check loader prompt was used if needed to pick kernel When booting an image with a non-default kernel on a platform using loader rather than direct booting (e.g. Morello), expect needs to interrupt the loader and select the alternate kernel before booting, but we weren't checking we managed to do this, only that if we saw the loader countdown we were able to interrupt it. Thus add a check to fail if the boot gets to single user (mounting root) without having seen the loader prompt. --- pycheribuild/boot_cheribsd/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pycheribuild/boot_cheribsd/__init__.py b/pycheribuild/boot_cheribsd/__init__.py index 47df03f7e..11d7b81c5 100755 --- a/pycheribuild/boot_cheribsd/__init__.py +++ b/pycheribuild/boot_cheribsd/__init__.py @@ -845,6 +845,7 @@ def boot_and_login(child: CheriBSDSpawnMixin, *, starttime, kernel_init_only=Fal loader_boot_prompt_messages = [*boot_messages, BOOT_LOADER_PROMPT] loader_boot_messages = [*loader_boot_prompt_messages, AUTOBOOT_PROMPT] i = child.expect(loader_boot_messages, timeout=20 * 60, timeout_msg="timeout before loader or kernel") + ran_manual_boot = False if i >= len(boot_messages): # Skip 10s wait from loader(8) if we see the autoboot message if i == loader_boot_messages.index(AUTOBOOT_PROMPT): # Hit Enter @@ -855,7 +856,7 @@ def boot_and_login(child: CheriBSDSpawnMixin, *, starttime, kernel_init_only=Fal i = child.expect(loader_boot_prompt_messages, timeout=60, timeout_msg="timeout before loader prompt") if i != loader_boot_prompt_messages.index(BOOT_LOADER_PROMPT): - failure("failed to enter boot loader prompt", exit=True) + failure("failed to enter boot loader prompt after stopping autoboot", exit=True) # Fall through to BOOT_LOADER_PROMPT else: child.sendline("\r") @@ -863,7 +864,10 @@ def boot_and_login(child: CheriBSDSpawnMixin, *, starttime, kernel_init_only=Fal success("===> loader(8) waiting boot commands") # Just boot the default kernel if no alternate kernel directory is given child.sendline("boot {}".format(boot_alternate_kernel_dir or "")) + ran_manual_boot = True i = child.expect(boot_messages, timeout=5 * 60, timeout_msg="timeout before kernel") + if boot_alternate_kernel_dir and not ran_manual_boot: + failure("failed to enter boot loader prompt", exit=True) if i == boot_messages.index(TRYING_TO_MOUNT_ROOT): success("===> mounting rootfs") if bootverbose: From a5dfcbf2792b00ad210f0ff24c846f55c709dde2 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Jul 2023 10:26:08 -0700 Subject: [PATCH 2/3] Update the regex for the boot loader. Upstream FreeBSD changed the autoboot countdown string in September of 2019 (merged to CheriBSD in late December 2022). The existing regex didn't match the new string, so test boots requesting a non-default kernel on Morello (e.g. the purecap kernel) have been booting the default (hybrid) kernel instead. This updates the regex to match on the new string as well as the old. --- pycheribuild/boot_cheribsd/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pycheribuild/boot_cheribsd/__init__.py b/pycheribuild/boot_cheribsd/__init__.py index 11d7b81c5..ecf45ec60 100755 --- a/pycheribuild/boot_cheribsd/__init__.py +++ b/pycheribuild/boot_cheribsd/__init__.py @@ -72,7 +72,10 @@ CompilationTargets.CHERIBSD_MORELLO_PURECAP, )} -AUTOBOOT_PROMPT = re.compile(r"(H|, h)it \[Enter] to boot ") +# boot loader without lua: "Hit [Enter] to boot " +# menu.lua before Sep 2019: ", hit [Enter] to boot " +# menu.lua: "[Space] to pause" +AUTOBOOT_PROMPT = re.compile(r"((H|, h)it \[Enter] to boot |\[Space] to pause)") BOOT_LOADER_PROMPT = "OK " STARTING_INIT = "start_init: trying /sbin/init" From 7a7e0b24b3c43c8e0383ffd2112507c7508ab3df Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Jul 2023 11:48:53 -0700 Subject: [PATCH 3/3] Replace str.format() calls with f strings to appease ruff. --- pycheribuild/projects/cross/benchmarks.py | 3 +-- pycheribuild/projects/cross/libcxx.py | 11 ++++------- pycheribuild/projects/repository.py | 3 +-- test-scripts/run_libcxx_tests.py | 3 +-- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/pycheribuild/projects/cross/benchmarks.py b/pycheribuild/projects/cross/benchmarks.py index 29d771e45..058db9767 100644 --- a/pycheribuild/projects/cross/benchmarks.py +++ b/pycheribuild/projects/cross/benchmarks.py @@ -483,8 +483,7 @@ def run_tests(self): self.fatal("running x86 tests is not implemented yet") return # testing, not benchmarking -> run only once - test_command = "cd '/build/{dirname}' && ./run_jenkins-bluehive.sh -d0 -r1 -s".format( - dirname=self.bundle_dir.name) + test_command = f"cd '/build/{self.bundle_dir.name}' && ./run_jenkins-bluehive.sh -d0 -r1 -s" self.target_info.run_cheribsd_test_script("run_simple_tests.py", "--test-command", test_command, "--test-timeout", str(120 * 60), mount_builddir=True) diff --git a/pycheribuild/projects/cross/libcxx.py b/pycheribuild/projects/cross/libcxx.py index b579a0999..79de531c7 100644 --- a/pycheribuild/projects/cross/libcxx.py +++ b/pycheribuild/projects/cross/libcxx.py @@ -330,16 +330,13 @@ def add_cross_flags(self): elif self.nfs_mounted_path: self.libcxx_lit_jobs = " -j1" # We can only run one job here since we are using scp self.fatal("nfs_mounted_path not portend to new libc++ test infrastructure yet") - executor = "SSHExecutorWithNFSMount(\\\"{host}\\\", nfs_dir=\\\"{nfs_dir}\\\"," \ - "path_in_target=\\\"{nfs_in_target}\\\", config=self, username=\\\"{user}\\\"," \ - " port={port})".format(host=self.qemu_host, user=self.qemu_user, port=self.qemu_port, - nfs_dir=self.nfs_mounted_path, nfs_in_target=self.nfs_path_in_qemu) + executor = f"SSHExecutorWithNFSMount(\\\"{self.qemu_host}\\\", nfs_dir=\\\"{self.nfs_mounted_path}\\\"," \ + f"path_in_target=\\\"{self.nfs_path_in_qemu}\\\", config=self," \ + f"username=\\\"{self.qemu_user}\\\", port={self.qemu_port})" else: self.libcxx_lit_jobs = " -j1" # We can only run one job here since we are using scp executor = self.commandline_to_str([self.source_dir / "utils/ssh.py", - "--host", "{user}@{host}:{port}".format(host=self.qemu_host, - user=self.qemu_user, - port=self.qemu_port)]) + "--host", f"{self.qemu_user}@{self.qemu_host}:{self.qemu_port}"]) if self.target_info.is_baremetal(): target_info = "libcxx.test.target_info.BaremetalNewlibTI" else: diff --git a/pycheribuild/projects/repository.py b/pycheribuild/projects/repository.py index a73487b71..f0851c12a 100644 --- a/pycheribuild/projects/repository.py +++ b/pycheribuild/projects/repository.py @@ -263,8 +263,7 @@ def ensure_cloned(self, current_project: "Project", *, src_dir: Path, base_proje default_clone_branch = self.get_default_branch(current_project, include_per_target=False) assert target_override is not None, "Default src != base src -> must have a per-target override" assert target_override.branch != default_clone_branch, \ - "Cannot create worktree with same branch as base repo: {} vs {}".format(target_override.branch, - default_clone_branch) + f"Cannot create worktree with same branch as base repo: {target_override.branch} vs {default_clone_branch}" if (src_dir / ".git").exists(): return current_project.info("Creating git-worktree checkout of", base_project_source_dir, "with branch", diff --git a/test-scripts/run_libcxx_tests.py b/test-scripts/run_libcxx_tests.py index 087b74bcb..382590170 100755 --- a/test-scripts/run_libcxx_tests.py +++ b/test-scripts/run_libcxx_tests.py @@ -314,8 +314,7 @@ def run_parallel_impl(args: argparse.Namespace, processes: "list[LitShardProcess if len(not_booted_processes) == 0: boot_cheribsd.success("All shards have booted succesfully. Releasing barrier (num_waiting = ", mp_barrier.n_waiting, ")") - assert mp_barrier.n_waiting == len(processes), "{} != {}".format(mp_barrier.n_waiting, - len(processes)) + assert mp_barrier.n_waiting == len(processes), f"{mp_barrier.n_waiting} != {len(processes)}" mp_barrier.wait(timeout=10) boot_cheribsd.success("Barrier has been released, tests should run now.") # assert target_process.stage < shard_result[2], "STAGE WENT BACKWARDS?"