Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cheribsd kernel flags #321

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions pycheribuild/config/chericonfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,6 @@ def __init__(self, loader, action_class) -> None:
self.skip_kernel = loader.add_bool_option(
"skip-kernel", "-skip-buildkernel", group=loader.freebsd_group,
help="Skip the buildkernel step when building FreeBSD or CheriBSD")
self.freebsd_kernconf = loader.add_commandline_only_option(
"kernel-config", "-kernconf", group=loader.freebsd_group, help_hidden=True,
help="Override the default FreeBSD/CheriBSD kernel config.")
self.freebsd_subdir = loader.add_commandline_only_option(
"freebsd-subdir", "-subdir", group=loader.freebsd_group, type=list, metavar="SUBDIRS",
help="Only build subdirs SUBDIRS of FreeBSD/CheriBSD instead of the full tree. Useful for quickly "
Expand Down
41 changes: 31 additions & 10 deletions pycheribuild/projects/cross/cheribsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,12 @@ def setup_config_options(cls, bootstrap_toolchain=False, use_upstream_llvm: bool
kernel_only_target=False, **kwargs) -> None:
super().setup_config_options(kernel_only_target=kernel_only_target, **kwargs)
if cls._xtarget:
# KERNCONF always depends on the target, so we don't inherit this config option. The only exception is
# the global --kernel-config option that is provided for convenience and backwards compat.
cls.kernel_config = cls.add_config_option(
"kernel-config", metavar="CONFIG", show_help=True, extra_fallback_config_names=["kernel-config"],
# KERNCONF always depends on the target, so we don't inherit this config option.
cls.option_kernel_config = cls.add_config_option(
"kernel-config", metavar="CONFIG", show_help=True, nargs="+", kind=list,
default=ComputedDefaultValue(
function=lambda _, p:
p.default_kernel_config() if p.has_default_buildkernel_kernel_config else None,
[p.default_kernel_config()] if p.has_default_buildkernel_kernel_config else None,
as_string="target-dependent, usually GENERIC"),
use_default_fallback_config_names=False, #
help="The kernel configuration to use for `make buildkernel`") # type: str
Expand Down Expand Up @@ -609,6 +608,15 @@ def setup_config_options(cls, bootstrap_toolchain=False, use_upstream_llvm: bool
assert not cls._xtarget.is_hybrid_or_purecap_cheri()
cls.build_lib32 = False

@property
def kernel_config(self):
# Shorthand to access the default kernel specified by the kernel-config option.
# The configuration option can be a list but the kernel_config is always the default
# kernel configuration to build, whether the option overrides it or it is the default one.
if self.option_kernel_config is None:
return None
return self.option_kernel_config[0]

def get_default_kernel_platform(self) -> ConfigPlatform:
if self.crosscompile_target.is_aarch64(include_purecap=True):
return ConfigPlatform.FVP
Expand Down Expand Up @@ -751,9 +759,13 @@ def __init__(self, *args, **kwargs) -> None:
self.kernel_toolchain_exists: bool = False
self.cross_toolchain_config = MakeOptions(MakeCommandKind.BsdMake, self)
if self.has_default_buildkernel_kernel_config:
assert self.kernel_config is not None
self.make_args.set(**self.arch_build_flags)
assert self.option_kernel_config is not None
self.extra_kernels = []
if self.option_kernel_config is not None:
# The first kernel configuration is the default one, all the others are new extra configs.
# This will be non-empty when the kernel-config list is overridden from cheribuild configuration.
self.extra_kernels += self.option_kernel_config[1:]
self.make_args.set(**self.arch_build_flags)

if self.subdir_override:
# build only part of the tree
Expand Down Expand Up @@ -1587,6 +1599,9 @@ def setup_config_options(cls, kernel_only_target=False, install_directory_help=N
"caprevoke-kernel", show_help=True, _allow_unknown_targets=True,
only_add_for_targets=CompilationTargets.ALL_CHERIBSD_CHERI_TARGETS_WITH_HYBRID,
help="Build kernel with caprevoke support (experimental)")

cls.external_configs = cls.add_config_option("extra-kernel-configs", metavar="CONFIG", default=[], kind=list,
nargs="+", help="Additional kernel configuration files to build")
if kernel_only_target:
return # The remaining options only affect the userspace build
cls.sysroot_only = cls.add_bool_option("sysroot-only", show_help=False,
Expand All @@ -1599,6 +1614,7 @@ def __init__(self, *args, **kwargs) -> None:
configs = self.extra_kernel_configs()
self.extra_kernels += [c.kernconf for c in configs if not c.mfsroot]
self.extra_kernels_with_mfs += [c.kernconf for c in configs if c.mfsroot]
self.extra_kernels += self.external_configs

def get_default_kernel_abi(self) -> KernelABI:
# XXX: Because the config option has _allow_unknown_targets it exists
Expand Down Expand Up @@ -1627,6 +1643,9 @@ def _get_config_variants(self, platforms: "set[ConfigPlatform]", kernABIs: "list
def _get_kABIs_to_build(self) -> "list[KernelABI]":
default_kABI = self.get_default_kernel_abi()
kernABIs = [default_kABI]
# If we are ovveriding the kernel configurations list, only build the default ABI
if self.kernel_config and self.kernel_config != self.default_kernel_config():
return kernABIs
# XXX: Because the config option has _allow_unknown_targets it exists
# in the base class and thus still inherited by non-purecap-kernel
# targets
Expand Down Expand Up @@ -1676,7 +1695,7 @@ def extra_kernel_configs(self) -> "list[CheriBSDConfig]":
def get_kernel_configs(self, platform: "Optional[ConfigPlatform]") -> "list[str]":
default = super().get_kernel_configs(platform)
extra = filter_kernel_configs(self.extra_kernel_configs(), platform=platform, kABI=None)
return default + [c.kernconf for c in extra]
return default + [c.kernconf for c in extra] + self.external_configs

def setup(self) -> None:
super().setup()
Expand Down Expand Up @@ -1817,9 +1836,11 @@ def default_kernel_config(self, platform: ConfigPlatform = None, **filter_kwargs

def get_kernel_configs(self, platform: "Optional[ConfigPlatform]") -> "typing.List[str]":
if self.kernel_config is not None:
return [self.kernel_config]
return [self.kernel_config] + self.external_configs
configs = self._get_all_kernel_configs()
return [c.kernconf for c in filter_kernel_configs(configs, platform=platform, kABI=None)]
conf_names = [c.kernconf for c in filter_kernel_configs(configs, platform=platform, kABI=None)]
conf_names += self.external_configs
return conf_names

def get_kernel_install_path(self, kernconf: str = None) -> Path:
""" Get the installed kernel path for an MFS kernel config that has been built. """
Expand Down
86 changes: 24 additions & 62 deletions tests/test_argument_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,58 +391,6 @@ def test_cheribsd_purecap_inherits_config_from_cheribsd():
assert not cheribsd_riscv_hybrid.debug_kernel, "riscv64-hybrid should have a JSON false override for debug-kernel"


def test_kernconf():
# The kernel-config command line option is special: There is a global (command-line-only) flag that is used
# as the default, but otherwise there should be no inheritance
config = _parse_arguments([])
cheribsd_riscv_hybrid = _get_cheribsd_instance("cheribsd-riscv64-hybrid", config)
cheribsd_riscv = _get_cheribsd_instance("cheribsd-riscv64", config)
freebsd_riscv = _get_target_instance("freebsd-riscv64", config, BuildFreeBSD)
freebsd_native = _get_target_instance("freebsd-amd64", config, BuildFreeBSD)
assert config.freebsd_kernconf is None
assert freebsd_riscv.kernel_config == "QEMU"
assert cheribsd_riscv_hybrid.kernel_config == "CHERI-QEMU"
assert freebsd_native.kernel_config == "GENERIC"

# Check that --kernconf is used as the fallback
config = _parse_arguments(["--kernconf=LINT", "--freebsd-riscv64/kernel-config=FOO"])
assert config.freebsd_kernconf == "LINT"
attr = inspect.getattr_static(freebsd_riscv, "kernel_config")
# previously we would replace the command line attribute with a string -> check this is no longer true
assert isinstance(attr, JsonAndCommandLineConfigOption)
assert freebsd_riscv.kernel_config == "FOO"
assert cheribsd_riscv_hybrid.kernel_config == "LINT"
assert freebsd_native.kernel_config == "LINT"

config = _parse_arguments(["--kernconf=LINT", "--cheribsd-riscv64-hybrid/kernel-config=SOMETHING"])
assert config.freebsd_kernconf == "LINT"
assert freebsd_riscv.kernel_config == "LINT"
assert cheribsd_riscv_hybrid.kernel_config == "SOMETHING"
assert freebsd_native.kernel_config == "LINT"

config = _parse_config_file_and_args(b'{ "cheribsd-riscv64/kernel-config": "RISCV64_CONFIG" }',
"--kernconf=GENERIC")
assert config.freebsd_kernconf == "GENERIC"
assert cheribsd_riscv_hybrid.kernel_config == "GENERIC"
assert cheribsd_riscv.kernel_config == "RISCV64_CONFIG"
assert freebsd_riscv.kernel_config == "GENERIC"
assert freebsd_native.kernel_config == "GENERIC"

# kernel-config/--kernconf should only be valid on the command line:
with pytest.raises(ValueError, match="^Unknown config option 'freebsd/kernel-config'$"):
_parse_config_file_and_args(b'{ "freebsd/kernel-config": "GENERIC" }')
# kernel-config/--kernconf should only be valid on the command line:
with pytest.raises(ValueError, match="^Option 'kernel-config' cannot be used in the config file$"):
_parse_config_file_and_args(b'{ "kernel-config": "GENERIC" }')
with pytest.raises(ValueError, match="^Option 'kernconf' cannot be used in the config file$"):
_parse_config_file_and_args(b'{ "kernconf": "GENERIC" }')

# There should not be any unsuffixed kernel-config options:
for tgt in ("cheribsd", "freebsd", "cheribsd-mfs-root-kernel"):
with pytest.raises(KeyError, match=r"error: unknown argument '--[\w-]+/kernel-config'"):
_parse_arguments(["--" + tgt + "/source-directory=/foo", "--" + tgt + "/kernel-config", "ABC"])


def test_duplicate_key():
with pytest.raises(SyntaxError, match="duplicate key: 'output-root'"):
_parse_config_file_and_args(b'{ "output-root": "/foo", "some-other-key": "abc", "output-root": "/bar" }')
Expand Down Expand Up @@ -691,6 +639,19 @@ def test_disk_image_path(target, expected_name):
"CHERI-PURECAP-QEMU",
"CHERI-FETT",
"CHERI-PURECAP-FETT"]),
pytest.param("cheribsd-riscv64-purecap",
["--cheribsd-riscv64-purecap/kernel-config", "FOOBAR_KERNEL",
"--cheribsd-riscv64-purecap/no-build-alternate-abi-kernels"],
"FOOBAR_KERNEL", []),
pytest.param("cheribsd-riscv64-purecap",
["--cheribsd-riscv64-purecap/kernel-config", "FOOBAR_KERNEL",
"--cheribsd-riscv64-purecap/build-alternate-abi-kernels"],
"FOOBAR_KERNEL", []),
pytest.param("cheribsd-riscv64-purecap",
["--cheribsd-riscv64-purecap/kernel-config", "FOOBAR_KERNEL",
"BAZBAZ_KERNEL",
"--cheribsd-riscv64-purecap/build-alternate-abi-kernels"],
"FOOBAR_KERNEL", ["BAZBAZ_KERNEL"]),
# Morello kernconf tests
pytest.param("cheribsd-aarch64",
[],
Expand All @@ -704,6 +665,14 @@ def test_disk_image_path(target, expected_name):
[],
"GENERIC-MORELLO",
["GENERIC-MORELLO-PURECAP"]),
pytest.param("cheribsd-morello-purecap",
["--cheribsd-morello-purecap/kernel-config", "FOOBAR_KERNEL",
"--cheribsd-morello-purecap/no-build-alternate-abi-kernels"],
"FOOBAR_KERNEL", []),
pytest.param("cheribsd-morello-purecap",
["--cheribsd-morello-purecap/kernel-config", "FOOBAR_KERNEL",
"--cheribsd-morello-purecap/build-alternate-abi-kernels"],
"FOOBAR_KERNEL", []),
# FreeBSD kernel configs
pytest.param("freebsd-i386", [], "GENERIC", []),
pytest.param("freebsd-aarch64", [], "GENERIC", []),
Expand Down Expand Up @@ -954,9 +923,9 @@ def test_mfs_root_kernel_config_options():
"auto_var_init", "build_alternate_abi_kernels",
"build_bench_kernels", "build_dir", "build_fett_kernels", "build_fpga_kernels",
"build_type", "caprevoke_kernel", "debug_kernel", "default_kernel_abi",
"extra_make_args", "fast_rebuild", "force_configure", "kernel_config",
"mfs_root_image", "skip_update", "use_ccache", "use_lto", "with_clean",
"with_debug_files", "with_debug_info"]
"external_configs", "extra_make_args", "fast_rebuild", "force_configure",
"mfs_root_image", "option_kernel_config", "skip_update", "use_ccache",
"use_lto", "with_clean", "with_debug_files", "with_debug_info"]


def test_mfs_root_kernel_inherits_defaults_from_cheribsd():
Expand Down Expand Up @@ -1007,13 +976,6 @@ def test_mfs_root_kernel_inherits_defaults_from_cheribsd():
assert cheribsd_riscv64_hybrid.kernel_config == "CHERI-QEMU"
assert mfs_riscv64.kernel_config is None
assert mfs_riscv64_hybrid.kernel_config == "MFS_CONFIG_RISCV64_HYBRID"
_parse_arguments(["--kernel-config=CONFIG_DEFAULT",
"--cheribsd-riscv64-purecap/kernel-config=BASE_CONFIG_RISCV64",
"--cheribsd-mfs-root-kernel-riscv64-hybrid/kernel-config=MFS_CONFIG_RISCV64_HYBRID"])
assert cheribsd_riscv64_purecap.kernel_config == "BASE_CONFIG_RISCV64"
assert cheribsd_riscv64_hybrid.kernel_config == "CONFIG_DEFAULT"
assert mfs_riscv64.kernel_config == "CONFIG_DEFAULT"
assert mfs_riscv64_hybrid.kernel_config == "MFS_CONFIG_RISCV64_HYBRID"


def test_relative_paths_in_config():
Expand Down