From 46fba09d849110b097d85ee4c07a053c4459ef03 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:22:10 +0100 Subject: [PATCH 01/64] Rebase Flow kernel on Tiny Core Linux --- README.md | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 233d51f..8006ca9 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,45 @@ # Flow Kernel -A freestanding kernel written in Flow. +Flow systems integration on top of a deliberately tiny Linux base. -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 CPU operations that cannot yet be expressed portably in Flow. +`flow-kernel` no longer implements its own bootloader, page tables, scheduler, interrupt subsystem, or virtual-memory manager. Those are Linux responsibilities. The base target is Tiny Core Linux CorePure64: a minimal command-line Linux system that gives Flow a mature x86_64 kernel, drivers, networking, processes, namespaces, cgroups, perf and the native Linux eBPF surface without dragging in a conventional desktop distribution. -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. +## Architecture -## Build +```text +Linux kernel + ↑ +Tiny Core CorePure64 userspace + ↑ +Flow system services / kernel-facing components + ↑ +Flow eBPF, XDP, tracing and driver experiments +``` + +Tiny Core is the substrate, not a fork. We consume its `vmlinuz64` and `corepure64.gz` release artifacts directly. + +## Fetch the Tiny Core base -The kernel consumes the Flow compiler as an external dependency. Set `FLOW` to the Flow driver you want to use, or place a sibling checkout at `../flow`. +The default is the pinned CorePure64 17.0 release. Override `TC_MAJOR` and `TC_VERSION` when intentionally moving the base. ```bash -git clone https://github.com/flooooooooooow/flow.git ../flow -FLOW=../flow/flow bash x86_64/build.sh +bash tinycore/fetch.sh ``` -The build requires Flow's normal transpiler dependencies plus `clang` and `ld.lld`. If `grub-file` is installed, the resulting ELF is also validated as Multiboot2. +Artifacts are placed under `build/tinycore/`. -## Boot +## Boot it ```bash -FLOW=../flow/flow bash x86_64/run.sh +bash tinycore/run.sh ``` -That additionally requires `grub-mkrescue` and `qemu-system-x86_64`. Successful boot reaches the serial message `Flow kernel: boot contract accepted`. +This boots the Tiny Core Linux kernel and initramfs directly in QEMU with the serial console attached to the terminal. No GRUB image and no Flow-owned architecture bootstrap are involved. + +## Flow compiler + +Flow remains a separate dependency. Kernel-facing Flow programs in this repository should compile against Linux ABIs or to eBPF; the language/compiler belongs in `flooooooooooow/flow` and is checked out independently in CI. ## Roadmap -The next layers are 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. +The next work is deliberately Linux-native: add a Flow-to-eBPF target, BTF-aware bindings, maps, verifier-safe helpers, tracepoint/kprobe hooks, XDP, TC hooks and eventually CO-RE-style relocatable programs. User-space Flow services can remain tiny and run directly on CorePure64. From 730b1a3385499f2450f338f98c176ddba0404515 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:22:21 +0100 Subject: [PATCH 02/64] Add Tiny Core base fetcher --- tinycore/fetch.sh | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tinycore/fetch.sh diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh new file mode 100644 index 0000000..d8ae45a --- /dev/null +++ b/tinycore/fetch.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +TC_MAJOR="${TC_MAJOR:-17.x}" +TC_VERSION="${TC_VERSION:-17.0}" +OUT="${1:-$ROOT/build/tinycore}" +BASE_URL="https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" + +mkdir -p "$OUT" + +fetch() +{ + local name="$1" + local url="$BASE_URL/$name" + local dst="$OUT/$name" + + if [[ -s "$dst" ]]; then + printf 'Using cached %s\n' "$dst" + return + fi + + printf 'Fetching %s\n' "$url" + curl --fail --location --retry 3 --output "$dst.part" "$url" + mv "$dst.part" "$dst" +} + +fetch vmlinuz64 +fetch corepure64.gz + +printf 'Tiny Core CorePure64 %s base ready in %s\n' "$TC_VERSION" "$OUT" +printf 'Kernel: %s\n' "$OUT/vmlinuz64" +printf 'Initramfs: %s\n' "$OUT/corepure64.gz" From 1f058fc33153408806a8a96705d7a6488faeeb6e Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:22:32 +0100 Subject: [PATCH 03/64] Add Tiny Core QEMU runner --- tinycore/run.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tinycore/run.sh diff --git a/tinycore/run.sh b/tinycore/run.sh new file mode 100644 index 0000000..bdb1d51 --- /dev/null +++ b/tinycore/run.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BUILD="${1:-$ROOT/build/tinycore}" + +if [[ ! -s "$BUILD/vmlinuz64" || ! -s "$BUILD/corepure64.gz" ]]; then + bash "$ROOT/tinycore/fetch.sh" "$BUILD" +fi + +if ! command -v qemu-system-x86_64 >/dev/null 2>&1; then + echo 'qemu-system-x86_64 is required' >&2 + exit 1 +fi + +exec qemu-system-x86_64 \ + -machine accel=tcg \ + -cpu max \ + -m "${FLOW_KERNEL_RAM:-256M}" \ + -kernel "$BUILD/vmlinuz64" \ + -initrd "$BUILD/corepure64.gz" \ + -append "console=ttyS0 quiet ${FLOW_KERNEL_CMDLINE:-}" \ + -nographic \ + -no-reboot From 1480a06d8bbed8018a13c5faa41e8d9ca01b6678 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:22:52 +0100 Subject: [PATCH 04/64] Switch CI to Tiny Core Linux boot substrate --- .github/workflows/ci.yml | 82 +++++++++++++++------------------------- 1 file changed, 31 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f8316b..af61071 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,87 +15,67 @@ permissions: contents: read jobs: - x86_64: - name: x86_64 freestanding boot + tinycore-x86_64: + name: Tiny Core CorePure64 boot runs-on: ubuntu-latest timeout-minutes: 15 steps: - - name: Checkout kernel + - name: Checkout Flow kernel integration uses: actions/checkout@v7 - - name: Checkout Flow compiler - uses: actions/checkout@v7 - with: - repository: flooooooooooow/flow - path: flow - - - name: Set up Flow Python environment - uses: ./flow/.github/actions/setup-python - - - name: Install freestanding and boot-test toolchain + - name: Install boot-test tools run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ - clang \ - lld \ - grub-common \ - grub-pc-bin \ - xorriso \ + curl \ + file \ qemu-system-x86 - - name: Build freestanding x86_64 ELF - env: - FLOW: ${{ github.workspace }}/flow/flow - FLOW_HOST: python - PYTHONPATH: ${{ github.workspace }}/flow/src + - name: Fetch Tiny Core Linux base run: | - chmod +x "$FLOW" x86_64/build.sh - bash 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' + bash tinycore/fetch.sh /tmp/tinycore + test -s /tmp/tinycore/vmlinuz64 + test -s /tmp/tinycore/corepure64.gz + file /tmp/tinycore/vmlinuz64 + gzip -t /tmp/tinycore/corepure64.gz - - 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 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 + - name: Boot Tiny Core kernel under QEMU run: | set +e - timeout 10s qemu-system-x86_64 \ + timeout 20s qemu-system-x86_64 \ -machine accel=tcg \ - -m 128M \ - -cdrom /tmp/flow-kernel.iso \ - -serial file:/tmp/flow-kernel-serial.log \ + -cpu max \ + -m 256M \ + -kernel /tmp/tinycore/vmlinuz64 \ + -initrd /tmp/tinycore/corepure64.gz \ + -append 'console=ttyS0' \ + -serial file:/tmp/tinycore-serial.log \ -display none \ -no-reboot \ -no-shutdown rc=$? set -e - cat /tmp/flow-kernel-serial.log + cat /tmp/tinycore-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 + grep -F 'Linux version' /tmp/tinycore-serial.log + + - name: Verify Flow compiler remains external + run: | + git clone --depth 1 https://github.com/flooooooooooow/flow.git /tmp/flow + test -x /tmp/flow/flow + test ! -e ./flow - - name: Upload kernel artifacts + - name: Upload boot log 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 + name: tinycore-x86_64-boot + path: /tmp/tinycore-serial.log if-no-files-found: warn retention-days: 7 From 06ac394e02cea2a28aadc362fe6ca81e0ce6ca1d Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:02 +0100 Subject: [PATCH 05/64] Remove bespoke x86_64 boot path --- x86_64/boot.S | 116 -------------------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 x86_64/boot.S diff --git a/x86_64/boot.S b/x86_64/boot.S deleted file mode 100644 index 8fa46df..0000000 --- a/x86_64/boot.S +++ /dev/null @@ -1,116 +0,0 @@ -.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 cbe05e8827e14886e691263776fcd39837aa36ec Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:11 +0100 Subject: [PATCH 06/64] Remove bespoke freestanding build path --- x86_64/build.sh | 57 ------------------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 x86_64/build.sh diff --git a/x86_64/build.sh b/x86_64/build.sh deleted file mode 100644 index 7108796..0000000 --- a/x86_64/build.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -BUILD="${1:-$HERE/build}" -FLOW="${FLOW:-$HERE/../../flow/flow}" - -if [[ ! -x "$FLOW" ]]; then - echo "Flow compiler not found or not executable: $FLOW" >&2 - echo "Set FLOW=/path/to/flow/flow or place a sibling checkout at ../flow." >&2 - exit 1 -fi - -mkdir -p "$BUILD" - -"$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 \ - -fno-pie \ - -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 \ - -fno-pie \ - -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 036f9334e7cda7915a4170cd0dc04fa6a2d8097d Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:19 +0100 Subject: [PATCH 07/64] Remove bespoke GRUB configuration --- x86_64/grub.cfg | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 x86_64/grub.cfg diff --git a/x86_64/grub.cfg b/x86_64/grub.cfg deleted file mode 100644 index d3244a9..0000000 --- a/x86_64/grub.cfg +++ /dev/null @@ -1,7 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "Flow Kernel" { - multiboot2 /boot/flow-kernel.elf - boot -} From f9886ea45b431324ea22bdfcaa723846e81896e3 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:25 +0100 Subject: [PATCH 08/64] Remove bespoke Flow kernel entry --- x86_64/kernel.flow | 77 ---------------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 x86_64/kernel.flow diff --git a/x86_64/kernel.flow b/x86_64/kernel.flow deleted file mode 100644 index 0b027d7..0000000 --- a/x86_64/kernel.flow +++ /dev/null @@ -1,77 +0,0 @@ -# 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 { - if bytes == 0 { - return 0 - } - return ((bytes - 1) / 4096) + 1 -} - -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 8316d7ba47bd594c8953b0337b1d255d867f5282 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:31 +0100 Subject: [PATCH 09/64] Remove bespoke x86_64 linker script --- x86_64/linker.ld | 56 ------------------------------------------------ 1 file changed, 56 deletions(-) delete mode 100644 x86_64/linker.ld diff --git a/x86_64/linker.ld b/x86_64/linker.ld deleted file mode 100644 index 7a3dcc0..0000000 --- a/x86_64/linker.ld +++ /dev/null @@ -1,56 +0,0 @@ -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 39fb810972a03c96944d2a0c721a704700fb2eb8 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:37 +0100 Subject: [PATCH 10/64] Remove bespoke x86_64 QEMU runner --- x86_64/run.sh | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 x86_64/run.sh diff --git a/x86_64/run.sh b/x86_64/run.sh deleted file mode 100644 index 085f032..0000000 --- a/x86_64/run.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -BUILD="${1:-$HERE/build}" -ISO_ROOT="$BUILD/iso" -ISO="$BUILD/flow-kernel.iso" - -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; } - -bash "$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 "$ISO" "$ISO_ROOT" - -exec qemu-system-x86_64 \ - -machine accel=tcg \ - -m 128M \ - -cdrom "$ISO" \ - -serial stdio \ - -display none \ - -no-reboot \ - -no-shutdown From 57ad7edf5d86349368b9fc39b43f37dda4e294ab Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:23:50 +0100 Subject: [PATCH 11/64] Define Linux eBPF integration target --- ebpf/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 ebpf/README.md diff --git a/ebpf/README.md b/ebpf/README.md new file mode 100644 index 0000000..9604b9a --- /dev/null +++ b/ebpf/README.md @@ -0,0 +1,18 @@ +# Flow eBPF + +Linux eBPF is the first kernel-facing execution target for Flow on the Tiny Core base. + +The implementation should lower a verifier-safe Flow subset to eBPF rather than recreate Linux kernel infrastructure. Initial scope: + +- BPF ELF emission and section metadata +- maps and map declarations +- verifier-safe scalar and pointer operations +- Linux helper bindings +- tracepoints and kprobes +- XDP programs +- TC ingress/egress hooks +- BTF type ingestion +- CO-RE-style relocations +- deterministic host-side tests against the Linux verifier + +The Tiny Core image is intentionally only the execution substrate. Compiler/backend work belongs in `flooooooooooow/flow`; this repository owns Linux integration, fixtures, boot images and end-to-end kernel tests. From dd2b757ba045b804e3501940ec3326a635c50005 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:24:04 +0100 Subject: [PATCH 12/64] Clarify Tiny Core release-line pinning --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8006ca9..adaa763 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Tiny Core is the substrate, not a fork. We consume its `vmlinuz64` and `corepure ## Fetch the Tiny Core base -The default is the pinned CorePure64 17.0 release. Override `TC_MAJOR` and `TC_VERSION` when intentionally moving the base. +The default tracks the CorePure64 `17.x` release line. Override `TC_MAJOR` when intentionally moving to another Tiny Core line. ```bash bash tinycore/fetch.sh From 290c5994729bc1a14cc59ac32579afc696d1e248 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:24:15 +0100 Subject: [PATCH 13/64] Track Tiny Core release line explicitly --- tinycore/fetch.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh index d8ae45a..a0e6ff2 100644 --- a/tinycore/fetch.sh +++ b/tinycore/fetch.sh @@ -3,7 +3,6 @@ set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TC_MAJOR="${TC_MAJOR:-17.x}" -TC_VERSION="${TC_VERSION:-17.0}" OUT="${1:-$ROOT/build/tinycore}" BASE_URL="https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" @@ -28,6 +27,6 @@ fetch() fetch vmlinuz64 fetch corepure64.gz -printf 'Tiny Core CorePure64 %s base ready in %s\n' "$TC_VERSION" "$OUT" +printf 'Tiny Core CorePure64 %s base ready in %s\n' "$TC_MAJOR" "$OUT" printf 'Kernel: %s\n' "$OUT/vmlinuz64" printf 'Initramfs: %s\n' "$OUT/corepure64.gz" From a95e4065f0ed5ce9bcea1396b586d88163e17318 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:26:25 +0100 Subject: [PATCH 14/64] docs: add Flow Kernel landing page --- site/index.html | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 site/index.html diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..a2a6a1b --- /dev/null +++ b/site/index.html @@ -0,0 +1,148 @@ + + + + + + + Flow Kernel + + + +
+
+ +
+ +
+
+
FLOW × LINUX × TINY CORE
+

