Skip to content
Merged
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
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ You can boot in QEMU, use the shell commands, inspect lock state and uptime, and
- Local builds use `kernel/VERSION` automatically.
- Release pipeline overrides with release tag so shipped assets match the tag exactly.
- Optional manual override:
- `make -C kernel all KERNEL_VERSION=v0.0.20260331`
- `make -C kernel all KERNEL_VERSION=v0.0.20260331.1`

## Project Website

Expand All @@ -94,6 +94,7 @@ You can boot in QEMU, use the shell commands, inspect lock state and uptime, and
- `kernel/src/multiboot.h`: Multiboot data structures used for boot-time memory map parsing.
- `kernel/src/pmm.c`, `kernel/src/pmm.h`: Physical memory manager bitmap and frame stats APIs.
- `kernel/src/heap.c`, `kernel/src/heap.h`: Heap allocator (`kmalloc`/`kfree`) with integrity checks, fragmentation stats, live histogram telemetry, and leak-trace snapshots.
- `kernel/src/heap_diag.c`, `kernel/src/heap_diag.h`: Heap diagnostics telemetry backend (histograms, trace snapshots, counters).
- `kernel/src/isr.s`: interrupt service routine stubs.
- `kernel/linker.ld`: Links the kernel at 1 MiB.
- `kernel/grub/grub.cfg`: GRUB menu entry.
Expand Down Expand Up @@ -133,6 +134,7 @@ make -C kernel test
```

This runs host-side unit tests for shared formatting helpers (`src/sbuf.c`) in parallel with kernel feature work.
It also runs heap diagnostics tests (`heap_diag_test`) and corruption-injection integrity tests (`heap_integrity_test`).
Both CI (`build-kernel.yml`) and release (`release-kernel.yml`) pipelines run this test gate before build/release assets.

## Run Coverage
Expand All @@ -141,7 +143,7 @@ Both CI (`build-kernel.yml`) and release (`release-kernel.yml`) pipelines run th
make -C kernel coverage
```

This generates an LCOV report at `kernel/build/coverage/lcov.info` for the host-side formatter test suite.
This generates an LCOV report at `kernel/build/coverage/lcov.info` for host-side formatter and heap diagnostics/integrity test suites.

## Codecov Bundle Analysis (Ready)

Expand All @@ -164,6 +166,7 @@ This generates an LCOV report at `kernel/build/coverage/lcov.info` for the host-
- Run `heapstress` (and `heapstress 512`) and verify stress summary counters print without hanging.
- Run `heaphist` and verify live block/byte buckets are printed.
- Run `heapleaks` (and `heapleaks 32`) and verify active allocation trace rows are printed.
- Run `make -C kernel test` and verify `heap_diag_test` and `heap_integrity_test` pass.
- Status bar continues updating lock states and uptime while typing commands.
- Keyboard input remains functional if heap queue allocation fails (fallback queue path).
- Decimal printing remains functional if print-buffer heap allocation fails (fallback path).
Expand Down
7 changes: 7 additions & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,33 +67,40 @@ test: $(BUILD_DIR)
$(HOST_CC) $(HOST_CFLAGS) tests/sbuf_boundary_test.c src/sbuf.c -o $(BUILD_DIR)/sbuf_boundary_test
$(HOST_CC) $(HOST_CFLAGS) tests/stats_util_test.c src/sbuf.c src/stats_util.c -o $(BUILD_DIR)/stats_util_test
$(HOST_CC) $(HOST_CFLAGS) tests/heap_diag_test.c src/heap_diag.c -o $(BUILD_DIR)/heap_diag_test
$(HOST_CC) $(HOST_CFLAGS) -DHEAP_ENABLE_TEST_HOOKS tests/heap_integrity_test.c src/heap.c src/heap_diag.c tests/pmm_stub.c -o $(BUILD_DIR)/heap_integrity_test
$(BUILD_DIR)/sbuf_test
$(BUILD_DIR)/sbuf_integration_test
$(BUILD_DIR)/sbuf_boundary_test
$(BUILD_DIR)/stats_util_test
$(BUILD_DIR)/heap_diag_test
$(BUILD_DIR)/heap_integrity_test

