From ca314eaeef2f818c9c60979f22409c087cc625c6 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:53:59 +0100 Subject: [PATCH 01/11] kernel: add Flow-owned base kernel entry --- kernel/x86_64/kernel.flow | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 kernel/x86_64/kernel.flow diff --git a/kernel/x86_64/kernel.flow b/kernel/x86_64/kernel.flow new file mode 100644 index 000000000..2ce1057c1 --- /dev/null +++ b/kernel/x86_64/kernel.flow @@ -0,0 +1,74 @@ +# Flow base kernel core. +# +# Phase one deliberately keeps the architecture shim tiny: Flow owns boot +# validation and kernel policy; the shim owns privileged CPU/serial operations. + +@cEmbed(" +#include + +static inline void flow_kernel_outb(uint16_t port, uint8_t value) { + __asm__ volatile (\"outb %0, %1\" : : \"a\"(value), \"Nd\"(port)); +} + +void flow_kernel_serial_init(void) { + flow_kernel_outb(0x3f8 + 1, 0x00); + flow_kernel_outb(0x3f8 + 3, 0x80); + flow_kernel_outb(0x3f8 + 0, 0x03); + flow_kernel_outb(0x3f8 + 1, 0x00); + flow_kernel_outb(0x3f8 + 3, 0x03); + flow_kernel_outb(0x3f8 + 2, 0xc7); + flow_kernel_outb(0x3f8 + 4, 0x0b); +} + +void flow_kernel_serial_write(const char* text) { + while (*text) { + flow_kernel_outb(0x3f8, (uint8_t)*text++); + } +} + +__attribute__((noreturn)) void flow_kernel_halt(void) { + for (;;) { + __asm__ volatile (\"cli; hlt\"); + } +} +") + +extern { + function flow_kernel_serial_init() -> void + function flow_kernel_serial_write(text: string) -> void + function flow_kernel_halt() -> void +} + +export function kernel_abi_version() -> u32 { + return 1 +} + +export function kernel_page_size() -> u64 { + return 4096 +} + +export function kernel_boot_magic_valid(magic: u32) -> bool { + return magic == 920085129 +} + +export function kernel_page_count(bytes: u64) -> u64 { + return (bytes + 4095) / 4096 +} + +export function kernel_main(multiboot_magic: u32, multiboot_info: ptr) -> i32 { + flow_kernel_serial_init() + flow_kernel_serial_write("Flow kernel: entry\n") + + if not kernel_boot_magic_valid(multiboot_magic) { + flow_kernel_serial_write("Flow kernel: invalid Multiboot2 magic\n") + return 1 + } + + if multiboot_info == null { + flow_kernel_serial_write("Flow kernel: missing Multiboot2 info\n") + return 2 + } + + flow_kernel_serial_write("Flow kernel: boot contract accepted\n") + return 0 +} From 6facf481ff515dbf86c496cae29832a52f1fceb1 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:54:29 +0100 Subject: [PATCH 02/11] kernel: add Multiboot2 x86_64 bootstrap --- kernel/x86_64/boot.S | 116 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 kernel/x86_64/boot.S diff --git a/kernel/x86_64/boot.S b/kernel/x86_64/boot.S new file mode 100644 index 000000000..8fa46df50 --- /dev/null +++ b/kernel/x86_64/boot.S @@ -0,0 +1,116 @@ +.section .multiboot,"a" +.align 8 +multiboot_header: + .long 0xe85250d6 + .long 0 + .long multiboot_header_end - multiboot_header + .long -(0xe85250d6 + 0 + (multiboot_header_end - multiboot_header)) + .short 0 + .short 0 + .long 8 +multiboot_header_end: + +.section .boot.data,"aw" +.align 8 +boot_magic: + .long 0 +boot_info: + .long 0 + +.align 4096 +pml4: + .skip 4096 +.align 4096 +pdpt: + .skip 4096 +.align 4096 +pd: + .skip 4096 + +.section .boot.bss,"aw",@nobits +.align 16 +stack_bottom: + .skip 65536 +stack_top: + +.section .boot.text,"ax" +.code32 +.global _start +.type _start, @function +_start: + cli + movl %eax, boot_magic + movl %ebx, boot_info + movl $stack_top, %esp + + movl $pdpt, %eax + orl $0x3, %eax + movl %eax, pml4 + + movl $pd, %eax + orl $0x3, %eax + movl %eax, pdpt + + xorl %ecx, %ecx +1: + movl %ecx, %eax + shll $21, %eax + orl $0x83, %eax + movl %eax, pd(,%ecx,8) + movl $0, pd+4(,%ecx,8) + incl %ecx + cmpl $512, %ecx + jne 1b + + movl %cr4, %eax + orl $(1 << 5), %eax + movl %eax, %cr4 + + movl $pml4, %eax + movl %eax, %cr3 + + movl $0xc0000080, %ecx + rdmsr + orl $(1 << 8), %eax + wrmsr + + movl %cr0, %eax + orl $(1 << 31), %eax + movl %eax, %cr0 + + lgdt gdt64_ptr + ljmp $0x08, $long_mode_start + +.code64 +long_mode_start: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + xorw %ax, %ax + movw %ax, %fs + movw %ax, %gs + + movq $stack_top, %rsp + xorq %rbp, %rbp + + movl boot_magic(%rip), %edi + movl boot_info(%rip), %esi + call flow_export_kernel_main + +2: + cli + hlt + jmp 2b +.size _start, . - _start + +.align 8 +gdt64: + .quad 0x0000000000000000 + .quad 0x00af9a000000ffff + .quad 0x00cf92000000ffff +gdt64_end: + +gdt64_ptr: + .word gdt64_end - gdt64 - 1 + .long gdt64 From ee51a1ac9ce0a06c4ad7990e1dcba8152a8d73e8 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:54:38 +0100 Subject: [PATCH 03/11] kernel: add freestanding linker layout --- kernel/x86_64/linker.ld | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 kernel/x86_64/linker.ld diff --git a/kernel/x86_64/linker.ld b/kernel/x86_64/linker.ld new file mode 100644 index 000000000..7a3dcc0fb --- /dev/null +++ b/kernel/x86_64/linker.ld @@ -0,0 +1,56 @@ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) + +SECTIONS +{ + . = 1M; + + .multiboot ALIGN(8) : + { + KEEP(*(.multiboot)) + } + + .boot.text ALIGN(4K) : + { + *(.boot.text) + } + + .boot.data ALIGN(4K) : + { + *(.boot.data) + } + + .boot.bss ALIGN(4K) (NOLOAD) : + { + *(.boot.bss) + } + + .text ALIGN(4K) : + { + *(.text .text.*) + } + + .rodata ALIGN(4K) : + { + *(.rodata .rodata.*) + } + + .data ALIGN(4K) : + { + *(.data .data.*) + } + + .bss ALIGN(4K) (NOLOAD) : + { + *(COMMON) + *(.bss .bss.*) + } + + /DISCARD/ : + { + *(.comment) + *(.eh_frame) + *(.note .note.*) + } +} From 8bc312131af614f33762aa668bdeed955644e2b3 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:54:53 +0100 Subject: [PATCH 04/11] kernel: add freestanding build pipeline --- kernel/x86_64/build.sh | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 kernel/x86_64/build.sh diff --git a/kernel/x86_64/build.sh b/kernel/x86_64/build.sh new file mode 100644 index 000000000..4b03a1863 --- /dev/null +++ b/kernel/x86_64/build.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "$HERE/../.." && pwd)" +BUILD="${1:-$HERE/build}" + +mkdir -p "$BUILD" + +"$ROOT/flow" transpile "$HERE/kernel.flow" \ + --c \ + --export kernel_main kernel_abi_version kernel_page_size kernel_boot_magic_valid kernel_page_count \ + -o "$BUILD/kernel.c" + +clang \ + -target x86_64-unknown-none-elf \ + -std=c11 \ + -ffreestanding \ + -fno-builtin \ + -fno-stack-protector \ + -fno-pic \ + -mno-red-zone \ + -ffunction-sections \ + -fdata-sections \ + -O2 \ + -c "$BUILD/kernel.c" \ + -o "$BUILD/kernel-flow.o" + +clang \ + -target x86_64-unknown-none-elf \ + -ffreestanding \ + -fno-pic \ + -mno-red-zone \ + -c "$HERE/boot.S" \ + -o "$BUILD/boot.o" + +ld.lld \ + -nostdlib \ + --gc-sections \ + -T "$HERE/linker.ld" \ + "$BUILD/boot.o" \ + "$BUILD/kernel-flow.o" \ + -o "$BUILD/flow-kernel.elf" + +if command -v grub-file >/dev/null 2>&1; then + grub-file --is-x86-multiboot2 "$BUILD/flow-kernel.elf" +fi + +printf '%s\n' "$BUILD/flow-kernel.elf" From 9faeb49d4d9bce73b7ff0a6abcb6fa126baf1e9c Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:12 +0100 Subject: [PATCH 05/11] kernel: make page count overflow safe --- kernel/x86_64/kernel.flow | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/x86_64/kernel.flow b/kernel/x86_64/kernel.flow index 2ce1057c1..0b027d749 100644 --- a/kernel/x86_64/kernel.flow +++ b/kernel/x86_64/kernel.flow @@ -52,7 +52,10 @@ export function kernel_boot_magic_valid(magic: u32) -> bool { } export function kernel_page_count(bytes: u64) -> u64 { - return (bytes + 4095) / 4096 + if bytes == 0 { + return 0 + } + return ((bytes - 1) / 4096) + 1 } export function kernel_main(multiboot_magic: u32, multiboot_info: ptr) -> i32 { From 9081763cc6b661b0a5f7008889978143d19a687b Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:18 +0100 Subject: [PATCH 06/11] kernel: add GRUB boot configuration --- kernel/x86_64/grub.cfg | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 kernel/x86_64/grub.cfg diff --git a/kernel/x86_64/grub.cfg b/kernel/x86_64/grub.cfg new file mode 100644 index 000000000..bc1d8ac0c --- /dev/null +++ b/kernel/x86_64/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "Flow kernel" { + multiboot2 /boot/flow-kernel.elf + boot +} From e85b5d609c2158adfece019307bc628b8e828dbb Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:26 +0100 Subject: [PATCH 07/11] kernel: add QEMU boot runner --- kernel/x86_64/run.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 kernel/x86_64/run.sh diff --git a/kernel/x86_64/run.sh b/kernel/x86_64/run.sh new file mode 100644 index 000000000..2e43f4dd8 --- /dev/null +++ b/kernel/x86_64/run.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BUILD="${1:-$HERE/build}" +ISO_ROOT="$BUILD/isofiles" + +command -v grub-mkrescue >/dev/null 2>&1 || { + echo "grub-mkrescue is required" >&2 + exit 1 +} +command -v qemu-system-x86_64 >/dev/null 2>&1 || { + echo "qemu-system-x86_64 is required" >&2 + exit 1 +} + +"$HERE/build.sh" "$BUILD" + +rm -rf "$ISO_ROOT" +mkdir -p "$ISO_ROOT/boot/grub" +cp "$BUILD/flow-kernel.elf" "$ISO_ROOT/boot/flow-kernel.elf" +cp "$HERE/grub.cfg" "$ISO_ROOT/boot/grub/grub.cfg" + +grub-mkrescue -o "$BUILD/flow-kernel.iso" "$ISO_ROOT" >/dev/null 2>&1 + +exec qemu-system-x86_64 \ + -cdrom "$BUILD/flow-kernel.iso" \ + -serial stdio \ + -display none \ + -no-reboot \ + -no-shutdown From 971733472cb99a266f36b848a1e1f94069e92dad Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:38 +0100 Subject: [PATCH 08/11] kernel: run build script portably --- kernel/x86_64/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/x86_64/run.sh b/kernel/x86_64/run.sh index 2e43f4dd8..800c3ba15 100644 --- a/kernel/x86_64/run.sh +++ b/kernel/x86_64/run.sh @@ -14,7 +14,7 @@ command -v qemu-system-x86_64 >/dev/null 2>&1 || { exit 1 } -"$HERE/build.sh" "$BUILD" +bash "$HERE/build.sh" "$BUILD" rm -rf "$ISO_ROOT" mkdir -p "$ISO_ROOT/boot/grub" From 7bf2d67711643f9d6fe99201aa85518835b75b33 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:51 +0100 Subject: [PATCH 09/11] kernel: document base kernel architecture --- kernel/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 kernel/README.md diff --git a/kernel/README.md b/kernel/README.md new file mode 100644 index 000000000..2ed0437df --- /dev/null +++ b/kernel/README.md @@ -0,0 +1,23 @@ +# Flow kernel + +This directory is the freestanding kernel substrate for Flow. The first target is x86_64 booted through Multiboot2. Flow owns the kernel entry contract and policy-facing primitives; the architecture layer is restricted to the CPU operations that cannot be expressed portably. + +The current base boots in 32-bit Multiboot2 mode, establishes an identity-mapped 1 GiB long-mode address space with 2 MiB pages, enters x86_64 long mode, installs a 64 KiB kernel stack, and calls the stable Flow C ABI entry `flow_export_kernel_main`. The Flow entry validates the Multiboot2 contract and reports boot state over COM1 serial. + +Build the ELF with: + +```bash +bash kernel/x86_64/build.sh +``` + +The build requires Flow's normal transpiler dependencies plus `clang` and `ld.lld`. If `grub-file` is installed, the build also validates the resulting ELF as Multiboot2. + +Boot it in QEMU with: + +```bash +bash kernel/x86_64/run.sh +``` + +That additionally requires `grub-mkrescue` and `qemu-system-x86_64`. Successful boot reaches the serial message `Flow kernel: boot contract accepted`. + +The next kernel layers should remain above this boundary: Multiboot2 memory-map ingestion, a physical page allocator, interrupt/exception tables, timer-driven scheduling, syscall entry, virtual memory ownership, and then the eBPF verifier/interpreter/JIT hooks. eBPF should consume explicit kernel hook surfaces rather than becoming part of the boot substrate. From 3dbb6874a5365c59c52ddb2e8678877400a1f132 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 12:55:57 +0100 Subject: [PATCH 10/11] kernel: add base kernel parser regression --- tests/unit/test_kernel_base.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/unit/test_kernel_base.py diff --git a/tests/unit/test_kernel_base.py b/tests/unit/test_kernel_base.py new file mode 100644 index 000000000..9a18d797d --- /dev/null +++ b/tests/unit/test_kernel_base.py @@ -0,0 +1,17 @@ +from pathlib import Path + +from flow.parser import parse_flow_code + + +ROOT = Path(__file__).resolve().parents[2] +KERNEL = ROOT / "kernel" / "x86_64" / "kernel.flow" + + +def test_base_kernel_parses_as_flow() -> None: + source = KERNEL.read_text() + declarations = parse_flow_code(source) + + assert declarations + assert "export function kernel_main" in source + assert "export function kernel_page_count" in source + assert "@cEmbed" in source From 3c8a5ca81c27b70bfc013a0b1132811c72dd2d09 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:02:00 +0100 Subject: [PATCH 11/11] ci: verify Flow base kernel build and boot --- .github/workflows/kernel.yml | 117 +++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .github/workflows/kernel.yml diff --git a/.github/workflows/kernel.yml b/.github/workflows/kernel.yml new file mode 100644 index 000000000..21ff6f642 --- /dev/null +++ b/.github/workflows/kernel.yml @@ -0,0 +1,117 @@ +name: Kernel CI + +on: + push: + branches: [main, master] + paths: + - 'kernel/**' + - 'src/**' + - 'compiler/**' + - 'flow' + - 'requirements.txt' + - 'requirements.lock' + - 'pyproject.toml' + - '.github/actions/**' + - '.github/workflows/kernel.yml' + pull_request: + branches: [main, master] + paths: + - 'kernel/**' + - 'src/**' + - 'compiler/**' + - 'flow' + - 'requirements.txt' + - 'requirements.lock' + - 'pyproject.toml' + - '.github/actions/**' + - '.github/workflows/kernel.yml' + workflow_dispatch: + +concurrency: + group: kernel-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + kernel: + name: x86_64 freestanding kernel + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v7 + + - uses: ./.github/actions/setup-python + + - name: Install freestanding and boot-test toolchain + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + clang \ + lld \ + grub-common \ + grub-pc-bin \ + xorriso \ + qemu-system-x86 + + - name: Parse kernel source + env: + PYTHONPATH: src + run: pytest tests/unit/test_kernel_base.py -v + + - name: Build freestanding x86_64 ELF + env: + PYTHONPATH: src + FLOW_HOST: python + run: | + chmod +x ./flow kernel/x86_64/build.sh + kernel/x86_64/build.sh /tmp/flow-kernel-build + test -s /tmp/flow-kernel-build/flow-kernel.elf + grub-file --is-x86-multiboot2 /tmp/flow-kernel-build/flow-kernel.elf + llvm-readelf -h /tmp/flow-kernel-build/flow-kernel.elf + llvm-nm /tmp/flow-kernel-build/flow-kernel.elf | grep -F 'flow_export_kernel_main' + + - name: Build bootable GRUB image + run: | + mkdir -p /tmp/flow-kernel-iso/boot/grub + cp /tmp/flow-kernel-build/flow-kernel.elf /tmp/flow-kernel-iso/boot/flow-kernel.elf + cp kernel/x86_64/grub.cfg /tmp/flow-kernel-iso/boot/grub/grub.cfg + grub-mkrescue -o /tmp/flow-kernel.iso /tmp/flow-kernel-iso + test -s /tmp/flow-kernel.iso + + - name: Boot smoke under QEMU + run: | + set +e + timeout 10s qemu-system-x86_64 \ + -machine accel=tcg \ + -m 128M \ + -cdrom /tmp/flow-kernel.iso \ + -serial file:/tmp/flow-kernel-serial.log \ + -display none \ + -no-reboot \ + -no-shutdown + rc=$? + set -e + + cat /tmp/flow-kernel-serial.log + if [[ "$rc" -ne 0 && "$rc" -ne 124 ]]; then + echo "QEMU exited unexpectedly with status $rc" >&2 + exit "$rc" + fi + + grep -F 'Flow kernel: entry' /tmp/flow-kernel-serial.log + grep -F 'Flow kernel: boot contract accepted' /tmp/flow-kernel-serial.log + + - name: Upload kernel artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: flow-kernel-x86_64 + path: | + /tmp/flow-kernel-build/flow-kernel.elf + /tmp/flow-kernel.iso + /tmp/flow-kernel-serial.log + if-no-files-found: warn + retention-days: 7