From 68be07098f45b9b5df921ee06219f41607783bcd Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Mon, 28 Sep 2026 23:13:11 +0300 Subject: [PATCH 1/9] scripts: update build_utils Latest GCC & Binutils + a few nice fixes. While at it, unhardcode the CI GCC version so it is fetched dynamically. Signed-off-by: Daniil Tatianin <99danilt@gmail.com> --- .github/workflows/main.yml | 12 +++++++++--- .gitignore | 2 ++ scripts/build_utils | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b5a92b56..3b43a558 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -51,15 +51,21 @@ jobs: with: submodules: true + - if: ${{ matrix.toolchain == 'gcc' }} + id: toolchain-version + name: Get the toolchain version + run: | + python3 -c 'import scripts.build_utils.toolchain_builder as tb + print(f"key=gcc-{tb.GCC_VERSION}-binutils-{tb.BINUTILS_VERSION}")' \ + >> "$GITHUB_OUTPUT" + - if: ${{ matrix.toolchain == 'gcc' }} id: toolchain-cache name: Restore the toolchain cache uses: actions/cache/restore@v4.2.2 - env: - gcc-version: 15.1.0 with: path: "${{ github.workspace }}/toolchain/tools-${{ matrix.toolchain }}-${{ matrix.arch }}" - key: "${{ runner.os }}-${{ runner.arch }}-${{ matrix.arch }}-gcc-${{ env.gcc-version }}" + key: "${{ runner.os }}-${{ runner.arch }}-${{ matrix.arch }}-${{ steps.toolchain-version.outputs.key }}" - name: Build the platform toolchain run: "${{ github.workspace }}/build.py --arch ${{ matrix.arch }} --toolchain ${{ matrix.toolchain }} --no-tune-native --toolchain-only" diff --git a/.gitignore b/.gitignore index b45008ea..3fa34d93 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ kernel-source/ bin/ hyper-* toolchain/tools-* +toolchain/*_sources +toolchain/*.tar.gz* __pycache__ diff --git a/scripts/build_utils b/scripts/build_utils index 1655098c..e4920dbc 160000 --- a/scripts/build_utils +++ b/scripts/build_utils @@ -1 +1 @@ -Subproject commit 1655098c202ff50ef23849b87e800fe12e9ff83b +Subproject commit e4920dbcc2a847a28e78ac1c1c3e81c0c83ee150 From 108740b899ba255ace0481acdbe45b4600a93b46 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Sun, 27 Sep 2026 00:28:35 +0300 Subject: [PATCH 2/9] common/bit: don't let BIT_U8() and BIT_U16() promote to int The shift in BIT_OF_TYPE() promotes any type narrower than int to int, so BIT_U8() and BIT_U16() produced a signed int, which BIT_FIELD_READ() then rejects as a field mask. Cast the result back to the requested type. Signed-off-by: Daniil Tatianin <99danilt@gmail.com> --- kernel/include/common/bit.h | 2 +- tests/test-cases/test_bit.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/include/common/bit.h b/kernel/include/common/bit.h index 6fc19d5d..2eaa82f0 100644 --- a/kernel/include/common/bit.h +++ b/kernel/include/common/bit.h @@ -7,7 +7,7 @@ #define BITS_PER_BYTE CHAR_BIT #define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) -#define BIT_OF_TYPE(type, x) (((type)1) << (x)) +#define BIT_OF_TYPE(type, x) ((type)(((type)1) << (x))) #define BIT_U8(x) BIT_OF_TYPE(u8, (x)) #define BIT_U16(x) BIT_OF_TYPE(u16, (x)) #define BIT_U32(x) BIT_OF_TYPE(u32, (x)) diff --git a/tests/test-cases/test_bit.c b/tests/test-cases/test_bit.c index f194a86c..2b5047e4 100644 --- a/tests/test-cases/test_bit.c +++ b/tests/test-cases/test_bit.c @@ -16,6 +16,11 @@ TEST_CASE(bit_constants_and_single_bit_macros) ASSERT_EQ(BIT_U16(9), (u16)0x0200); ASSERT_EQ(BIT_U32(31), 0x80000000u); ASSERT_EQ(BIT_U64(63), 0x8000000000000000ull); + + ASSERT_EQ(sizeof(BIT_U8(0)), sizeof(u8)); + ASSERT_EQ(sizeof(BIT_U16(0)), sizeof(u16)); + ASSERT_EQ(sizeof(BIT_U32(0)), sizeof(u32)); + ASSERT_EQ(sizeof(BIT_U64(0)), sizeof(u64)); } TEST_CASE(bit_mask_helpers) From 0081e9de5bf99cc98b9c2edb8d9a71ac7c1abadf Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Sat, 26 Sep 2026 23:11:05 +0300 Subject: [PATCH 3/9] panic: introduce panic_in_progress() Lets code that serializes itself against other callers, such as the console flush, get out of the panic path's way. Signed-off-by: Daniil Tatianin <99danilt@gmail.com> --- kernel/include/panic.h | 2 ++ kernel/panic.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/kernel/include/panic.h b/kernel/include/panic.h index 13ad67fe..0d867ddd 100644 --- a/kernel/include/panic.h +++ b/kernel/include/panic.h @@ -5,6 +5,8 @@ #include #include +bool panic_in_progress(void); + NORETURN PRINTF_DECL(1, 2) void panic(const char *reason, ...); diff --git a/kernel/panic.c b/kernel/panic.c index 68863563..315f12cc 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -10,6 +10,11 @@ static bool s_in_panic; +bool panic_in_progress(void) +{ + return atomic_load_acquire(&s_in_panic); +} + #undef panic void panic(const char *fmt, ...) { From f1d3744ead68652cf492777cef126495d03fa574 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Sat, 26 Sep 2026 23:11:05 +0300 Subject: [PATCH 4/9] log: don't re-enter the console flush A print from inside a flush, e.g. a WARN() in a console driver or an interrupt that logs mid write, flushed again and clobbered the static buffers the outer flush was still using. Registering a console flushed the same way with no protection at all. Let only one caller flush at a time. A nested caller leaves its record in the ring and marks the flush pending for the owner to pick up. A panic flushes regardless, since the flush it interrupted never resumes. Signed-off-by: Daniil Tatianin <99danilt@gmail.com> --- kernel/console.c | 2 +- kernel/include/log.h | 7 ++-- kernel/log.c | 76 +++++++++++++++++++++++++++++++++++++--- tests/kernel_helpers.cpp | 3 +- 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/kernel/console.c b/kernel/console.c index a8d1306f..c207b4bf 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -23,7 +23,7 @@ error_t register_console(struct console *con) con->next = g_consoles; g_consoles = con; - log_flush_console(con); + log_flush_consoles(); return EOK; } diff --git a/kernel/include/log.h b/kernel/include/log.h index 012f3070..b3fe204f 100644 --- a/kernel/include/log.h +++ b/kernel/include/log.h @@ -65,11 +65,8 @@ enum log_level { void vprint(const char *msg, va_list vlist); -// Defined in console.h -struct console; - -// Writes every record the console has not seen yet to it -void log_flush_console(struct console *con); +// Writes out every record to every console that hasn't yet been output by it +void log_flush_consoles(void); PRINTF_DECL(1, 2) void print(const char *msg, ...); diff --git a/kernel/log.c b/kernel/log.c index d08fdfd4..e8af86ac 100644 --- a/kernel/log.c +++ b/kernel/log.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -11,6 +13,7 @@ #include #include #include +#include #include