coverage: $(BUILD_DIR)
@mkdir -p $(BUILD_DIR)/coverage
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c src/sbuf.c -o $(BUILD_DIR)/sbuf_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -DHEAP_ENABLE_TEST_HOOKS -c src/heap.c -o $(BUILD_DIR)/heap_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c src/heap_diag.c -o $(BUILD_DIR)/heap_diag_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c src/stats_util.c -o $(BUILD_DIR)/stats_util_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/sbuf_test.c -o $(BUILD_DIR)/sbuf_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/sbuf_integration_test.c -o $(BUILD_DIR)/sbuf_integration_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/sbuf_boundary_test.c -o $(BUILD_DIR)/sbuf_boundary_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/stats_util_test.c -o $(BUILD_DIR)/stats_util_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/heap_diag_test.c -o $(BUILD_DIR)/heap_diag_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -DHEAP_ENABLE_TEST_HOOKS -c tests/heap_integrity_test.c -o $(BUILD_DIR)/heap_integrity_test_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) -c tests/pmm_stub.c -o $(BUILD_DIR)/pmm_stub_cov.o
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/sbuf_test_cov.o $(BUILD_DIR)/sbuf_cov.o -o $(BUILD_DIR)/sbuf_test_cov
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/sbuf_integration_test_cov.o $(BUILD_DIR)/sbuf_cov.o -o $(BUILD_DIR)/sbuf_integration_test_cov
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/sbuf_boundary_test_cov.o $(BUILD_DIR)/sbuf_cov.o -o $(BUILD_DIR)/sbuf_boundary_test_cov
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/stats_util_test_cov.o $(BUILD_DIR)/sbuf_cov.o $(BUILD_DIR)/stats_util_cov.o -o $(BUILD_DIR)/stats_util_test_cov
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/heap_diag_test_cov.o $(BUILD_DIR)/heap_diag_cov.o -o $(BUILD_DIR)/heap_diag_test_cov
$(HOST_CC) $(HOST_COVERAGE_CFLAGS) $(BUILD_DIR)/heap_integrity_test_cov.o $(BUILD_DIR)/heap_cov.o $(BUILD_DIR)/heap_diag_cov.o $(BUILD_DIR)/pmm_stub_cov.o -o $(BUILD_DIR)/heap_integrity_test_cov
lcov --zerocounters --directory $(BUILD_DIR)
$(BUILD_DIR)/sbuf_test_cov
$(BUILD_DIR)/sbuf_integration_test_cov
$(BUILD_DIR)/sbuf_boundary_test_cov
$(BUILD_DIR)/stats_util_test_cov
$(BUILD_DIR)/heap_diag_test_cov
$(BUILD_DIR)/heap_integrity_test_cov
lcov --capture --directory $(BUILD_DIR) --output-file $(BUILD_DIR)/coverage/lcov.raw.info
lcov --remove $(BUILD_DIR)/coverage/lcov.raw.info '/usr/*' '*/tests/*' --output-file $(BUILD_DIR)/coverage/lcov.info
lcov --summary $(BUILD_DIR)/coverage/lcov.info
Expand Down
2 changes: 1 addition & 1 deletion kernel/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.0.20260331
v0.0.20260331.1
81 changes: 81 additions & 0 deletions kernel/src/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ struct heap_block {

static struct heap_block* g_heap_head = (struct heap_block*)0;

#ifdef HEAP_ENABLE_TEST_HOOKS
enum {
HEAP_TEST_MAX_BLOCKS = 32u,
HEAP_TEST_ARENA_SIZE = 16384u
};

static uint8_t g_heap_test_arena[HEAP_TEST_ARENA_SIZE];
static struct heap_block* g_heap_test_blocks[HEAP_TEST_MAX_BLOCKS];
static uint32_t g_heap_test_block_count = 0u;
#endif

static uint32_t align_up(uint32_t value, uint32_t align) {
return (value + align - 1u) & ~(align - 1u);
}
Expand Down Expand Up @@ -218,6 +229,76 @@ int heap_check_integrity(struct heap_integrity_report* out_report) {
return heap_check_integrity_internal(out_report);
}

#ifdef HEAP_ENABLE_TEST_HOOKS
int heap_debug_seed_chain(const uint32_t* sizes, const uint8_t* free_flags, uint32_t count) {
if (sizes == 0 || free_flags == 0 || count == 0u || count > HEAP_TEST_MAX_BLOCKS) {
return 0;
}

g_heap_head = (struct heap_block*)0;
g_heap_test_block_count = 0u;

uintptr_t cursor = (uintptr_t)&g_heap_test_arena[0];
uintptr_t arena_end = (uintptr_t)&g_heap_test_arena[HEAP_TEST_ARENA_SIZE];

struct heap_block* prev = (struct heap_block*)0;
for (uint32_t i = 0; i < count; ++i) {
struct heap_block* block = (struct heap_block*)cursor;
uintptr_t payload_start = cursor + block_overhead();
uintptr_t next_cursor = payload_start + sizes[i];
if (next_cursor > arena_end) {
g_heap_head = (struct heap_block*)0;
g_heap_test_block_count = 0u;
return 0;
}

block->magic = HEAP_MAGIC;
block->size = sizes[i];
block->free = free_flags[i] ? 1u : 0u;
block->next = (struct heap_block*)0;

if (prev == 0) {
g_heap_head = block;
} else {
prev->next = block;
}

g_heap_test_blocks[i] = block;
prev = block;
cursor = next_cursor;
g_heap_test_block_count = i + 1u;
}

return 1;
}

void heap_debug_corrupt_magic(uint32_t index) {
if (index >= g_heap_test_block_count) {
return;
}
g_heap_test_blocks[index]->magic = 0u;
}

void heap_debug_misalign_size(uint32_t index) {
if (index >= g_heap_test_block_count) {
return;
}
g_heap_test_blocks[index]->size |= 1u;
}

void heap_debug_make_next_regression(uint32_t index) {
if (index == 0u || index >= g_heap_test_block_count) {
return;
}
g_heap_test_blocks[index]->next = g_heap_test_blocks[index - 1u];
}

void heap_debug_clear_chain(void) {
g_heap_head = (struct heap_block*)0;
g_heap_test_block_count = 0u;
}
#endif

struct heap_stats heap_get_stats(void) {
struct heap_stats stats;
stats.total_bytes = 0u;
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,12 @@ const uint32_t* heap_hist_bucket_limits(void);
uint32_t heap_hist_bucket_count(void);
int heap_check_integrity(struct heap_integrity_report* out_report);

#ifdef HEAP_ENABLE_TEST_HOOKS
int heap_debug_seed_chain(const uint32_t* sizes, const uint8_t* free_flags, uint32_t count);
void heap_debug_corrupt_magic(uint32_t index);
void heap_debug_misalign_size(uint32_t index);
void heap_debug_make_next_regression(uint32_t index);
void heap_debug_clear_chain(void);
#endif

#endif
93 changes: 93 additions & 0 deletions kernel/tests/heap_integrity_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <stdint.h>
#include <stdio.h>

#define HEAP_ENABLE_TEST_HOOKS
#include "../src/heap.h"

static int expect_u32(const char* name, uint32_t actual, uint32_t expected) {
if (actual != expected) {
printf("FAIL: %s (actual=%u expected=%u)\n", name, actual, expected);
return 0;
}

printf("PASS: %s\n", name);
return 1;
}

static int expect_true(const char* name, int value) {
if (!value) {
printf("FAIL: %s\n", name);
return 0;
}

printf("PASS: %s\n", name);
return 1;
}

int main(void) {
int ok = 1;

{
uint32_t sizes[] = {32u, 64u, 128u};
uint8_t frees[] = {0u, 1u, 0u};
ok &= expect_true("seed valid chain", heap_debug_seed_chain(sizes, frees, 3u));

struct heap_integrity_report report;
int pass = heap_check_integrity(&report);
ok &= expect_true("valid chain integrity pass", pass);
ok &= expect_u32("valid corrupted headers", report.corrupted_headers, 0u);
ok &= expect_u32("valid split align", report.split_alignment_issues, 0u);
ok &= expect_u32("valid unmerged free pairs", report.adjacent_unmerged_free_pairs, 0u);
ok &= expect_u32("valid next regressions", report.next_pointer_regressions, 0u);
}

{
uint32_t sizes[] = {32u, 64u};
uint8_t frees[] = {0u, 0u};
ok &= expect_true("seed for magic corruption", heap_debug_seed_chain(sizes, frees, 2u));
heap_debug_corrupt_magic(1u);

struct heap_integrity_report report;
int pass = heap_check_integrity(&report);
ok &= expect_true("magic corruption detected", !pass);
ok &= expect_u32("magic corrupted headers count", report.corrupted_headers, 1u);
}

{
uint32_t sizes[] = {32u, 64u};
uint8_t frees[] = {0u, 0u};
ok &= expect_true("seed for misalign", heap_debug_seed_chain(sizes, frees, 2u));
heap_debug_misalign_size(0u);

struct heap_integrity_report report;
int pass = heap_check_integrity(&report);
ok &= expect_true("misalign detected", !pass);
ok &= expect_u32("misalign count", report.split_alignment_issues, 1u);
}

{
uint32_t sizes[] = {32u, 64u};
uint8_t frees[] = {1u, 1u};
ok &= expect_true("seed for unmerged pair", heap_debug_seed_chain(sizes, frees, 2u));

struct heap_integrity_report report;
int pass = heap_check_integrity(&report);
ok &= expect_true("unmerged pair detected", !pass);
ok &= expect_u32("unmerged free pair count", report.adjacent_unmerged_free_pairs, 1u);
}

{
uint32_t sizes[] = {32u, 64u, 96u};
uint8_t frees[] = {0u, 0u, 0u};
ok &= expect_true("seed for next regression", heap_debug_seed_chain(sizes, frees, 3u));
heap_debug_make_next_regression(2u);

struct heap_integrity_report report;
int pass = heap_check_integrity(&report);
ok &= expect_true("next regression detected", !pass);
ok &= expect_u32("next regression count", report.next_pointer_regressions, 1u);
}

heap_debug_clear_chain();
return ok ? 0 : 1;
}
24 changes: 24 additions & 0 deletions kernel/tests/pmm_stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdint.h>

#include "../src/pmm.h"

void pmm_initialize(uint32_t multiboot_magic, const struct multiboot_info* mbi) {
(void)multiboot_magic;
(void)mbi;
}

uint32_t pmm_alloc_frame(void) {
return 0u;
}

void pmm_free_frame(uint32_t physical_addr) {
(void)physical_addr;
}

struct pmm_stats pmm_get_stats(void) {
struct pmm_stats stats;
stats.total_frames = 0u;
stats.used_frames = 0u;
stats.free_frames = 0u;
return stats;
}
11 changes: 8 additions & 3 deletions site/docs.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ <h2>Architecture Diagram</h2>

<rect x="360" y="60" width="260" height="110" rx="10" class="d-box d-core" />
<text x="380" y="95" class="d-title">Kernel Core</text>
<text x="380" y="122" class="d-text">kernel_main, shell, memmap</text>
<text x="380" y="122" class="d-text">kernel_main, shell, memmap, heapcheck</text>
<text x="380" y="145" class="d-text">version + command dispatch</text>

<rect x="660" y="60" width="260" height="110" rx="10" class="d-box d-display" />
Expand Down Expand Up @@ -213,7 +213,8 @@ <h2>Build, Test, Release</h2>
<div class="split">
<div class="code-box">
<h3>Local Build</h3>
<pre><code>make -C kernel all CROSS_COMPILE=
<pre><code>make -C kernel test
make -C kernel all CROSS_COMPILE=
make -C kernel iso CROSS_COMPILE=
qemu-system-i386 -cdrom kernel/build/kernel.iso</code></pre>
</div>
Expand Down Expand Up @@ -272,7 +273,11 @@ <h2>Source Map</h2>
</tr>
<tr>
<td class="mono">kernel/src/heap.c</td>
<td>Kernel heap allocator (`kmalloc`/`kfree`) with fragmentation stats, size histogram telemetry, and leak-trace reporting</td>
<td>Kernel heap allocator (`kmalloc`/`kfree`) with integrity checks, fragmentation stats, size histogram telemetry, and leak-trace reporting</td>
</tr>
<tr>
<td class="mono">kernel/src/heap_diag.c</td>
<td>Heap diagnostics telemetry backend for counters, histograms, and allocation trace snapshots</td>
</tr>
<tr>
<td class="mono">kernel/src/stats_util.c</td>
Expand Down
10 changes: 7 additions & 3 deletions site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1>Project SigmaBoot <span class="alpha-badge">ALPHA</span></h1>
<p class="warning-note"><strong>Warning:</strong> Experimental alpha software. Features and behavior may change without notice.</p>
<div class="cta-row">
<a class="btn btn-primary" href="#run">Run It</a>
<a class="btn btn-ghost" href="#release" id="download-latest-btn">Download v0.0.20260331</a>
<a class="btn btn-ghost" href="#release" id="download-latest-btn">Download v0.0.20260331.1</a>
<a class="btn btn-ghost" href="docs.html">Read Docs</a>
</div>
<div class="terminal-glimpse" aria-label="Terminal preview">
Expand Down Expand Up @@ -115,7 +115,7 @@ <h2>Release Pipeline</h2>
then attaches downloadable artifacts to each published release.
</p>
<ul>
<li>Tag used: v0.0.20260331</li>
<li>Tag used: v0.0.20260331.1</li>
<li>CI artifacts: workflow run downloads</li>
<li>Release assets: direct downloads for users</li>
</ul>
Expand Down Expand Up @@ -203,7 +203,11 @@ <h2>Roadmap</h2>
</div>
<div class="point">
<span></span>
<p><strong>Next:</strong> add allocator corruption injection tests for negative-path validation of integrity diagnostics.</p>
<p><strong>Done:</strong> allocator corruption injection tests added for negative-path validation of integrity diagnostics.</p>
</div>
<div class="point">
<span></span>
<p><strong>Next:</strong> expose integrity fault details in a compact shell diagnostics summary command for faster triage.</p>
</div>
</div>
</section>
Expand Down
Loading