A tiny operating base for systems written in Flow.

+

Linux does the commodity kernel work. Tiny Core keeps the machine small. Flow targets the parts worth reinventing: kernel-facing services, tracing, networking, and eBPF.

+ + +
+
+
+ flow-kernel / architecture +
+
$ flow-kernel --stack
+
+Linux kernel
+    ↑
+Tiny Core CorePure64
+    ↑
+Flow systems layer
+    ├── eBPF / BTF / CO-RE
+    ├── XDP / TC
+    ├── tracing / kprobes
+    └── tiny user-space services
+
+
+ +
+
+
Linux-nativeNo custom bootloader or scheduler
+
CorePure64Minimal 64-bit Tiny Core base
+
eBPF-firstKernel-facing Flow target
+
Separate compilerFlow remains its own project
+
+
+ +
+
+ 01 / ARCHITECTURE +

Keep the kernel mature.
Make the systems layer new.

+
+ +
+
+
04
+

Linux kernel

+

Memory management, scheduling, drivers, networking, namespaces, cgroups, perf and the verifier already exist here.

+
+
+
03
+

Tiny Core

+

CorePure64 provides a deliberately small command-line userspace without turning the project into another general-purpose distro.

+
+
+
02
+

Flow systems

+

Small Linux-facing services and tooling compiled from Flow, with the language and compiler remaining independently versioned.

+
+
+
01
+

Flow eBPF

+

Verifier-safe programs, BTF-aware bindings, maps, tracing hooks, XDP and TC form the first serious kernel-facing target.

+
+
+
+ +
+
+
+ 02 / EBPF +

Don’t rebuild Linux.
Program it.

+

Flow’s kernel work starts where Linux exposes stable, optimisable attachment points.

+
+
+
01
Backend

Lower a verifier-safe Flow subset to eBPF.

+
02
BTF + helpers

Typed Linux bindings, helper declarations and map primitives.

+
03
Observability

Tracepoints, kprobes and perf/ring-buffer event transport.

+
04
Networking

XDP and TC hooks for low-latency packet programs.

+
05
Portable programs

CO-RE-style relocation against kernel BTF.

+
+
+
+ +
+
+ 03 / BOOT +

Two commands to the base system.

+
+ +
+
+ FETCH +
git clone https://github.com/flooooooooooow/flow-kernel.git
+cd flow-kernel
+bash tinycore/fetch.sh
+

Fetches the pinned Tiny Core CorePure64 kernel and initramfs into build/tinycore/.

+
+
+ RUN +
bash tinycore/run.sh
+

Boots vmlinuz64 and corepure64.gz directly under QEMU with a serial console.

+
+
+
+ +
+
+

“The base should be boring.
The layer above it shouldn’t be.

+

Flow Kernel uses Linux for solved systems problems and reserves experimentation for the interfaces where Flow can change the economics of systems programming.

+
+
+
+ +
+ +

Flow systems work on a Tiny Core Linux base.

+ Source ↗ +
+ + From e13c61d19be48a4b78ba32a317068064f18ae52e Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:26:59 +0100 Subject: [PATCH 15/64] docs: style Flow Kernel GitHub Pages site --- site/style.css | 219 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 site/style.css diff --git a/site/style.css b/site/style.css new file mode 100644 index 0000000..30a01ee --- /dev/null +++ b/site/style.css @@ -0,0 +1,219 @@ +:root { + --bg: #080a0d; + --bg-soft: #0e1116; + --panel: #11151b; + --panel-2: #151a22; + --text: #f4f7fb; + --muted: #98a2b3; + --line: rgba(255,255,255,.11); + --accent: #79f2c0; + --accent-2: #9bf7d2; + --max: 1180px; +} + +* { box-sizing: border-box; } +html { scroll-behavior: smooth; } +body { + margin: 0; + background: var(--bg); + color: var(--text); + font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + line-height: 1.5; + overflow-x: hidden; +} +body::before { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + background: + radial-gradient(circle at 14% 10%, rgba(121,242,192,.10), transparent 28rem), + radial-gradient(circle at 80% 30%, rgba(93,125,255,.08), transparent 30rem); + z-index: -2; +} +.noise { + position: fixed; + inset: 0; + pointer-events: none; + opacity: .035; + z-index: -1; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.8'/%3E%3C/svg%3E"); +} + +a { color: inherit; text-decoration: none; } +.shell { width: min(calc(100% - 40px), var(--max)); margin-inline: auto; } + +.nav { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 76px; + border-bottom: 1px solid var(--line); +} +.brand { display: flex; align-items: center; gap: 10px; font-weight: 680; letter-spacing: -.02em; } +.brand-mark { + width: 30px; + height: 30px; + display: inline-grid; + place-items: center; + border: 1px solid rgba(121,242,192,.55); + border-radius: 9px; + color: var(--accent); + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; +} +.nav-links { display: flex; align-items: center; gap: 24px; color: #c5ccd7; font-size: 14px; } +.nav-links a:not(.pill):hover { color: #fff; } +.pill { border: 1px solid var(--line); border-radius: 999px; padding: 8px 13px; background: rgba(255,255,255,.025); } + +.hero { padding: 96px 0 76px; } +.eyebrow, .section-heading > span { + color: var(--accent); + font: 700 12px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + letter-spacing: .15em; +} +h1 { + max-width: 900px; + margin: 20px 0 24px; + font-size: clamp(54px, 8vw, 108px); + line-height: .92; + letter-spacing: -.065em; + font-weight: 750; +} +h1 span { color: #9ba5b3; } +.lede { + max-width: 780px; + margin: 0; + color: #b2bbc7; + font-size: clamp(18px, 2vw, 23px); + line-height: 1.55; + letter-spacing: -.015em; +} +.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; } +.button { display: inline-flex; align-items: center; padding: 12px 17px; border-radius: 10px; font-weight: 650; font-size: 14px; } +.button.primary { background: var(--accent); color: #06100c; } +.button.primary:hover { background: var(--accent-2); } +.button.ghost { border: 1px solid var(--line); background: rgba(255,255,255,.025); color: #d6dbe3; } + +.terminal { + margin-top: 72px; + overflow: hidden; + border: 1px solid var(--line); + border-radius: 16px; + background: linear-gradient(180deg, rgba(19,24,31,.93), rgba(10,13,17,.96)); + box-shadow: 0 32px 80px rgba(0,0,0,.38); +} +.terminal-bar { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + min-height: 44px; + padding: 0 14px; + border-bottom: 1px solid var(--line); + color: #6f7a89; + font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; +} +.dots { display: flex; gap: 7px; } +.dots i { width: 8px; height: 8px; display: block; border-radius: 50%; background: #3a424f; } +.terminal pre { margin: 0; padding: 32px; overflow: auto; } +.terminal code, .code-card code { font: 14px/1.75 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } +.muted { color: #647081; } +.bright { color: #f5f7fa; } +.accent { color: var(--accent); } + +.strip { border-block: 1px solid var(--line); background: rgba(255,255,255,.018); } +.stats { display: grid; grid-template-columns: repeat(4, 1fr); } +.stats > div { padding: 27px 22px; border-right: 1px solid var(--line); } +.stats > div:first-child { padding-left: 0; } +.stats > div:last-child { border-right: 0; } +.stats strong { display: block; font-size: 15px; margin-bottom: 4px; } +.stats span { display: block; color: #7f8998; font-size: 13px; } + +.section { padding-block: 110px; } +.section-heading { margin-bottom: 46px; } +.section-heading h2 { + margin: 13px 0 0; + font-size: clamp(40px, 5vw, 67px); + line-height: .98; + letter-spacing: -.05em; +} +.section-heading.compact { margin-bottom: 0; } +.section-heading.compact p { max-width: 480px; color: #8f9aa9; font-size: 17px; } + +.architecture-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; } +.layer { + position: relative; + min-height: 260px; + padding: 30px; + border: 1px solid var(--line); + border-radius: 14px; + background: rgba(255,255,255,.025); + overflow: hidden; +} +.layer::after { + content: ""; + position: absolute; + width: 220px; + height: 220px; + border-radius: 50%; + right: -130px; + bottom: -140px; + background: var(--glow, rgba(255,255,255,.06)); + filter: blur(8px); +} +.layer.linux { --glow: rgba(125,146,255,.14); } +.layer.tiny { --glow: rgba(255,197,92,.12); } +.layer.flow { --glow: rgba(121,242,192,.14); } +.layer.ebpf { --glow: rgba(164,113,255,.14); } +.layer-index { color: #667181; font: 12px ui-monospace, monospace; } +.layer h3 { margin: 64px 0 8px; font-size: 25px; letter-spacing: -.035em; } +.layer p { max-width: 510px; margin: 0; color: #8e98a7; font-size: 15px; } + +.dark-section { background: #05070a; border-block: 1px solid var(--line); padding-block: 110px; } +.split { display: grid; grid-template-columns: .9fr 1.1fr; gap: 90px; align-items: start; } +.roadmap { border-top: 1px solid var(--line); } +.roadmap-item { display: grid; grid-template-columns: 52px 1fr; gap: 14px; padding: 22px 0; border-bottom: 1px solid var(--line); } +.roadmap-item > span { color: #596474; font: 12px ui-monospace, monospace; padding-top: 3px; } +.roadmap-item strong { font-size: 17px; } +.roadmap-item p { margin: 4px 0 0; color: #7f8997; font-size: 14px; } +.roadmap-item.active > span, .roadmap-item.active strong { color: var(--accent); } + +.code-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } +.code-card { border: 1px solid var(--line); border-radius: 14px; background: var(--panel); overflow: hidden; } +.code-label { display: block; padding: 13px 18px; border-bottom: 1px solid var(--line); color: #697484; font: 11px ui-monospace, monospace; letter-spacing: .12em; } +.code-card pre { margin: 0; padding: 24px 20px; overflow: auto; background: #0a0d11; } +.code-card p { margin: 0; padding: 18px 20px 21px; color: #8994a3; font-size: 14px; } +.code-card p code { color: #cdd4dd; } + +.manifesto { padding: 90px 0; border-top: 1px solid var(--line); background: linear-gradient(135deg, rgba(121,242,192,.045), transparent 55%); } +.quote { margin: 0; font-size: clamp(44px, 6vw, 78px); line-height: .98; letter-spacing: -.055em; font-weight: 720; } +.quote span { color: var(--accent); } +.subquote { max-width: 760px; margin: 28px 0 0; color: #8e99a7; font-size: 17px; } + +.footer { min-height: 130px; display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 36px; color: #7f8997; font-size: 13px; } +.footer > a:hover { color: #fff; } +.footer-brand { color: #d8dde5; } + +@media (max-width: 840px) { + .nav-links a:not(.pill) { display: none; } + .hero { padding-top: 68px; } + h1 { font-size: clamp(50px, 15vw, 82px); } + .stats { grid-template-columns: 1fr 1fr; } + .stats > div { border-bottom: 1px solid var(--line); } + .stats > div:nth-child(2) { border-right: 0; } + .stats > div:nth-child(3), .stats > div:nth-child(4) { border-bottom: 0; } + .stats > div:first-child { padding-left: 22px; } + .architecture-grid, .code-grid, .split { grid-template-columns: 1fr; } + .split { gap: 48px; } + .section, .dark-section { padding-block: 78px; } + .footer { grid-template-columns: 1fr; gap: 12px; padding-block: 32px; } +} + +@media (max-width: 520px) { + .shell { width: min(calc(100% - 28px), var(--max)); } + .stats { grid-template-columns: 1fr; } + .stats > div { border-right: 0; border-bottom: 1px solid var(--line) !important; padding-left: 8px !important; } + .stats > div:last-child { border-bottom: 0 !important; } + .terminal pre { padding: 22px 18px; } + .terminal code { font-size: 12px; } + .layer { min-height: 230px; } +} From 31e3e6e73ae136cb131fa0188311d4b9e23da4ac Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:27:09 +0100 Subject: [PATCH 16/64] ci: deploy Flow Kernel site to GitHub Pages --- .github/workflows/pages.yml | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/pages.yml diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..ac47bde --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,40 @@ +name: Pages + +on: + push: + branches: [main] + paths: + - 'site/**' + - '.github/workflows/pages.yml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Configure Pages + uses: actions/configure-pages@v5 + + - name: Upload site + uses: actions/upload-pages-artifact@v3 + with: + path: site + + - name: Deploy + id: deployment + uses: actions/deploy-pages@v4 From 35643ac7ee251d5fb8eff235aef3300fdee083be Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:41:12 +0100 Subject: [PATCH 17/64] Harden Tiny Core artifact fetch and verification --- tinycore/fetch.sh | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh index a0e6ff2..9d1aa7c 100644 --- a/tinycore/fetch.sh +++ b/tinycore/fetch.sh @@ -3,6 +3,8 @@ set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TC_MAJOR="${TC_MAJOR:-17.x}" +TC_VERSION="${TC_VERSION:-17.0}" +TC_KERNEL="${TC_KERNEL:-6.18.2-tinycore64}" OUT="${1:-$ROOT/build/tinycore}" BASE_URL="https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" @@ -20,13 +22,43 @@ fetch() fi printf 'Fetching %s\n' "$url" - curl --fail --location --retry 3 --output "$dst.part" "$url" + if ! curl --fail --location --retry 3 --retry-all-errors --output "$dst.part" "$url"; then + rm -f "$dst.part" + printf 'Tiny Core artifact unavailable: %s\n' "$url" >&2 + exit 1 + fi mv "$dst.part" "$dst" } +verify_md5() +{ + local name="$1" + local sum_file="$OUT/$name.md5.txt" + + fetch "$name.md5.txt" + ( + cd "$OUT" + md5sum --check "$(basename "$sum_file")" + ) +} + fetch vmlinuz64 fetch corepure64.gz +verify_md5 vmlinuz64 +verify_md5 corepure64.gz + +gzip -t "$OUT/corepure64.gz" + +{ + printf 'tinycore_major=%s\n' "$TC_MAJOR" + printf 'tinycore_version=%s\n' "$TC_VERSION" + printf 'kernel_version=%s\n' "$TC_KERNEL" + printf 'source=%s\n' "$BASE_URL" + printf 'vmlinuz64_md5=%s\n' "$(awk '{print $1}' "$OUT/vmlinuz64.md5.txt")" + printf 'corepure64_md5=%s\n' "$(awk '{print $1}' "$OUT/corepure64.gz.md5.txt")" +} > "$OUT/manifest.txt" -printf 'Tiny Core CorePure64 %s base ready in %s\n' "$TC_MAJOR" "$OUT" +cat "$OUT/manifest.txt" +printf 'Tiny Core CorePure64 %s base ready in %s\n' "$TC_VERSION" "$OUT" printf 'Kernel: %s\n' "$OUT/vmlinuz64" printf 'Initramfs: %s\n' "$OUT/corepure64.gz" From c4d3ae7a46908ce10aa139941054259502551f07 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:41:27 +0100 Subject: [PATCH 18/64] Harden Tiny Core CI and cache verified base --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af61071..218cddb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,6 @@ name: Kernel CI on: push: - branches: [main] pull_request: branches: [main] workflow_dispatch: @@ -32,13 +31,34 @@ jobs: file \ qemu-system-x86 - - name: Fetch Tiny Core Linux base + - name: Cache Tiny Core base + uses: actions/cache@v4 + with: + path: /tmp/tinycore + key: tinycore-corepure64-17.0-linux-6.18.2 + + - name: Fetch and verify Tiny Core Linux base + env: + TC_MAJOR: 17.x + TC_VERSION: '17.0' + TC_KERNEL: 6.18.2-tinycore64 run: | bash tinycore/fetch.sh /tmp/tinycore test -s /tmp/tinycore/vmlinuz64 test -s /tmp/tinycore/corepure64.gz + test -s /tmp/tinycore/manifest.txt file /tmp/tinycore/vmlinuz64 gzip -t /tmp/tinycore/corepure64.gz + cat /tmp/tinycore/manifest.txt + + - name: Record upstream kernel configuration + run: | + curl --fail --location --retry 3 \ + --output /tmp/tinycore/config-6.18.2-tinycore64 \ + https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.2-tinycore64 + + grep -E '^(CONFIG_BPF|CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_KPROBES|CONFIG_BPF_EVENTS|CONFIG_DEBUG_INFO_BTF)=' \ + /tmp/tinycore/config-6.18.2-tinycore64 || true - name: Boot Tiny Core kernel under QEMU run: | @@ -63,7 +83,7 @@ jobs: exit "$rc" fi - grep -F 'Linux version' /tmp/tinycore-serial.log + grep -F 'Linux version 6.18.2-tinycore64' /tmp/tinycore-serial.log - name: Verify Flow compiler remains external run: | @@ -71,11 +91,14 @@ jobs: test -x /tmp/flow/flow test ! -e ./flow - - name: Upload boot log + - name: Upload verification artifacts if: always() uses: actions/upload-artifact@v4 with: - name: tinycore-x86_64-boot - path: /tmp/tinycore-serial.log + name: tinycore-x86_64-verification + path: | + /tmp/tinycore-serial.log + /tmp/tinycore/manifest.txt + /tmp/tinycore/config-6.18.2-tinycore64 if-no-files-found: warn retention-days: 7 From 009f76727aa836fa54e962abb11ef645eef51cd4 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:41:40 +0100 Subject: [PATCH 19/64] Add kernel CI and Pages badges --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index adaa763..7cac947 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Flow Kernel +[![Kernel CI](https://github.com/flooooooooooow/flow-kernel/actions/workflows/ci.yml/badge.svg)](https://github.com/flooooooooooow/flow-kernel/actions/workflows/ci.yml) +[![GitHub Pages](https://github.com/flooooooooooow/flow-kernel/actions/workflows/pages.yml/badge.svg)](https://github.com/flooooooooooow/flow-kernel/actions/workflows/pages.yml) + Flow systems integration on top of a deliberately tiny Linux base. `flow-kernel` no longer implements its own bootloader, page tables, scheduler, interrupt subsystem, or virtual-memory manager. Those are Linux responsibilities. The base target is Tiny Core Linux CorePure64: a minimal command-line Linux system that gives Flow a mature x86_64 kernel, drivers, networking, processes, namespaces, cgroups, perf and the native Linux eBPF surface without dragging in a conventional desktop distribution. @@ -20,7 +23,7 @@ Tiny Core is the substrate, not a fork. We consume its `vmlinuz64` and `corepure ## Fetch the Tiny Core base -The default tracks the CorePure64 `17.x` release line. Override `TC_MAJOR` when intentionally moving to another Tiny Core line. +The default tracks Tiny Core CorePure64 17.0 with Linux `6.18.2-tinycore64`. The fetch script verifies Tiny Core's published MD5 sidecars and records a manifest containing the exact version and checksums used. ```bash bash tinycore/fetch.sh From bcedd8b6085117026b4be0bc56f195745291f96c Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:43:25 +0100 Subject: [PATCH 20/64] Clarify flow-kernel ownership boundary --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7cac947..9632438 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ Flow eBPF, XDP, tracing and driver experiments Tiny Core is the substrate, not a fork. We consume its `vmlinuz64` and `corepure64.gz` release artifacts directly. +## Repository boundary + +`flooooooooooow/flow` owns language syntax, parser/type-system behaviour, generic compiler infrastructure and reusable target/backend machinery. `flow-kernel` owns Linux-specific ABI bindings, kernel-facing Flow libraries, eBPF program APIs and examples, loaders/control-plane code, Tiny Core packaging, kernel integration tests and systems benchmarks. Changes needed in the Flow compiler should be implemented upstream rather than copied into this repository. + ## Fetch the Tiny Core base The default tracks Tiny Core CorePure64 17.0 with Linux `6.18.2-tinycore64`. The fetch script verifies Tiny Core's published MD5 sidecars and records a manifest containing the exact version and checksums used. From b3608f4ad69d8a193f525d283868e69194f0f83e Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:43:39 +0100 Subject: [PATCH 21/64] Document Tiny Core verification status --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9632438..ebd6603 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,10 @@ bash tinycore/run.sh This boots the Tiny Core Linux kernel and initramfs directly in QEMU with the serial console attached to the terminal. No GRUB image and no Flow-owned architecture bootstrap are involved. +## Verification + +CI caches the Tiny Core base, revalidates the published checksum sidecars, records the exact source/version/checksums, captures the serial boot log and archives the shipped kernel configuration. The eBPF/BTF feature set is intentionally checked from the real Tiny Core kernel config instead of assumed from the Linux version. + ## Flow compiler Flow remains a separate dependency. Kernel-facing Flow programs in this repository should compile against Linux ABIs or to eBPF; the language/compiler belongs in `flooooooooooow/flow` and is checked out independently in CI. From 66d885ea60ada1ba72ec86aaf0d72dd8ba83324c Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:44:01 +0100 Subject: [PATCH 22/64] Define eBPF backend boundary --- ebpf/README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ebpf/README.md b/ebpf/README.md index 9604b9a..5c31b4a 100644 --- a/ebpf/README.md +++ b/ebpf/README.md @@ -1,18 +1,20 @@ # Flow eBPF -Linux eBPF is the first kernel-facing execution target for Flow on the Tiny Core base. +This directory is the kernel-facing eBPF layer for Flow. -The implementation should lower a verifier-safe Flow subset to eBPF rather than recreate Linux kernel infrastructure. Initial scope: +The compiler implementation itself belongs in `flooooooooooow/flow`. This repository owns the Linux program model around that backend: section conventions, helper/map bindings, verifier-safe APIs, loaders, attach/detach workflows, Tiny Core integration, examples and end-to-end kernel tests. -- BPF ELF emission and section metadata -- maps and map declarations -- verifier-safe scalar and pointer operations -- Linux helper bindings -- tracepoints and kprobes -- XDP programs -- TC ingress/egress hooks -- BTF type ingestion -- CO-RE-style relocations -- deterministic host-side tests against the Linux verifier +## Target contract -The Tiny Core image is intentionally only the execution substrate. Compiler/backend work belongs in `flooooooooooow/flow`; this repository owns Linux integration, fixtures, boot images and end-to-end kernel tests. +The intended compiler contract is a little-endian Linux eBPF target (`bpfel`) lowered through Flow's MLIR/LLVM path into standalone eBPF ELF objects. Programs must not depend on the normal Flow runtime, dynamic allocation, unwinding or unsupported indirect behaviour. Pointer provenance, stack use and loop lowering must be verifier-safe before an object is handed to the kernel. + +## Initial hook order + +1. tracepoints +2. kprobes/fentry where supported +3. ring-buffer event delivery +4. XDP +5. TC ingress/egress +6. CO-RE/BTF-based portable programs + +Stock Tiny Core kernel capabilities are inspected explicitly in CI. If CorePure64 does not expose the BPF/BTF features required by a phase, the project should add a reproducible Tiny Core kernel variant rather than silently assuming support. From aeb7f62111c4cb6e15dd19e733c7a8432204001a Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 13:44:14 +0100 Subject: [PATCH 23/64] Document Flow eBPF target constraints --- ebpf/README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/ebpf/README.md b/ebpf/README.md index 5c31b4a..a466800 100644 --- a/ebpf/README.md +++ b/ebpf/README.md @@ -6,7 +6,31 @@ The compiler implementation itself belongs in `flooooooooooow/flow`. This reposi ## Target contract -The intended compiler contract is a little-endian Linux eBPF target (`bpfel`) lowered through Flow's MLIR/LLVM path into standalone eBPF ELF objects. Programs must not depend on the normal Flow runtime, dynamic allocation, unwinding or unsupported indirect behaviour. Pointer provenance, stack use and loop lowering must be verifier-safe before an object is handed to the kernel. +The intended compiler contract is a little-endian Linux eBPF target (`bpfel`) lowered through Flow's MLIR/LLVM path into standalone eBPF ELF objects. + +The first backend must enforce these invariants before verifier load: + +- no dependency on the normal Flow runtime +- no dynamic allocation +- no exceptions or unwinding +- bounded/verifier-safe loops +- bounded stack use +- verifier-safe pointer provenance +- no unsupported indirect calls or dynamic dispatch +- target-specific helper availability +- deterministic ELF section/program metadata + +## Canonical lowering + +```text +Flow source + → Flow AST / typed IR + → MLIR / LLVM lowering + → LLVM BPF target (bpfel) + → standalone eBPF ELF + → Linux verifier + → attach to Linux hook +``` ## Initial hook order From f1060ef7c2304babc1275582da0bc30b82741dc4 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:02:20 +0100 Subject: [PATCH 24/64] Document Flow Linux ABI boundary --- docs/linux-abi.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 docs/linux-abi.md diff --git a/docs/linux-abi.md b/docs/linux-abi.md new file mode 100644 index 0000000..8585f40 --- /dev/null +++ b/docs/linux-abi.md @@ -0,0 +1,55 @@ +# Flow Linux ABI boundary + +`flow-kernel` targets the Linux userspace ABI directly for tiny services and the Linux eBPF ABI for kernel-facing programs. It does not introduce a private kernel ABI. + +## Supported userspace ABI + +The initial target is Linux x86_64. Flow scalar mappings are intentionally exact-width: + +| Linux ABI concept | Flow type | +|---|---| +| `char` / byte | `u8` | +| `short` | `i16` / `u16` | +| `int` | `i32` / `u32` | +| `long`, `ssize_t`, syscall return | `i64` | +| `unsigned long`, `size_t` | `u64` | +| address / opaque pointer | `ptr` | +| C string input | `string` when Flow owns the storage, otherwise `ptr` | +| file descriptor | `i32` | + +The syscall layer does not translate `errno`. Raw Linux syscall results are returned directly: non-negative values indicate success and negative values are `-errno`. + +## Initial syscall surface + +The first libc-free surface is deliberately small: + +- `write(fd, buffer, count)` +- `exit(status)` +- `mmap(address, length, protection, flags, fd, offset)` +- `clock_gettime(clock_id, timespec_ptr)` + +These cover basic output, process termination, memory acquisition, clocks and file-descriptor based service code without introducing libc as a runtime requirement. + +## Stable FFI pattern + +Architecture-specific syscall instructions live in tiny `@cEmbed` shims. Flow owns type checking and service logic; the shim owns only the ABI register convention and `syscall` instruction. No libc symbol should be required by a deployed CorePure64 service. + +For x86_64 Linux, syscall arguments use `rax` for the syscall number and `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9` for arguments 1–6. The wrappers in `linux/x86_64/abi.flow` encode that boundary. + +## Repository boundary + +Belongs in `flow-kernel`: + +- Linux ABI bindings and fixtures +- Tiny Core integration and packaging +- libc-free service examples +- eBPF loader/runtime integration +- end-to-end QEMU and kernel tests + +Belongs in `flooooooooooow/flow`: + +- language syntax +- compiler IR and lowering +- target selection such as `bpfel` +- verifier-aware compiler diagnostics +- object emission and backend implementation From f8d597b7becf66efa827db098b730cebc3cd82d9 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:02:38 +0100 Subject: [PATCH 25/64] Add libc-free Linux x86_64 syscall ABI --- linux/x86_64/abi.flow | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 linux/x86_64/abi.flow diff --git a/linux/x86_64/abi.flow b/linux/x86_64/abi.flow new file mode 100644 index 0000000..826b897 --- /dev/null +++ b/linux/x86_64/abi.flow @@ -0,0 +1,69 @@ +# Linux x86_64 raw syscall ABI for Flow. +# +# These wrappers intentionally bypass libc. Linux returns negative errno values +# directly; callers decide whether and how to translate them. + +@cEmbed(" +typedef unsigned long flow_u64; +typedef long flow_i64; +typedef int flow_i32; + +static inline flow_i64 flow_linux_syscall1(flow_i64 n, flow_i64 a1) { + flow_i64 r; + __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(n), \"D\"(a1) : \"rcx\", \"r11\", \"memory\"); + return r; +} + +static inline flow_i64 flow_linux_syscall2(flow_i64 n, flow_i64 a1, flow_i64 a2) { + flow_i64 r; + __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(n), \"D\"(a1), \"S\"(a2) : \"rcx\", \"r11\", \"memory\"); + return r; +} + +static inline flow_i64 flow_linux_syscall3(flow_i64 n, flow_i64 a1, flow_i64 a2, flow_i64 a3) { + flow_i64 r; + __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(n), \"D\"(a1), \"S\"(a2), \"d\"(a3) : \"rcx\", \"r11\", \"memory\"); + return r; +} + +static inline flow_i64 flow_linux_syscall6(flow_i64 n, flow_i64 a1, flow_i64 a2, flow_i64 a3, flow_i64 a4, flow_i64 a5, flow_i64 a6) { + register flow_i64 r10 __asm__(\"r10\") = a4; + register flow_i64 r8 __asm__(\"r8\") = a5; + register flow_i64 r9 __asm__(\"r9\") = a6; + flow_i64 r; + __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(n), \"D\"(a1), \"S\"(a2), \"d\"(a3), \"r\"(r10), \"r\"(r8), \"r\"(r9) : \"rcx\", \"r11\", \"memory\"); + return r; +} + +flow_i64 flow_linux_write(flow_i32 fd, const void* data, flow_u64 count) { + return flow_linux_syscall3(1, fd, (flow_i64)data, count); +} + +__attribute__((noreturn)) void flow_linux_exit(flow_i32 status) { + flow_linux_syscall1(60, status); + __builtin_unreachable(); +} + +flow_i64 flow_linux_mmap(void* address, flow_u64 length, flow_i32 protection, flow_i32 flags, flow_i32 fd, flow_i64 offset) { + return flow_linux_syscall6(9, (flow_i64)address, length, protection, flags, fd, offset); +} + +flow_i64 flow_linux_clock_gettime(flow_i32 clock_id, void* timespec) { + return flow_linux_syscall2(228, clock_id, (flow_i64)timespec); +} +") + +extern { + function flow_linux_write(fd: i32, data: ptr, count: u64) -> i64 + function flow_linux_exit(status: i32) -> void + function flow_linux_mmap(address: ptr, length: u64, protection: i32, flags: i32, fd: i32, offset: i64) -> i64 + function flow_linux_clock_gettime(clock_id: i32, timespec: ptr) -> i64 +} + +export function linux_stdout_fd() -> i32 { + return 1 +} + +export function linux_stderr_fd() -> i32 { + return 2 +} From d5c9614b769f8288bc4309cfc39885ccbc2d19b2 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:02:47 +0100 Subject: [PATCH 26/64] Add libc-free Flow hello service --- examples/hello.flow | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 examples/hello.flow diff --git a/examples/hello.flow b/examples/hello.flow new file mode 100644 index 0000000..b28571c --- /dev/null +++ b/examples/hello.flow @@ -0,0 +1,28 @@ +# Minimal Flow userspace service for Tiny Core CorePure64. +# +# The service uses the Linux syscall ABI directly and requires no libc or +# dynamic loader. `_start` is supplied by examples/start.S. + +@cEmbed(" +typedef unsigned long flow_u64; +typedef long flow_i64; + +flow_i64 flow_hello_write(const void* data, flow_u64 count) { + flow_i64 r; + __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(1), \"D\"(1), \"S\"(data), \"d\"(count) : \"rcx\", \"r11\", \"memory\"); + return r; +} +") + +extern { + function flow_hello_write(data: string, count: u64) -> i64 +} + +export function hello_main() -> i32 { + let message = "Flow on Tiny Core: hello from a libc-free process\n" + let result = flow_hello_write(message, 49) + if result < 0 { + return 1 + } + return 0 +} From 589adda7b9226bbbdf27402a86056f84904d92e4 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:02:58 +0100 Subject: [PATCH 27/64] Add libc-free x86_64 process entry --- examples/start.S | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 examples/start.S diff --git a/examples/start.S b/examples/start.S new file mode 100644 index 0000000..de9e189 --- /dev/null +++ b/examples/start.S @@ -0,0 +1,11 @@ +.section .text +.global _start +.type _start,@function +_start: + xor %rbp, %rbp + and $-16, %rsp + call flow_export_hello_main + mov %eax, %edi + mov $60, %eax + syscall + ud2 From e1c3238b40fb208480346c60c57a9dc74a42145c Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:03:11 +0100 Subject: [PATCH 28/64] Fix hello service write length --- examples/hello.flow | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/hello.flow b/examples/hello.flow index b28571c..c4c12b8 100644 --- a/examples/hello.flow +++ b/examples/hello.flow @@ -20,7 +20,7 @@ extern { export function hello_main() -> i32 { let message = "Flow on Tiny Core: hello from a libc-free process\n" - let result = flow_hello_write(message, 49) + let result = flow_hello_write(message, 50) if result < 0 { return 1 } From 5e4a63ab5587cd8a2c1921c724b71b7ef21821b4 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:03:20 +0100 Subject: [PATCH 29/64] Build libc-free Flow service --- examples/build-hello.sh | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 examples/build-hello.sh diff --git a/examples/build-hello.sh b/examples/build-hello.sh new file mode 100644 index 0000000..a3503ab --- /dev/null +++ b/examples/build-hello.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +FLOW="${FLOW:-$ROOT/../flow/flow}" +OUT="${1:-$ROOT/build/hello}" + +if [[ ! -x "$FLOW" ]]; then + echo "Flow compiler not found at $FLOW" >&2 + exit 1 +fi + +mkdir -p "$OUT" + +"$FLOW" transpile "$ROOT/examples/hello.flow" \ + --c \ + --export hello_main \ + -o "$OUT/hello.c" + +clang \ + -target x86_64-linux-gnu \ + -std=c11 \ + -ffreestanding \ + -fno-builtin \ + -fno-stack-protector \ + -fno-pic \ + -fno-pie \ + -O2 \ + -c "$OUT/hello.c" \ + -o "$OUT/hello-flow.o" + +clang \ + -target x86_64-linux-gnu \ + -ffreestanding \ + -fno-pic \ + -fno-pie \ + -c "$ROOT/examples/start.S" \ + -o "$OUT/start.o" + +ld.lld \ + -static \ + -nostdlib \ + -e _start \ + "$OUT/start.o" \ + "$OUT/hello-flow.o" \ + -o "$OUT/flow-hello" + +if command -v readelf >/dev/null 2>&1; then + readelf -l "$OUT/flow-hello" | grep -qv 'Requesting program interpreter' +fi + +printf '%s\n' "$OUT/flow-hello" From 9eaebda12a9a688187f34261a0d3498aced1327b Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:03:54 +0100 Subject: [PATCH 30/64] Run libc-free Flow service in Tiny Core CI --- .github/workflows/ci.yml | 75 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 218cddb..223efed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,12 +23,16 @@ jobs: - name: Checkout Flow kernel integration uses: actions/checkout@v7 - - name: Install boot-test tools + - name: Install build and boot-test tools run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ + binutils \ + clang \ + cpio \ curl \ file \ + lld \ qemu-system-x86 - name: Cache Tiny Core base @@ -51,14 +55,22 @@ jobs: gzip -t /tmp/tinycore/corepure64.gz cat /tmp/tinycore/manifest.txt - - name: Record upstream kernel configuration + - name: Verify upstream eBPF and BTF kernel configuration run: | curl --fail --location --retry 3 \ --output /tmp/tinycore/config-6.18.2-tinycore64 \ https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.2-tinycore64 grep -E '^(CONFIG_BPF|CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_KPROBES|CONFIG_BPF_EVENTS|CONFIG_DEBUG_INFO_BTF)=' \ - /tmp/tinycore/config-6.18.2-tinycore64 || true + /tmp/tinycore/config-6.18.2-tinycore64 \ + | tee /tmp/tinycore/bpf-config.txt + + grep -Fx 'CONFIG_BPF=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_SYSCALL=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_JIT=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_KPROBES=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_EVENTS=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_DEBUG_INFO_BTF=y' /tmp/tinycore/bpf-config.txt - name: Boot Tiny Core kernel under QEMU run: | @@ -85,12 +97,64 @@ jobs: grep -F 'Linux version 6.18.2-tinycore64' /tmp/tinycore-serial.log - - name: Verify Flow compiler remains external + - name: Checkout Flow compiler externally run: | git clone --depth 1 https://github.com/flooooooooooow/flow.git /tmp/flow test -x /tmp/flow/flow test ! -e ./flow + - name: Build libc-free Flow hello service + env: + FLOW: /tmp/flow/flow + FLOW_HOST: python + PYTHONPATH: /tmp/flow/src + run: | + chmod +x /tmp/flow/flow examples/build-hello.sh + bash examples/build-hello.sh /tmp/flow-hello-build + test -x /tmp/flow-hello-build/flow-hello + file /tmp/flow-hello-build/flow-hello + ! readelf -l /tmp/flow-hello-build/flow-hello | grep -F 'Requesting program interpreter' + ! nm -u /tmp/flow-hello-build/flow-hello | grep . + + - name: Add Flow service to CorePure64 initramfs + run: | + mkdir -p /tmp/flow-overlay/opt + cp /tmp/flow-hello-build/flow-hello /tmp/flow-overlay/opt/flow-hello + chmod 0755 /tmp/flow-overlay/opt/flow-hello + + gzip -dc /tmp/tinycore/corepure64.gz > /tmp/flow-corepure64.cpio + ( + cd /tmp/flow-overlay + find . -print0 | cpio --null -o --format=newc --owner=0:0 + ) >> /tmp/flow-corepure64.cpio + gzip -9 < /tmp/flow-corepure64.cpio > /tmp/flow-corepure64.gz + gzip -t /tmp/flow-corepure64.gz + + - name: Run Flow process inside CorePure64 + run: | + set +e + timeout 15s qemu-system-x86_64 \ + -machine accel=tcg \ + -cpu max \ + -m 256M \ + -kernel /tmp/tinycore/vmlinuz64 \ + -initrd /tmp/flow-corepure64.gz \ + -append 'console=ttyS0 init=/opt/flow-hello' \ + -serial file:/tmp/flow-service-serial.log \ + -display none \ + -no-reboot \ + -no-shutdown + rc=$? + set -e + + cat /tmp/flow-service-serial.log + if [[ "$rc" -ne 0 && "$rc" -ne 124 ]]; then + echo "QEMU exited unexpectedly with status $rc" >&2 + exit "$rc" + fi + + grep -F 'Flow on Tiny Core: hello from a libc-free process' /tmp/flow-service-serial.log + - name: Upload verification artifacts if: always() uses: actions/upload-artifact@v4 @@ -98,7 +162,10 @@ jobs: name: tinycore-x86_64-verification path: | /tmp/tinycore-serial.log + /tmp/flow-service-serial.log /tmp/tinycore/manifest.txt /tmp/tinycore/config-6.18.2-tinycore64 + /tmp/tinycore/bpf-config.txt + /tmp/flow-hello-build/flow-hello if-no-files-found: warn retention-days: 7 From b22a8128de232f42169726f151f6e963866b440f Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:04:32 +0100 Subject: [PATCH 31/64] Add libc-free syscall examples --- docs/syscalls.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/syscalls.md diff --git a/docs/syscalls.md b/docs/syscalls.md new file mode 100644 index 0000000..9449413 --- /dev/null +++ b/docs/syscalls.md @@ -0,0 +1,52 @@ +# Libc-free syscall examples + +The canonical x86_64 bindings live in `linux/x86_64/abi.flow`. They return raw Linux syscall results; negative values are `-errno`. + +## File descriptors and `write` + +```flow +let stdout: i32 = 1 +let result: i64 = flow_linux_write(stdout, data, count) +if result < 0 { + # handle -errno +} +``` + +File descriptors are `i32`; byte counts and sizes are `u64`. + +## `exit` + +```flow +flow_linux_exit(0) +``` + +`exit` never returns. Minimal binaries normally use the `_start` stub in `examples/start.S`, which exits with the Flow entrypoint's return value. + +## `mmap` + +```flow +# PROT_READ | PROT_WRITE = 3 +# MAP_PRIVATE | MAP_ANONYMOUS = 34 +let raw: i64 = flow_linux_mmap(null, 4096, 3, 34, -1, 0) +if raw < 0 { + # allocation failed: raw is -errno +} +``` + +The initial binding intentionally returns the raw machine-word result as `i64`; a higher-level typed pointer wrapper can be layered on top without changing the Linux ABI shim. + +## `clock_gettime` + +```flow +# CLOCK_MONOTONIC = 1 +let result: i64 = flow_linux_clock_gettime(1, timespec_ptr) +if result < 0 { + # clock read failed +} +``` + +The caller owns the two-`i64` `timespec` storage for the x86_64 ABI. Keeping the primitive pointer-based avoids forcing a kernel C struct representation into the Flow language. + +## Minimal service + +`examples/hello.flow` demonstrates the deployed shape used by CI: Flow logic plus a tiny direct-syscall shim, transpiled to C and linked with `-static -nostdlib`. CI checks that the resulting ELF has neither a program interpreter nor unresolved symbols before inserting it into the CorePure64 initramfs. From 9559bfbae183cb171b683cc1a50d211a02c72f08 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:14:50 +0100 Subject: [PATCH 32/64] Bound Tiny Core artifact download time --- tinycore/fetch.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh index 9d1aa7c..812c31a 100644 --- a/tinycore/fetch.sh +++ b/tinycore/fetch.sh @@ -5,6 +5,8 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TC_MAJOR="${TC_MAJOR:-17.x}" TC_VERSION="${TC_VERSION:-17.0}" TC_KERNEL="${TC_KERNEL:-6.18.2-tinycore64}" +TC_CONNECT_TIMEOUT="${TC_CONNECT_TIMEOUT:-15}" +TC_FETCH_TIMEOUT="${TC_FETCH_TIMEOUT:-120}" OUT="${1:-$ROOT/build/tinycore}" BASE_URL="https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" @@ -22,9 +24,17 @@ fetch() fi printf 'Fetching %s\n' "$url" - if ! curl --fail --location --retry 3 --retry-all-errors --output "$dst.part" "$url"; then + if ! curl \ + --fail \ + --location \ + --retry 3 \ + --retry-all-errors \ + --connect-timeout "$TC_CONNECT_TIMEOUT" \ + --max-time "$TC_FETCH_TIMEOUT" \ + --output "$dst.part" \ + "$url"; then rm -f "$dst.part" - printf 'Tiny Core artifact unavailable: %s\n' "$url" >&2 + printf 'Tiny Core artifact unavailable or timed out after %ss: %s\n' "$TC_FETCH_TIMEOUT" "$url" >&2 exit 1 fi mv "$dst.part" "$dst" @@ -54,6 +64,8 @@ gzip -t "$OUT/corepure64.gz" printf 'tinycore_version=%s\n' "$TC_VERSION" printf 'kernel_version=%s\n' "$TC_KERNEL" printf 'source=%s\n' "$BASE_URL" + printf 'connect_timeout_seconds=%s\n' "$TC_CONNECT_TIMEOUT" + printf 'fetch_timeout_seconds=%s\n' "$TC_FETCH_TIMEOUT" printf 'vmlinuz64_md5=%s\n' "$(awk '{print $1}' "$OUT/vmlinuz64.md5.txt")" printf 'corepure64_md5=%s\n' "$(awk '{print $1}' "$OUT/corepure64.gz.md5.txt")" } > "$OUT/manifest.txt" From c0a9cb0e5c3469a5a665bc2c874dcd364dac3d2f Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:17:29 +0100 Subject: [PATCH 33/64] Track Tiny Core 17.1 with mirror fallback --- tinycore/fetch.sh | 55 +++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh index 812c31a..8b9b691 100644 --- a/tinycore/fetch.sh +++ b/tinycore/fetch.sh @@ -3,41 +3,54 @@ set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TC_MAJOR="${TC_MAJOR:-17.x}" -TC_VERSION="${TC_VERSION:-17.0}" -TC_KERNEL="${TC_KERNEL:-6.18.2-tinycore64}" -TC_CONNECT_TIMEOUT="${TC_CONNECT_TIMEOUT:-15}" -TC_FETCH_TIMEOUT="${TC_FETCH_TIMEOUT:-120}" +TC_VERSION="${TC_VERSION:-17.1}" +TC_KERNEL="${TC_KERNEL:-6.18.35-tinycore64}" +TC_CONNECT_TIMEOUT="${TC_CONNECT_TIMEOUT:-10}" +TC_FETCH_TIMEOUT="${TC_FETCH_TIMEOUT:-90}" OUT="${1:-$ROOT/build/tinycore}" -BASE_URL="https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" + +BASE_URLS=( + "https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" + "https://ftp.icm.edu.pl/packages/linux-tinycorelinux/${TC_MAJOR}/x86_64/release/distribution_files" + "https://ftp.dk.xemacs.org/mirrors/mirrors/pub/tinycorelinux/${TC_MAJOR}/x86_64/release/distribution_files" +) mkdir -p "$OUT" fetch() { local name="$1" - local url="$BASE_URL/$name" local dst="$OUT/$name" + local base_url + local url if [[ -s "$dst" ]]; then printf 'Using cached %s\n' "$dst" return fi - printf 'Fetching %s\n' "$url" - if ! curl \ - --fail \ - --location \ - --retry 3 \ - --retry-all-errors \ - --connect-timeout "$TC_CONNECT_TIMEOUT" \ - --max-time "$TC_FETCH_TIMEOUT" \ - --output "$dst.part" \ - "$url"; then + for base_url in "${BASE_URLS[@]}"; do + url="$base_url/$name" + printf 'Fetching %s\n' "$url" + if curl \ + --fail \ + --location \ + --retry 1 \ + --retry-all-errors \ + --connect-timeout "$TC_CONNECT_TIMEOUT" \ + --max-time "$TC_FETCH_TIMEOUT" \ + --output "$dst.part" \ + "$url"; then + mv "$dst.part" "$dst" + printf '%s\n' "$base_url" > "$OUT/source-url.txt" + return + fi rm -f "$dst.part" - printf 'Tiny Core artifact unavailable or timed out after %ss: %s\n' "$TC_FETCH_TIMEOUT" "$url" >&2 - exit 1 - fi - mv "$dst.part" "$dst" + printf 'Tiny Core source failed, trying next mirror: %s\n' "$url" >&2 + done + + printf 'Tiny Core artifact unavailable from all configured mirrors: %s\n' "$name" >&2 + exit 1 } verify_md5() @@ -63,7 +76,7 @@ gzip -t "$OUT/corepure64.gz" printf 'tinycore_major=%s\n' "$TC_MAJOR" printf 'tinycore_version=%s\n' "$TC_VERSION" printf 'kernel_version=%s\n' "$TC_KERNEL" - printf 'source=%s\n' "$BASE_URL" + printf 'source=%s\n' "$(cat "$OUT/source-url.txt")" printf 'connect_timeout_seconds=%s\n' "$TC_CONNECT_TIMEOUT" printf 'fetch_timeout_seconds=%s\n' "$TC_FETCH_TIMEOUT" printf 'vmlinuz64_md5=%s\n' "$(awk '{print $1}' "$OUT/vmlinuz64.md5.txt")" From c4d479a0e2e23b1b71a594e7c5686d0352c5f00f Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:17:58 +0100 Subject: [PATCH 34/64] Verify Tiny Core 17.1 across mirrors --- .github/workflows/ci.yml | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 223efed..6363425 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,13 +39,13 @@ jobs: uses: actions/cache@v4 with: path: /tmp/tinycore - key: tinycore-corepure64-17.0-linux-6.18.2 + key: tinycore-corepure64-17.1-linux-6.18.35 - name: Fetch and verify Tiny Core Linux base env: TC_MAJOR: 17.x - TC_VERSION: '17.0' - TC_KERNEL: 6.18.2-tinycore64 + TC_VERSION: '17.1' + TC_KERNEL: 6.18.35-tinycore64 run: | bash tinycore/fetch.sh /tmp/tinycore test -s /tmp/tinycore/vmlinuz64 @@ -53,16 +53,35 @@ jobs: test -s /tmp/tinycore/manifest.txt file /tmp/tinycore/vmlinuz64 gzip -t /tmp/tinycore/corepure64.gz + grep -Fx 'tinycore_version=17.1' /tmp/tinycore/manifest.txt + grep -Fx 'kernel_version=6.18.35-tinycore64' /tmp/tinycore/manifest.txt cat /tmp/tinycore/manifest.txt - name: Verify upstream eBPF and BTF kernel configuration run: | - curl --fail --location --retry 3 \ - --output /tmp/tinycore/config-6.18.2-tinycore64 \ - https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.2-tinycore64 + CONFIG=/tmp/tinycore/config-6.18.35-tinycore64 + urls=( + 'https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + 'https://ftp.icm.edu.pl/packages/linux-tinycorelinux/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + 'https://ftp.dk.xemacs.org/mirrors/mirrors/pub/tinycorelinux/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + ) + found=0 + for url in "${urls[@]}"; do + if curl --fail --location --connect-timeout 10 --max-time 45 --output "$CONFIG.part" "$url"; then + mv "$CONFIG.part" "$CONFIG" + echo "kernel_config_source=$url" | tee /tmp/tinycore/config-source.txt + found=1 + break + fi + rm -f "$CONFIG.part" + done + if [[ "$found" -ne 1 ]]; then + echo 'Could not retrieve Tiny Core kernel configuration from any configured mirror' >&2 + exit 1 + fi grep -E '^(CONFIG_BPF|CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_KPROBES|CONFIG_BPF_EVENTS|CONFIG_DEBUG_INFO_BTF)=' \ - /tmp/tinycore/config-6.18.2-tinycore64 \ + "$CONFIG" \ | tee /tmp/tinycore/bpf-config.txt grep -Fx 'CONFIG_BPF=y' /tmp/tinycore/bpf-config.txt @@ -95,7 +114,7 @@ jobs: exit "$rc" fi - grep -F 'Linux version 6.18.2-tinycore64' /tmp/tinycore-serial.log + grep -F 'Linux version 6.18.35-tinycore64' /tmp/tinycore-serial.log - name: Checkout Flow compiler externally run: | @@ -164,7 +183,8 @@ jobs: /tmp/tinycore-serial.log /tmp/flow-service-serial.log /tmp/tinycore/manifest.txt - /tmp/tinycore/config-6.18.2-tinycore64 + /tmp/tinycore/config-6.18.35-tinycore64 + /tmp/tinycore/config-source.txt /tmp/tinycore/bpf-config.txt /tmp/flow-hello-build/flow-hello if-no-files-found: warn From dd71d2d0ae94e92669f852c74fed38889352e717 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:18:16 +0100 Subject: [PATCH 35/64] Update Tiny Core baseline to 17.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebd6603..1bad046 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Tiny Core is the substrate, not a fork. We consume its `vmlinuz64` and `corepure ## Fetch the Tiny Core base -The default tracks Tiny Core CorePure64 17.0 with Linux `6.18.2-tinycore64`. The fetch script verifies Tiny Core's published MD5 sidecars and records a manifest containing the exact version and checksums used. +The default tracks Tiny Core CorePure64 17.1 with Linux `6.18.35-tinycore64`. The fetch script tries the Tiny Core origin followed by configured public mirrors, verifies Tiny Core's published MD5 sidecars, and records a manifest containing the exact version, source mirror and checksums used. ```bash bash tinycore/fetch.sh From 46b01c7d335afd330b813774d0461f23f45baa85 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:23:50 +0100 Subject: [PATCH 36/64] Let Tiny Core boot proof precede BPF metadata probe --- .github/workflows/ci.yml | 67 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6363425..76f7fc3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,40 +57,6 @@ jobs: grep -Fx 'kernel_version=6.18.35-tinycore64' /tmp/tinycore/manifest.txt cat /tmp/tinycore/manifest.txt - - name: Verify upstream eBPF and BTF kernel configuration - run: | - CONFIG=/tmp/tinycore/config-6.18.35-tinycore64 - urls=( - 'https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' - 'https://ftp.icm.edu.pl/packages/linux-tinycorelinux/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' - 'https://ftp.dk.xemacs.org/mirrors/mirrors/pub/tinycorelinux/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' - ) - found=0 - for url in "${urls[@]}"; do - if curl --fail --location --connect-timeout 10 --max-time 45 --output "$CONFIG.part" "$url"; then - mv "$CONFIG.part" "$CONFIG" - echo "kernel_config_source=$url" | tee /tmp/tinycore/config-source.txt - found=1 - break - fi - rm -f "$CONFIG.part" - done - if [[ "$found" -ne 1 ]]; then - echo 'Could not retrieve Tiny Core kernel configuration from any configured mirror' >&2 - exit 1 - fi - - grep -E '^(CONFIG_BPF|CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_KPROBES|CONFIG_BPF_EVENTS|CONFIG_DEBUG_INFO_BTF)=' \ - "$CONFIG" \ - | tee /tmp/tinycore/bpf-config.txt - - grep -Fx 'CONFIG_BPF=y' /tmp/tinycore/bpf-config.txt - grep -Fx 'CONFIG_BPF_SYSCALL=y' /tmp/tinycore/bpf-config.txt - grep -Fx 'CONFIG_BPF_JIT=y' /tmp/tinycore/bpf-config.txt - grep -Fx 'CONFIG_KPROBES=y' /tmp/tinycore/bpf-config.txt - grep -Fx 'CONFIG_BPF_EVENTS=y' /tmp/tinycore/bpf-config.txt - grep -Fx 'CONFIG_DEBUG_INFO_BTF=y' /tmp/tinycore/bpf-config.txt - - name: Boot Tiny Core kernel under QEMU run: | set +e @@ -174,6 +140,39 @@ jobs: grep -F 'Flow on Tiny Core: hello from a libc-free process' /tmp/flow-service-serial.log + - name: Probe upstream eBPF and BTF kernel configuration metadata + continue-on-error: true + run: | + CONFIG=/tmp/tinycore/config-6.18.35-tinycore64 + urls=( + 'https://repo.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + 'https://www.tinycorelinux.net/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + 'https://ftp.icm.edu.pl/packages/linux-tinycorelinux/17.x/x86_64/release/src/kernel/config-6.18.35-tinycore64' + ) + found=0 + for url in "${urls[@]}"; do + if curl --fail --location --connect-timeout 8 --max-time 30 --output "$CONFIG.part" "$url"; then + mv "$CONFIG.part" "$CONFIG" + echo "kernel_config_source=$url" | tee /tmp/tinycore/config-source.txt + found=1 + break + fi + rm -f "$CONFIG.part" + done + if [[ "$found" -ne 1 ]]; then + echo 'Kernel config metadata unavailable; boot/service validation remains authoritative for this job.' >&2 + exit 1 + fi + + grep -E '^(CONFIG_BPF|CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_KPROBES|CONFIG_BPF_EVENTS|CONFIG_DEBUG_INFO_BTF)=' \ + "$CONFIG" | tee /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_SYSCALL=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_JIT=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_KPROBES=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_BPF_EVENTS=y' /tmp/tinycore/bpf-config.txt + grep -Fx 'CONFIG_DEBUG_INFO_BTF=y' /tmp/tinycore/bpf-config.txt + - name: Upload verification artifacts if: always() uses: actions/upload-artifact@v4 From 6b397c79bf85030d687ced3e911821b63884d81b Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:26:01 +0100 Subject: [PATCH 37/64] Prefer healthy Tiny Core mirrors --- tinycore/fetch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tinycore/fetch.sh b/tinycore/fetch.sh index 8b9b691..53f580c 100644 --- a/tinycore/fetch.sh +++ b/tinycore/fetch.sh @@ -10,9 +10,9 @@ TC_FETCH_TIMEOUT="${TC_FETCH_TIMEOUT:-90}" OUT="${1:-$ROOT/build/tinycore}" BASE_URLS=( - "https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" "https://ftp.icm.edu.pl/packages/linux-tinycorelinux/${TC_MAJOR}/x86_64/release/distribution_files" - "https://ftp.dk.xemacs.org/mirrors/mirrors/pub/tinycorelinux/${TC_MAJOR}/x86_64/release/distribution_files" + "https://repo.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" + "https://www.tinycorelinux.net/${TC_MAJOR}/x86_64/release/distribution_files" ) mkdir -p "$OUT" From c86c74dc90dfed712a6f54f92a6fc910345ee9c8 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:28:52 +0100 Subject: [PATCH 38/64] Fix libc-free Flow syscall shim --- examples/hello.flow | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hello.flow b/examples/hello.flow index c4c12b8..29ab6a1 100644 --- a/examples/hello.flow +++ b/examples/hello.flow @@ -7,9 +7,9 @@ typedef unsigned long flow_u64; typedef long flow_i64; -flow_i64 flow_hello_write(const void* data, flow_u64 count) { +flow_i64 flow_hello_write(char* data, flow_u64 count) { flow_i64 r; - __asm__ volatile (\"syscall\" : \"=a\"(r) : \"a\"(1), \"D\"(1), \"S\"(data), \"d\"(count) : \"rcx\", \"r11\", \"memory\"); + __asm__ volatile ("syscall" : "=a"(r) : "a"(1), "D"(1), "S"(data), "d"(count) : "rcx", "r11", "memory"); return r; } ") From 5dd423df6a3be3d4c9e96f43fd888472ae60c6b0 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:31:15 +0100 Subject: [PATCH 39/64] Keep libc-free hello logic in pure Flow --- examples/hello.flow | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/examples/hello.flow b/examples/hello.flow index 29ab6a1..44de4d0 100644 --- a/examples/hello.flow +++ b/examples/hello.flow @@ -1,18 +1,7 @@ # Minimal Flow userspace service for Tiny Core CorePure64. # -# The service uses the Linux syscall ABI directly and requires no libc or -# dynamic loader. `_start` is supplied by examples/start.S. - -@cEmbed(" -typedef unsigned long flow_u64; -typedef long flow_i64; - -flow_i64 flow_hello_write(char* data, flow_u64 count) { - flow_i64 r; - __asm__ volatile ("syscall" : "=a"(r) : "a"(1), "D"(1), "S"(data), "d"(count) : "rcx", "r11", "memory"); - return r; -} -") +# The architecture-specific syscall instruction lives in examples/syscall.c; +# Flow owns the service logic and the stable extern boundary. extern { function flow_hello_write(data: string, count: u64) -> i64 From 8c9bffc5419357275e0328564f4f06c0e91f1b48 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:31:23 +0100 Subject: [PATCH 40/64] Add libc-free x86_64 syscall shim --- examples/syscall.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/syscall.c diff --git a/examples/syscall.c b/examples/syscall.c new file mode 100644 index 0000000..6f2925e --- /dev/null +++ b/examples/syscall.c @@ -0,0 +1,14 @@ +typedef unsigned long flow_u64; +typedef long flow_i64; + +flow_i64 flow_hello_write(char *data, flow_u64 count) +{ + flow_i64 result; + __asm__ volatile ( + "syscall" + : "=a"(result) + : "a"(1), "D"(1), "S"(data), "d"(count) + : "rcx", "r11", "memory" + ); + return result; +} From ca020aed1633f0f214fba35ea3ed5a182b0a322e Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:31:35 +0100 Subject: [PATCH 41/64] Link libc-free syscall shim into Flow service --- examples/build-hello.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/build-hello.sh b/examples/build-hello.sh index a3503ab..2806310 100644 --- a/examples/build-hello.sh +++ b/examples/build-hello.sh @@ -29,6 +29,18 @@ clang \ -c "$OUT/hello.c" \ -o "$OUT/hello-flow.o" +clang \ + -target x86_64-linux-gnu \ + -std=c11 \ + -ffreestanding \ + -fno-builtin \ + -fno-stack-protector \ + -fno-pic \ + -fno-pie \ + -O2 \ + -c "$ROOT/examples/syscall.c" \ + -o "$OUT/syscall.o" + clang \ -target x86_64-linux-gnu \ -ffreestanding \ @@ -43,10 +55,14 @@ ld.lld \ -e _start \ "$OUT/start.o" \ "$OUT/hello-flow.o" \ + "$OUT/syscall.o" \ -o "$OUT/flow-hello" if command -v readelf >/dev/null 2>&1; then - readelf -l "$OUT/flow-hello" | grep -qv 'Requesting program interpreter' + if readelf -l "$OUT/flow-hello" | grep -F 'Requesting program interpreter'; then + echo 'flow-hello unexpectedly requires a dynamic loader' >&2 + exit 1 + fi fi printf '%s\n' "$OUT/flow-hello" From a20e33c5f16a2e5b2ebc8d1806a0086ccb23db49 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 14:33:27 +0100 Subject: [PATCH 42/64] Run Flow hello as initramfs PID 1 --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76f7fc3..cc6bcbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,6 @@ jobs: echo "QEMU exited unexpectedly with status $rc" >&2 exit "$rc" fi - grep -F 'Linux version 6.18.35-tinycore64' /tmp/tinycore-serial.log - name: Checkout Flow compiler externally @@ -124,7 +123,7 @@ jobs: -m 256M \ -kernel /tmp/tinycore/vmlinuz64 \ -initrd /tmp/flow-corepure64.gz \ - -append 'console=ttyS0 init=/opt/flow-hello' \ + -append 'console=ttyS0 rdinit=/opt/flow-hello' \ -serial file:/tmp/flow-service-serial.log \ -display none \ -no-reboot \ @@ -137,7 +136,6 @@ jobs: echo "QEMU exited unexpectedly with status $rc" >&2 exit "$rc" fi - grep -F 'Flow on Tiny Core: hello from a libc-free process' /tmp/flow-service-serial.log - name: Probe upstream eBPF and BTF kernel configuration metadata From 5fb41e76034679db9a1a43840937f4d1eff8c825 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 16:47:12 +0100 Subject: [PATCH 43/64] Add ordered Linux boot diagnostic contract --- diagnostics/boot-sequence.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 diagnostics/boot-sequence.json diff --git a/diagnostics/boot-sequence.json b/diagnostics/boot-sequence.json new file mode 100644 index 0000000..9162db1 --- /dev/null +++ b/diagnostics/boot-sequence.json @@ -0,0 +1,29 @@ +{ + "schema": 1, + "sequence": [ + {"id": "kernel", "marker": "Linux version 6.18.35-tinycore64", "description": "Linux kernel entered and serial console is alive"}, + {"id": "initramfs", "marker": "Trying to unpack rootfs image as initramfs", "description": "Kernel reached initramfs unpack"}, + {"id": "pid1", "marker": "FLOW_DIAG 010 PID1_START OK", "description": "Diagnostic init is executing as PID 1"}, + {"id": "proc", "marker": "FLOW_DIAG 020 PROCFS OK", "description": "procfs mounted and PID 1 visible"}, + {"id": "sys", "marker": "FLOW_DIAG 030 SYSFS OK", "description": "sysfs mounted and kernel device model visible"}, + {"id": "write", "marker": "FLOW_DIAG 040 WRITE_TEST OK", "description": "Early userspace has writable temporary storage"}, + {"id": "cpu_mem", "marker": "FLOW_DIAG 050 CPU_MEMORY OK", "description": "CPU and memory accounting are sane"}, + {"id": "clock", "marker": "FLOW_DIAG 060 CLOCK OK", "description": "Kernel clock is readable and non-zero"}, + {"id": "devices", "marker": "FLOW_DIAG 070 DEVICES OK", "description": "Core device/sysfs model is available"}, + {"id": "network", "marker": "FLOW_DIAG 080 NETWORK OK", "description": "Network stack and loopback interface are present"}, + {"id": "bpf", "marker": "FLOW_DIAG 090 BPF OK", "description": "Kernel exposes BPF filesystem support or BPF syscall capability metadata"}, + {"id": "flow", "marker": "FLOW_DIAG 100 FLOW_EXEC OK", "description": "A libc-free Flow executable ran successfully"}, + {"id": "complete", "marker": "FLOW_DIAG 110 COMPLETE OK", "description": "All mandatory diagnostics completed in order"} + ], + "fatal_patterns": [ + "Kernel panic", + "not syncing", + "BUG:", + "Oops:", + "general protection fault", + "segfault at", + "Unable to mount root fs", + "No working init found", + "Attempted to kill init" + ] +} From 5223f24d5d8850b3f89e86aa45f9cf6bc03d4203 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 16:47:24 +0100 Subject: [PATCH 44/64] Add ordered boot log verifier --- diagnostics/check_boot.py | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 diagnostics/check_boot.py diff --git a/diagnostics/check_boot.py b/diagnostics/check_boot.py new file mode 100644 index 0000000..92ba833 --- /dev/null +++ b/diagnostics/check_boot.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + + +def load_contract(path: Path) -> dict: + with path.open("r", encoding="utf-8") as handle: + return json.load(handle) + + +def main() -> int: + parser = argparse.ArgumentParser(description="Verify an ordered Linux boot diagnostic sequence.") + parser.add_argument("log", type=Path) + parser.add_argument( + "--contract", + type=Path, + default=Path(__file__).with_name("boot-sequence.json"), + ) + parser.add_argument("--report", type=Path) + args = parser.parse_args() + + text = args.log.read_text(encoding="utf-8", errors="replace") + contract = load_contract(args.contract) + + failures: list[str] = [] + evidence: list[dict[str, object]] = [] + + lower_text = text.lower() + for pattern in contract["fatal_patterns"]: + if pattern.lower() in lower_text: + failures.append(f"fatal boot pattern present: {pattern}") + + cursor = -1 + for stage in contract["sequence"]: + marker = stage["marker"] + position = text.find(marker, cursor + 1) + ok = position >= 0 + if not ok: + failures.append(f"missing or out-of-order stage {stage['id']}: {marker}") + else: + cursor = position + evidence.append( + { + "id": stage["id"], + "description": stage["description"], + "marker": marker, + "ok": ok, + "offset": position, + } + ) + + report = { + "schema": contract.get("schema", 1), + "log": str(args.log), + "ok": not failures, + "stages": evidence, + "failures": failures, + } + + rendered = json.dumps(report, indent=2) + if args.report: + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(rendered + "\n", encoding="utf-8") + + print(rendered) + return 0 if not failures else 1 + + +if __name__ == "__main__": + sys.exit(main()) From 0fdf4a47788ff6faf3ad01daa5858e94360d6283 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 16:47:39 +0100 Subject: [PATCH 45/64] Add PID 1 boot diagnostics --- diagnostics/init.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 diagnostics/init.sh diff --git a/diagnostics/init.sh b/diagnostics/init.sh new file mode 100644 index 0000000..7545d24 --- /dev/null +++ b/diagnostics/init.sh @@ -0,0 +1,68 @@ +#!/bin/sh +set -eu + +mark () +{ + printf 'FLOW_DIAG %s %s OK\n' "$1" "$2" +} + +fail () +{ + printf 'FLOW_DIAG FAIL %s\n' "$1" >&2 + exec sh +} + +[ "$$" -eq 1 ] || fail "diagnostic init is not PID 1" +mark 010 PID1_START + +mkdir -p /proc /sys /dev /tmp +mount -t proc proc /proc || fail "cannot mount procfs" +[ -r /proc/1/status ] || fail "PID 1 missing from procfs" +mark 020 PROCFS + +mount -t sysfs sysfs /sys || fail "cannot mount sysfs" +[ -d /sys/devices ] || fail "sysfs device model missing" +mark 030 SYSFS + +printf 'flow-kernel-diagnostic\n' >/tmp/flow-write-test || fail "cannot write /tmp" +grep -q 'flow-kernel-diagnostic' /tmp/flow-write-test || fail "write test mismatch" +mark 040 WRITE_TEST + +[ -r /proc/cpuinfo ] || fail "cpuinfo unavailable" +[ -r /proc/meminfo ] || fail "meminfo unavailable" +grep -q '^processor' /proc/cpuinfo || fail "no CPU reported" +awk '/^MemTotal:/ { if ($2 > 0) ok=1 } END { exit ok ? 0 : 1 }' /proc/meminfo || fail "invalid MemTotal" +mark 050 CPU_MEMORY + +uptime_ticks="$(cut -d. -f1 /proc/uptime 2>/dev/null || echo 0)" +[ "${uptime_ticks:-0}" -ge 0 ] || fail "clock unavailable" +mark 060 CLOCK + +[ -d /sys/class ] || fail "sysfs classes missing" +[ -e /dev/console ] || mknod /dev/console c 5 1 || fail "console device unavailable" +mark 070 DEVICES + +if [ -d /sys/class/net/lo ]; then + mark 080 NETWORK +else + fail "loopback interface missing" +fi + +if grep -qE '(^|[[:space:]])bpf([[:space:]]|$)' /proc/filesystems 2>/dev/null; then + mark 090 BPF +elif [ -e /proc/sys/kernel/unprivileged_bpf_disabled ]; then + mark 090 BPF +else + fail "BPF capability evidence missing" +fi + +[ -x /opt/flow-hello ] || fail "Flow smoke binary missing" +/opt/flow-hello || fail "Flow smoke binary failed" +mark 100 FLOW_EXEC + +mark 110 COMPLETE + +while : +do + sleep 3600 + done From 855348369d61d8f5fd49140e505969cfaccff765 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 16:48:13 +0100 Subject: [PATCH 46/64] Run ordered boot health diagnostics in QEMU --- .github/workflows/ci.yml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc6bcbc..5dc4af9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,11 +100,12 @@ jobs: ! readelf -l /tmp/flow-hello-build/flow-hello | grep -F 'Requesting program interpreter' ! nm -u /tmp/flow-hello-build/flow-hello | grep . - - name: Add Flow service to CorePure64 initramfs + - name: Add diagnostic init and Flow service to CorePure64 run: | mkdir -p /tmp/flow-overlay/opt cp /tmp/flow-hello-build/flow-hello /tmp/flow-overlay/opt/flow-hello - chmod 0755 /tmp/flow-overlay/opt/flow-hello + cp diagnostics/init.sh /tmp/flow-overlay/opt/flow-diag-init + chmod 0755 /tmp/flow-overlay/opt/flow-hello /tmp/flow-overlay/opt/flow-diag-init gzip -dc /tmp/tinycore/corepure64.gz > /tmp/flow-corepure64.cpio ( @@ -114,29 +115,32 @@ jobs: gzip -9 < /tmp/flow-corepure64.cpio > /tmp/flow-corepure64.gz gzip -t /tmp/flow-corepure64.gz - - name: Run Flow process inside CorePure64 + - name: Run ordered boot health sequence run: | set +e - timeout 15s qemu-system-x86_64 \ + timeout 20s qemu-system-x86_64 \ -machine accel=tcg \ -cpu max \ -m 256M \ -kernel /tmp/tinycore/vmlinuz64 \ -initrd /tmp/flow-corepure64.gz \ - -append 'console=ttyS0 rdinit=/opt/flow-hello' \ - -serial file:/tmp/flow-service-serial.log \ + -append 'console=ttyS0 rdinit=/opt/flow-diag-init' \ + -serial file:/tmp/flow-diagnostics-serial.log \ -display none \ -no-reboot \ -no-shutdown rc=$? set -e - cat /tmp/flow-service-serial.log + cat /tmp/flow-diagnostics-serial.log if [[ "$rc" -ne 0 && "$rc" -ne 124 ]]; then echo "QEMU exited unexpectedly with status $rc" >&2 exit "$rc" fi - grep -F 'Flow on Tiny Core: hello from a libc-free process' /tmp/flow-service-serial.log + + python3 diagnostics/check_boot.py \ + /tmp/flow-diagnostics-serial.log \ + --report /tmp/boot-health.json - name: Probe upstream eBPF and BTF kernel configuration metadata continue-on-error: true @@ -178,7 +182,8 @@ jobs: name: tinycore-x86_64-verification path: | /tmp/tinycore-serial.log - /tmp/flow-service-serial.log + /tmp/flow-diagnostics-serial.log + /tmp/boot-health.json /tmp/tinycore/manifest.txt /tmp/tinycore/config-6.18.35-tinycore64 /tmp/tinycore/config-source.txt From 4c69a0c5f523a3006ee1de0f21736e37faa1b42d Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 17:12:13 +0100 Subject: [PATCH 47/64] Expand ordered Linux health contract --- diagnostics/boot-sequence.json | 49 +++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/diagnostics/boot-sequence.json b/diagnostics/boot-sequence.json index 9162db1..8fec0af 100644 --- a/diagnostics/boot-sequence.json +++ b/diagnostics/boot-sequence.json @@ -1,19 +1,30 @@ { - "schema": 1, + "schema": 2, + "kernel_version": "6.18.35-tinycore64", "sequence": [ - {"id": "kernel", "marker": "Linux version 6.18.35-tinycore64", "description": "Linux kernel entered and serial console is alive"}, - {"id": "initramfs", "marker": "Trying to unpack rootfs image as initramfs", "description": "Kernel reached initramfs unpack"}, - {"id": "pid1", "marker": "FLOW_DIAG 010 PID1_START OK", "description": "Diagnostic init is executing as PID 1"}, - {"id": "proc", "marker": "FLOW_DIAG 020 PROCFS OK", "description": "procfs mounted and PID 1 visible"}, - {"id": "sys", "marker": "FLOW_DIAG 030 SYSFS OK", "description": "sysfs mounted and kernel device model visible"}, - {"id": "write", "marker": "FLOW_DIAG 040 WRITE_TEST OK", "description": "Early userspace has writable temporary storage"}, - {"id": "cpu_mem", "marker": "FLOW_DIAG 050 CPU_MEMORY OK", "description": "CPU and memory accounting are sane"}, - {"id": "clock", "marker": "FLOW_DIAG 060 CLOCK OK", "description": "Kernel clock is readable and non-zero"}, - {"id": "devices", "marker": "FLOW_DIAG 070 DEVICES OK", "description": "Core device/sysfs model is available"}, - {"id": "network", "marker": "FLOW_DIAG 080 NETWORK OK", "description": "Network stack and loopback interface are present"}, - {"id": "bpf", "marker": "FLOW_DIAG 090 BPF OK", "description": "Kernel exposes BPF filesystem support or BPF syscall capability metadata"}, - {"id": "flow", "marker": "FLOW_DIAG 100 FLOW_EXEC OK", "description": "A libc-free Flow executable ran successfully"}, - {"id": "complete", "marker": "FLOW_DIAG 110 COMPLETE OK", "description": "All mandatory diagnostics completed in order"} + {"id":"kernel","kind":"log","marker":"Linux version 6.18.35-tinycore64","severity":"required","description":"Linux kernel entered and serial console is alive"}, + {"id":"initramfs","kind":"log","marker":"Trying to unpack rootfs image as initramfs","severity":"required","description":"Kernel reached initramfs unpack"}, + {"id":"pid1","kind":"diag","seq":"010","name":"PID1_START","severity":"required","description":"Diagnostic init is executing as PID 1"}, + {"id":"procfs","kind":"diag","seq":"020","name":"PROCFS","severity":"required","description":"procfs mounted and PID 1 is visible"}, + {"id":"sysfs","kind":"diag","seq":"030","name":"SYSFS","severity":"required","description":"sysfs mounted and kernel device model is visible"}, + {"id":"devices","kind":"diag","seq":"040","name":"DEVICES","severity":"required","description":"core character devices and sysfs classes are available"}, + {"id":"write","kind":"diag","seq":"050","name":"WRITE_TEST","severity":"required","description":"early userspace can create and verify writable state"}, + {"id":"cpu","kind":"diag","seq":"060","name":"CPU","severity":"required","description":"at least one CPU is enumerated"}, + {"id":"memory","kind":"diag","seq":"070","name":"MEMORY","severity":"required","description":"memory accounting is present and non-zero"}, + {"id":"clock","kind":"diag","seq":"080","name":"CLOCK_TIMER","severity":"required","description":"monotonic uptime advances across a sleep"}, + {"id":"rng","kind":"diag","seq":"090","name":"RNG","severity":"required","description":"kernel random source can produce bytes"}, + {"id":"process","kind":"diag","seq":"100","name":"PROCESS","severity":"required","description":"process creation and wait status work"}, + {"id":"signal","kind":"diag","seq":"110","name":"SIGNAL","severity":"required","description":"signal delivery terminates a child process"}, + {"id":"pipe","kind":"diag","seq":"120","name":"PIPE_IPC","severity":"required","description":"pipe-based IPC transfers data"}, + {"id":"filesystem","kind":"diag","seq":"130","name":"FILESYSTEM","severity":"required","description":"create/read/write/rename/link filesystem operations work"}, + {"id":"block","kind":"diag","seq":"140","name":"BLOCK","severity":"advisory","description":"kernel exposes at least one block-device class entry"}, + {"id":"network","kind":"diag","seq":"150","name":"NETWORK","severity":"required","description":"loopback interface and network procfs state exist"}, + {"id":"dns","kind":"diag","seq":"160","name":"DNS","severity":"advisory","description":"resolver configuration contains a nameserver"}, + {"id":"namespace","kind":"diag","seq":"170","name":"NAMESPACES","severity":"required","description":"Linux namespace handles are exposed"}, + {"id":"cgroup","kind":"diag","seq":"180","name":"CGROUP","severity":"advisory","description":"cgroup filesystem capability is present"}, + {"id":"bpf","kind":"diag","seq":"190","name":"BPF","severity":"required","description":"kernel exposes BPF syscall/filesystem capability evidence"}, + {"id":"flow","kind":"diag","seq":"200","name":"FLOW_EXEC","severity":"required","description":"libc-free Flow executable ran successfully"}, + {"id":"complete","kind":"diag","seq":"210","name":"COMPLETE","severity":"required","description":"all required diagnostic stages completed in order"} ], "fatal_patterns": [ "Kernel panic", @@ -24,6 +35,12 @@ "segfault at", "Unable to mount root fs", "No working init found", - "Attempted to kill init" - ] + "Attempted to kill init", + "FLOW_DIAG FAIL" + ], + "timing_policy": { + "warn_regression_ratio": 1.5, + "fail_regression_ratio": 3.0, + "absolute_slack_ms": 250 + } } From 897e9baf1cbfd395ca992e8be323bdbb859495f3 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 17:12:33 +0100 Subject: [PATCH 48/64] Expand PID 1 Linux subsystem diagnostics --- diagnostics/init.sh | 128 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 26 deletions(-) diff --git a/diagnostics/init.sh b/diagnostics/init.sh index 7545d24..94c16cd 100644 --- a/diagnostics/init.sh +++ b/diagnostics/init.sh @@ -1,68 +1,144 @@ #!/bin/sh set -eu +now_ms () +{ + if [ -r /proc/uptime ]; then + awk '{ split($1, a, "."); frac=a[2] "000"; printf "%d", (a[1] * 1000) + substr(frac, 1, 3) }' /proc/uptime + else + printf '0' + fi +} + mark () { - printf 'FLOW_DIAG %s %s OK\n' "$1" "$2" + printf 'FLOW_DIAG %s %s %s t_ms=%s\n' "$1" "$2" "$3" "$(now_ms)" } fail () { - printf 'FLOW_DIAG FAIL %s\n' "$1" >&2 - exec sh + printf 'FLOW_DIAG FAIL %s t_ms=%s\n' "$1" "$(now_ms)" >&2 + while :; do sleep 3600; done +} + +advisory () +{ + mark "$1" "$2" WARN } [ "$$" -eq 1 ] || fail "diagnostic init is not PID 1" -mark 010 PID1_START +mark 010 PID1_START OK -mkdir -p /proc /sys /dev /tmp +mkdir -p /proc /sys /dev /tmp /run /sys/fs/cgroup mount -t proc proc /proc || fail "cannot mount procfs" [ -r /proc/1/status ] || fail "PID 1 missing from procfs" -mark 020 PROCFS +mark 020 PROCFS OK mount -t sysfs sysfs /sys || fail "cannot mount sysfs" [ -d /sys/devices ] || fail "sysfs device model missing" -mark 030 SYSFS +mark 030 SYSFS OK + +[ -d /sys/class ] || fail "sysfs classes missing" +[ -e /dev/null ] || mknod /dev/null c 1 3 || fail "cannot create /dev/null" +[ -e /dev/console ] || mknod /dev/console c 5 1 || fail "cannot create /dev/console" +[ -e /dev/urandom ] || mknod /dev/urandom c 1 9 || fail "cannot create /dev/urandom" +mark 040 DEVICES OK printf 'flow-kernel-diagnostic\n' >/tmp/flow-write-test || fail "cannot write /tmp" -grep -q 'flow-kernel-diagnostic' /tmp/flow-write-test || fail "write test mismatch" -mark 040 WRITE_TEST +grep -q '^flow-kernel-diagnostic$' /tmp/flow-write-test || fail "write test mismatch" +mark 050 WRITE_TEST OK [ -r /proc/cpuinfo ] || fail "cpuinfo unavailable" -[ -r /proc/meminfo ] || fail "meminfo unavailable" grep -q '^processor' /proc/cpuinfo || fail "no CPU reported" +mark 060 CPU OK + +[ -r /proc/meminfo ] || fail "meminfo unavailable" awk '/^MemTotal:/ { if ($2 > 0) ok=1 } END { exit ok ? 0 : 1 }' /proc/meminfo || fail "invalid MemTotal" -mark 050 CPU_MEMORY +mark 070 MEMORY OK -uptime_ticks="$(cut -d. -f1 /proc/uptime 2>/dev/null || echo 0)" -[ "${uptime_ticks:-0}" -ge 0 ] || fail "clock unavailable" -mark 060 CLOCK +before="$(cut -d. -f1 /proc/uptime)" +sleep 1 +after="$(cut -d. -f1 /proc/uptime)" +[ "$after" -gt "$before" ] || fail "monotonic clock did not advance" +mark 080 CLOCK_TIMER OK -[ -d /sys/class ] || fail "sysfs classes missing" -[ -e /dev/console ] || mknod /dev/console c 5 1 || fail "console device unavailable" -mark 070 DEVICES +rm -f /tmp/flow-rng +dd if=/dev/urandom of=/tmp/flow-rng bs=16 count=1 2>/dev/null || fail "cannot read urandom" +[ "$(wc -c /dev/null +rc=$? +set -e +[ "$rc" -ne 0 ] || fail "signal did not terminate child" +mark 110 SIGNAL OK + +printf 'flow-pipe-test\n' | grep -q '^flow-pipe-test$' || fail "pipe IPC failed" +mark 120 PIPE_IPC OK + +rm -rf /tmp/flow-fs +mkdir /tmp/flow-fs || fail "mkdir failed" +printf 'abc123\n' >/tmp/flow-fs/a || fail "file create failed" +grep -q '^abc123$' /tmp/flow-fs/a || fail "file read failed" +mv /tmp/flow-fs/a /tmp/flow-fs/b || fail "rename failed" +ln /tmp/flow-fs/b /tmp/flow-fs/c || fail "hard link failed" +cmp /tmp/flow-fs/b /tmp/flow-fs/c || fail "linked file mismatch" +mark 130 FILESYSTEM OK + +if [ -d /sys/class/block ] && [ -n "$(ls -A /sys/class/block 2>/dev/null)" ]; then + mark 140 BLOCK OK +else + advisory 140 BLOCK +fi + +if [ -d /sys/class/net/lo ] && [ -r /proc/net/dev ]; then + mark 150 NETWORK OK +else + fail "loopback/network stack missing" +fi + +if [ -r /etc/resolv.conf ] && grep -q '^[[:space:]]*nameserver[[:space:]]' /etc/resolv.conf; then + mark 160 DNS OK +else + advisory 160 DNS +fi + +[ -e /proc/self/ns/mnt ] || fail "mount namespace handle missing" +[ -e /proc/self/ns/pid ] || fail "pid namespace handle missing" +[ -e /proc/self/ns/net ] || fail "network namespace handle missing" +mark 170 NAMESPACES OK -if [ -d /sys/class/net/lo ]; then - mark 080 NETWORK +if grep -qE '(^|[[:space:]])cgroup2?($|[[:space:]])' /proc/filesystems 2>/dev/null; then + mark 180 CGROUP OK else - fail "loopback interface missing" + advisory 180 CGROUP fi -if grep -qE '(^|[[:space:]])bpf([[:space:]]|$)' /proc/filesystems 2>/dev/null; then - mark 090 BPF +if grep -qE '(^|[[:space:]])bpf($|[[:space:]])' /proc/filesystems 2>/dev/null; then + mark 190 BPF OK elif [ -e /proc/sys/kernel/unprivileged_bpf_disabled ]; then - mark 090 BPF + mark 190 BPF OK else fail "BPF capability evidence missing" fi [ -x /opt/flow-hello ] || fail "Flow smoke binary missing" /opt/flow-hello || fail "Flow smoke binary failed" -mark 100 FLOW_EXEC +mark 200 FLOW_EXEC OK -mark 110 COMPLETE +mark 210 COMPLETE OK +printf 'FLOW_DIAG SUMMARY HEALTHY t_ms=%s\n' "$(now_ms)" while : do sleep 3600 - done +done From 6c852c25d1111ce0feda95d3064bd3e1e3eff325 Mon Sep 17 00:00:00 2001 From: Abhishek Shivakumar Date: Mon, 17 Aug 2026 17:12:50 +0100 Subject: [PATCH 49/64] Report ordered health stages, timings and degradation --- diagnostics/check_boot.py | 80 +++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/diagnostics/check_boot.py b/diagnostics/check_boot.py index 92ba833..0404116 100644 --- a/diagnostics/check_boot.py +++ b/diagnostics/check_boot.py @@ -3,9 +3,15 @@ import argparse import json +import re import sys from pathlib import Path +DIAG_RE = re.compile( + r"FLOW_DIAG\s+(?P\d{3})\s+(?P[A-Z0-9_]+)\s+" + r"(?POK|WARN)\s+t_ms=(?P