Skip to content

Config Presets - #27

Merged
d-tatianin merged 37 commits into
masterfrom
misc
Oct 3, 2026
Merged

d-tatianin merged 37 commits into
masterfrom
misc

Conversation

@d-tatianin

Copy link
Copy Markdown
Member

No description provided.

GCC's LTO plugin resolves which IR symbols are referenced before code
generation, but the memset() and memcpy() calls GCC emits for struct
initializers only appear during code generation. With LTO on, memset()
is dropped as unreferenced and the link fails.

Add ultra_sources_no_lto() and build both string.c files with it, so
these functions always reach the linker as machine code.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
At -O2 and above GCC lowers __builtin_strcmp() to strncmp() when it
knows a bound on one of the strings, so any optimized build that
compares against a fixed size array fails to link without it.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
arg_parser.h uses uint64_t and int64_t but relies on another standard
header to pull in <cstdint>, which GCC 16's libstdc++ no longer does,
so the unit tests fail to build.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
@d-tatianin
d-tatianin force-pushed the misc branch 2 times, most recently from a85ae6b to c6752b5 Compare September 29, 2026 22:37
clang deprecated giving -fuse-ld= a path in favor of --ld-path=, so use
that.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
It's annoying to have to manually edit the config every time you want to
make an image for real hardware, so just add a target option instead.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
build.py is getting huge as it is, and we're going to need this code to
be reusable to implement a lint check, so factor it out.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A preset has to select its arch today, and --arch only checks it for a
conflict, so one preset cannot serve several architectures.

Take the arch from --arch, x86_64 by default, and apply it on top of
the preset like the toolchain. A preset that selects a different arch
is an error. The arch becomes part of a preset build's directory name.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
--config recreates the build directory's .config from the preset on
every run, so anything changed through --menuconfig is gone on the
next build.

Only create .config when it does not exist yet. When the preset changes
later, apply just the options it changed and keep the ones changed
through menuconfig. To tell the two apart, the build directory keeps
what the preset produced last time in .config.merge-base. If both sides
changed the same option, the menuconfig value wins and a warning is
printed, as it is when an option stops having an effect because
something it depends on was turned off. --reset-config recreates
.config from the preset.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The base config lists the "recommended" options to enable for a chosen
platform. Other architectures like aarch64 may add extra platforms in
the future alognside "base", but for an architecture that is mostly
one platform aka the IBM PC for x86_64, base will likely remain the only
platform we support.

Automatically load configs/arch/<arch>/base.config, when the arch has
one, for builds without --config. A --config file build is still loaded
on its own without the base pre-applied.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A build without --config gets only the Kconfig defaults, which leave
every debug check off, while day to day development wants the cheap
ones on.

Add configs/debug-lite.config with the memory management assertions
and the undefined behavior sanitizer, and build it when --config is not
given. --config now also takes the name of a preset in configs/. Presets
are loaded on top of the arch's base config. The default preset keeps
the plain build-<toolchain>-<arch> directory.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
@d-tatianin
d-tatianin force-pushed the misc branch 4 times, most recently from f1b70ef to 9dc3ebd Compare October 3, 2026 12:56
Config files go stale without anyone noticing: a renamed symbol is
dropped with no warning, and a changed Kconfig default can turn a line
into a no-op or change what it means.

Add scripts/check_configs.py and run it as the "configs" lint check.
Each line must name an existing symbol, must not pick the arch or the
toolchain, and must change the resulting config for at least one arch
and toolchain the file is built with. Presets must not set symbols that
only exist for one arch, those belong in the arch's base config.

The check resolves many configs on one Kconfig object, which needs
the kconfiglib fix for unset_values() leaving symbols marked as
assigned, so pull it in here.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A config with -O3 and LTO.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
--lint only needs compile_commands.json, so there's no reason to build
the entire kernel to run it.

Split configuring out of cmake_build() and make --lint configure, then
check and stop. An existing build directory is configured again, so a
source added since the last build is checked too.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The unit tests only need the host compiler but run in every build job,
once per toolchain, and the lint step hides behind a condition that
picks one of those jobs.

Move each into its own job: the unit tests once per OS, the lint once
on ubuntu with clang.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Now that we have clean config presets, use those for CI instead of
hardcoding a separate config for it.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
An arch selects its bitness and endianness, and Kconfig cannot stop it
from selecting both, since choice members cannot be selected. Make
CMake reject both, next to its checks for neither. The bitness check
now tests ARCH_WIDTH, leaving ARCH_UNKNOWN_BIT_WIDTH unused, and
nothing ever read ARCH_UNKNOWN_ENDIAN, so drop both.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
It isn't a constant but a value memory.c sets at boot, like everything
else in arch/memory.h. smbios.c got PAGE_SIZE through memory/io.h and
now includes arch/constants.h itself.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Every arch hardcoded the same constants in its own arch/constants.h.
Make the page size a Kconfig choice limited to the sizes an arch
selects with ARCH_HAS_PAGE_SIZE_*, add CACHE_LINE_SHIFT defaulting to
6, which an arch can override through ARCH_CACHE_LINE_SHIFT, and
derive the constants from both in a generic <arch_constants.h> that
replaces arch/constants.h.

x2apic.c used nothing from arch/constants.h and just drops the include.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The linker flag hardcoded 4096, which would disagree with PAGE_SIZE
as soon as an arch offers another page size.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Any width other than 4 silently made phys_addr_t a u64.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Macros for sharing typed constants/literals with assembly.

- LITERAL_OF_TYPE for literals, e.g. LITERAL_OF_TYPE(reg_t, 123)
- CONSTANT_OF_TYPE for constant values that aren't literals,
  e.g. CONSTANT_OF_TYPE(virt_addr_t, CONFIG_VIRT_BASE + 0x1000)

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
These are supposed to represent an arch-native, unsigned value.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
An #if on a macro that was never defined silently evaluates to 0,
e.g. a CONFIG_ value an arch forgot to provide. Make it an error.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
cr2 is not a physical address.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The generic CheckCompilerFlag module only exists since CMake 3.19,
while we require 3.18. Include the C one once for the whole kernel
instead of from arch/x86_64.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
phys_addr_t is supposed to be an opaque width type and it also depends
on ULTRA_ARCH_PHYS_ADDR_WIDTH, so we cannot print it using a hardcoded
format specifier. Add a special %p extension for it which always formats
it correctly with the right number of digits.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The page table sizes are size_t like the other values in the message.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
u8 and the other narrow unsigned types promote to int, so %d compiled
for them without a warning.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The variable prefix check dumped and walked the AST of each source on
its own. Collect what it needs in one cached scan, so more checks can
read the same parse instead of running clang again.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Without one the compiler picks an enum's type from its values, and
that type decides the enum's size and how it is printed.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The compiler only sees the type under a typedef, so it accepts %llX
for a phys_addr_t or %lu for a virt_addr_t. We want to enforce stricter
rules for consistency + validate the types for our %p extensions.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Conflating page frame numbers and physical addresses makes the code
harder to read and is bug prone. Moreover, this now collides with the
requirement of %pPA for physical addresses. Make pfn_t its own type and
add related helpers.

Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
@d-tatianin
d-tatianin merged commit 8944fd5 into master Oct 3, 2026
10 checks passed
@d-tatianin
d-tatianin deleted the misc branch October 3, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant