From d023ee8459e86ec2e2151188508d54b6d18ad1b7 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Fri, 10 Apr 2026 20:40:28 +0800 Subject: [PATCH] Stage 10 --- Makefile | 46 ++--- cleonos/c/apps/elfrunner_kmain.c | 8 + cleonos/c/apps/memc_kmain.c | 8 + cleonos/c/include/cleonos_syscall.h | 2 + cleonos/c/kelf.ld | 29 ++++ clks/include/clks/kelf.h | 13 ++ clks/include/clks/service.h | 1 + clks/include/clks/syscall.h | 2 + clks/kernel/kelf.c | 254 ++++++++++++++++++++++++++++ clks/kernel/kmain.c | 13 +- clks/kernel/service.c | 4 + clks/kernel/syscall.c | 5 + docs/stage10.md | 39 +++++ 13 files changed, 404 insertions(+), 20 deletions(-) create mode 100644 cleonos/c/apps/elfrunner_kmain.c create mode 100644 cleonos/c/apps/memc_kmain.c create mode 100644 cleonos/c/kelf.ld create mode 100644 clks/include/clks/kelf.h create mode 100644 clks/kernel/kelf.c create mode 100644 docs/stage10.md diff --git a/Makefile b/Makefile index 1297a61..af96502 100644 --- a/Makefile +++ b/Makefile @@ -43,8 +43,10 @@ USER_CC ?= cc USER_LD ?= ld RUSTC ?= rustc USER_LINKER_SCRIPT := cleonos/c/user.ld +KELF_LINKER_SCRIPT := cleonos/c/kelf.ld USER_CFLAGS := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Icleonos/c/include USER_LDFLAGS := -nostdlib -z max-page-size=0x1000 -T $(USER_LINKER_SCRIPT) +KELF_LDFLAGS := -nostdlib -z max-page-size=0x1000 -T $(KELF_LINKER_SCRIPT) ifeq ($(NO_COLOR),1) COLOR_RESET := @@ -93,6 +95,7 @@ C_SOURCES := \ clks/kernel/userland.c \ clks/kernel/driver.c \ clks/kernel/service.c \ + clks/kernel/kelf.c \ clks/lib/string.c \ clks/drivers/serial/serial.c \ clks/drivers/video/framebuffer.c \ @@ -112,11 +115,16 @@ USER_COMMON_SOURCES := \ USER_COMMON_OBJECTS := $(patsubst %.c,$(USER_OBJ_ROOT)/%.o,$(USER_COMMON_SOURCES)) USER_SHELL_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/shell_main.o -USER_ELFRUNNER_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/elfrunner_main.o -USER_MEMC_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/memc_main.o USER_TTYDRV_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/ttydrv_main.o +USER_ELFRUNNER_KOBJ := $(USER_OBJ_ROOT)/cleonos/c/apps/elfrunner_kmain.o +USER_MEMC_KOBJ := $(USER_OBJ_ROOT)/cleonos/c/apps/memc_kmain.o USER_RUST_LIB := $(USER_LIB_DIR)/libcleonos_user_rust.a -USER_APPS := $(USER_APP_DIR)/shell.elf $(USER_APP_DIR)/elfrunner.elf $(USER_APP_DIR)/memc.elf $(USER_APP_DIR)/ttydrv.elf + +APP_SHELL := $(USER_APP_DIR)/shell.elf +APP_TTYDRV := $(USER_APP_DIR)/ttydrv.elf +APP_ELFRUNNER := $(USER_APP_DIR)/elfrunner.elf +APP_MEMC := $(USER_APP_DIR)/memc.elf +USER_APPS := $(APP_SHELL) $(APP_TTYDRV) $(APP_ELFRUNNER) $(APP_MEMC) CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include ASFLAGS_COMMON := -ffreestanding -Iclks/include @@ -206,10 +214,10 @@ ramdisk-root: userapps > @mkdir -p $(RAMDISK_ROOT) > @cp -a ramdisk/. $(RAMDISK_ROOT)/ > @mkdir -p $(RAMDISK_ROOT)/system $(RAMDISK_ROOT)/shell $(RAMDISK_ROOT)/driver -> @cp $(USER_APP_DIR)/shell.elf $(RAMDISK_ROOT)/shell/shell.elf -> @cp $(USER_APP_DIR)/elfrunner.elf $(RAMDISK_ROOT)/system/elfrunner.elf -> @cp $(USER_APP_DIR)/memc.elf $(RAMDISK_ROOT)/system/memc.elf -> @cp $(USER_APP_DIR)/ttydrv.elf $(RAMDISK_ROOT)/driver/ttydrv.elf +> @cp $(APP_SHELL) $(RAMDISK_ROOT)/shell/shell.elf +> @cp $(APP_ELFRUNNER) $(RAMDISK_ROOT)/system/elfrunner.elf +> @cp $(APP_MEMC) $(RAMDISK_ROOT)/system/memc.elf +> @cp $(APP_TTYDRV) $(RAMDISK_ROOT)/driver/ttydrv.elf ramdisk: $(RAMDISK_IMAGE) @@ -238,26 +246,26 @@ $(USER_RUST_LIB): cleonos/rust/src/lib.rs Makefile > @mkdir -p $(dir $@) > @$(RUSTC) --crate-type staticlib -C panic=abort -O $< -o $@ -$(USER_APP_DIR)/shell.elf: $(USER_COMMON_OBJECTS) $(USER_SHELL_OBJECT) $(USER_RUST_LIB) $(USER_LINKER_SCRIPT) +$(APP_SHELL): $(USER_COMMON_OBJECTS) $(USER_SHELL_OBJECT) $(USER_RUST_LIB) $(USER_LINKER_SCRIPT) > $(call log_step,linking user shell.elf) > @mkdir -p $(dir $@) > @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_SHELL_OBJECT) $(USER_RUST_LIB) -$(USER_APP_DIR)/elfrunner.elf: $(USER_COMMON_OBJECTS) $(USER_ELFRUNNER_OBJECT) $(USER_LINKER_SCRIPT) -> $(call log_step,linking user elfrunner.elf) -> @mkdir -p $(dir $@) -> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_ELFRUNNER_OBJECT) - -$(USER_APP_DIR)/memc.elf: $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT) $(USER_LINKER_SCRIPT) -> $(call log_step,linking user memc.elf) -> @mkdir -p $(dir $@) -> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT) - -$(USER_APP_DIR)/ttydrv.elf: $(USER_COMMON_OBJECTS) $(USER_TTYDRV_OBJECT) $(USER_LINKER_SCRIPT) +$(APP_TTYDRV): $(USER_COMMON_OBJECTS) $(USER_TTYDRV_OBJECT) $(USER_LINKER_SCRIPT) > $(call log_step,linking user ttydrv.elf) > @mkdir -p $(dir $@) > @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_TTYDRV_OBJECT) +$(APP_ELFRUNNER): $(USER_ELFRUNNER_KOBJ) $(KELF_LINKER_SCRIPT) +> $(call log_step,linking kernel-elf elfrunner.elf) +> @mkdir -p $(dir $@) +> @$(USER_LD) $(KELF_LDFLAGS) -o $@ $(USER_ELFRUNNER_KOBJ) + +$(APP_MEMC): $(USER_MEMC_KOBJ) $(KELF_LINKER_SCRIPT) +> $(call log_step,linking kernel-elf memc.elf) +> @mkdir -p $(dir $@) +> @$(USER_LD) $(KELF_LDFLAGS) -o $@ $(USER_MEMC_KOBJ) + $(RAMDISK_IMAGE): ramdisk-root Makefile > $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE)) > @mkdir -p $(dir $@) diff --git a/cleonos/c/apps/elfrunner_kmain.c b/cleonos/c/apps/elfrunner_kmain.c new file mode 100644 index 0000000..6903e09 --- /dev/null +++ b/cleonos/c/apps/elfrunner_kmain.c @@ -0,0 +1,8 @@ +typedef unsigned long long u64; + +static u64 clks_local_counter = 0ULL; + +u64 cleonos_kelf_entry(u64 tick, u64 run_count) { + clks_local_counter += (run_count ^ tick) & 0xFFULL; + return clks_local_counter; +} diff --git a/cleonos/c/apps/memc_kmain.c b/cleonos/c/apps/memc_kmain.c new file mode 100644 index 0000000..097c5c4 --- /dev/null +++ b/cleonos/c/apps/memc_kmain.c @@ -0,0 +1,8 @@ +typedef unsigned long long u64; + +static u64 clks_memc_state = 0ULL; + +u64 cleonos_kelf_entry(u64 tick, u64 run_count) { + clks_memc_state += (tick & 0x1FULL) + run_count; + return clks_memc_state; +} diff --git a/cleonos/c/include/cleonos_syscall.h b/cleonos/c/include/cleonos_syscall.h index c7c0a72..22a6e79 100644 --- a/cleonos/c/include/cleonos_syscall.h +++ b/cleonos/c/include/cleonos_syscall.h @@ -11,6 +11,8 @@ typedef unsigned long long usize; #define CLEONOS_SYSCALL_SERVICE_COUNT 4ULL #define CLEONOS_SYSCALL_SERVICE_READY_COUNT 5ULL #define CLEONOS_SYSCALL_CONTEXT_SWITCHES 6ULL +#define CLEONOS_SYSCALL_KELF_COUNT 7ULL +#define CLEONOS_SYSCALL_KELF_RUNS 8ULL u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_sys_log_write(const char *message, u64 length); diff --git a/cleonos/c/kelf.ld b/cleonos/c/kelf.ld new file mode 100644 index 0000000..ddda59d --- /dev/null +++ b/cleonos/c/kelf.ld @@ -0,0 +1,29 @@ +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(cleonos_kelf_entry) + +PHDRS { + text PT_LOAD FLAGS(5); + rodata PT_LOAD FLAGS(4); + data PT_LOAD FLAGS(6); +} + +SECTIONS { + . = 0x0; + + .text : ALIGN(0x1000) { + *(.text .text.*) + } :text + + .rodata : ALIGN(0x1000) { + *(.rodata .rodata.*) + } :rodata + + .data : ALIGN(0x1000) { + *(.data .data.*) + } :data + + .bss : ALIGN(0x1000) { + *(COMMON) + *(.bss .bss.*) + } :data +} diff --git a/clks/include/clks/kelf.h b/clks/include/clks/kelf.h new file mode 100644 index 0000000..0f9eaf7 --- /dev/null +++ b/clks/include/clks/kelf.h @@ -0,0 +1,13 @@ +#ifndef CLKS_KELF_H +#define CLKS_KELF_H + +#include + +typedef u64 (*clks_kelf_entry_fn)(u64 tick, u64 run_count); + +void clks_kelf_init(void); +void clks_kelf_tick(u64 tick); +u64 clks_kelf_count(void); +u64 clks_kelf_total_runs(void); + +#endif diff --git a/clks/include/clks/service.h b/clks/include/clks/service.h index 7f80b78..9c01455 100644 --- a/clks/include/clks/service.h +++ b/clks/include/clks/service.h @@ -11,6 +11,7 @@ enum clks_service_id { CLKS_SERVICE_FS = 3, CLKS_SERVICE_DRIVER = 4, CLKS_SERVICE_SCHED = 5, + CLKS_SERVICE_KELF = 6, }; enum clks_service_state { diff --git a/clks/include/clks/syscall.h b/clks/include/clks/syscall.h index 7f39376..22e1077 100644 --- a/clks/include/clks/syscall.h +++ b/clks/include/clks/syscall.h @@ -10,6 +10,8 @@ #define CLKS_SYSCALL_SERVICE_COUNT 4ULL #define CLKS_SYSCALL_SERVICE_READY_COUNT 5ULL #define CLKS_SYSCALL_CONTEXT_SWITCHES 6ULL +#define CLKS_SYSCALL_KELF_COUNT 7ULL +#define CLKS_SYSCALL_KELF_RUNS 8ULL void clks_syscall_init(void); u64 clks_syscall_dispatch(void *frame_ptr); diff --git a/clks/kernel/kelf.c b/clks/kernel/kelf.c new file mode 100644 index 0000000..fb53df3 --- /dev/null +++ b/clks/kernel/kelf.c @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include +#include + +#define CLKS_KELF_MAX_APPS 8U +#define CLKS_ELF64_PT_LOAD 1U + +struct clks_elf64_ehdr { + u8 e_ident[16]; + u16 e_type; + u16 e_machine; + u32 e_version; + u64 e_entry; + u64 e_phoff; + u64 e_shoff; + u32 e_flags; + u16 e_ehsize; + u16 e_phentsize; + u16 e_phnum; + u16 e_shentsize; + u16 e_shnum; + u16 e_shstrndx; +}; + +struct clks_elf64_phdr { + u32 p_type; + u32 p_flags; + u64 p_offset; + u64 p_vaddr; + u64 p_paddr; + u64 p_filesz; + u64 p_memsz; + u64 p_align; +}; + +struct clks_kelf_app { + clks_bool loaded; + char path[64]; + void *runtime_image; + u64 runtime_size; + clks_kelf_entry_fn entry; + u64 run_count; + u64 last_run_tick; + u64 last_ret; +}; + +static struct clks_kelf_app clks_kelf_apps[CLKS_KELF_MAX_APPS]; +static u64 clks_kelf_app_count = 0ULL; +static u64 clks_kelf_total_runs_count = 0ULL; +static u64 clks_kelf_rr_index = 0ULL; +static u64 clks_kelf_last_dispatch_tick = 0ULL; + +static void clks_kelf_copy_name(char *dst, usize dst_size, const char *src) { + usize i = 0U; + + if (dst == CLKS_NULL || dst_size == 0U) { + return; + } + + while (i + 1U < dst_size && src[i] != '\0') { + dst[i] = src[i]; + i++; + } + + dst[i] = '\0'; +} + +static clks_bool clks_kelf_load_runtime_image(const void *image, + u64 size, + void **out_runtime, + u64 *out_runtime_size, + clks_kelf_entry_fn *out_entry) { + const struct clks_elf64_ehdr *eh; + u64 min_vaddr = 0xffffffffffffffffULL; + u64 max_vaddr = 0ULL; + u16 i; + u8 *runtime; + + if (out_runtime == CLKS_NULL || out_runtime_size == CLKS_NULL || out_entry == CLKS_NULL) { + return CLKS_FALSE; + } + + if (clks_elf64_validate(image, size) == CLKS_FALSE) { + return CLKS_FALSE; + } + + eh = (const struct clks_elf64_ehdr *)image; + + for (i = 0; i < eh->e_phnum; i++) { + const struct clks_elf64_phdr *ph = + (const struct clks_elf64_phdr *)((const u8 *)image + eh->e_phoff + ((u64)i * eh->e_phentsize)); + u64 seg_end; + + if (ph->p_type != CLKS_ELF64_PT_LOAD || ph->p_memsz == 0ULL) { + continue; + } + + if (ph->p_filesz > ph->p_memsz) { + return CLKS_FALSE; + } + + if (ph->p_offset > size || ph->p_filesz > (size - ph->p_offset)) { + return CLKS_FALSE; + } + + seg_end = ph->p_vaddr + ph->p_memsz; + + if (seg_end < ph->p_vaddr) { + return CLKS_FALSE; + } + + if (ph->p_vaddr < min_vaddr) { + min_vaddr = ph->p_vaddr; + } + + if (seg_end > max_vaddr) { + max_vaddr = seg_end; + } + } + + if (max_vaddr <= min_vaddr) { + return CLKS_FALSE; + } + + *out_runtime_size = max_vaddr - min_vaddr; + runtime = (u8 *)clks_kmalloc((usize)(*out_runtime_size)); + + if (runtime == CLKS_NULL) { + return CLKS_FALSE; + } + + clks_memset(runtime, 0, (usize)(*out_runtime_size)); + + for (i = 0; i < eh->e_phnum; i++) { + const struct clks_elf64_phdr *ph = + (const struct clks_elf64_phdr *)((const u8 *)image + eh->e_phoff + ((u64)i * eh->e_phentsize)); + + if (ph->p_type != CLKS_ELF64_PT_LOAD || ph->p_memsz == 0ULL) { + continue; + } + + clks_memcpy(runtime + (usize)(ph->p_vaddr - min_vaddr), + (const u8 *)image + ph->p_offset, + (usize)ph->p_filesz); + } + + if (eh->e_entry < min_vaddr || eh->e_entry >= max_vaddr) { + clks_kfree(runtime); + return CLKS_FALSE; + } + + *out_entry = (clks_kelf_entry_fn)(void *)(runtime + (usize)(eh->e_entry - min_vaddr)); + *out_runtime = runtime; + return CLKS_TRUE; +} + +static void clks_kelf_probe_path(const char *path) { + const void *image; + u64 size = 0ULL; + void *runtime = CLKS_NULL; + u64 runtime_size = 0ULL; + clks_kelf_entry_fn entry = CLKS_NULL; + struct clks_kelf_app *slot; + + if (clks_kelf_app_count >= CLKS_KELF_MAX_APPS) { + return; + } + + image = clks_fs_read_all(path, &size); + + if (image == CLKS_NULL || size == 0ULL) { + clks_log(CLKS_LOG_WARN, "KELF", "APP FILE NOT FOUND"); + clks_log(CLKS_LOG_WARN, "KELF", path); + return; + } + + if (clks_kelf_load_runtime_image(image, size, &runtime, &runtime_size, &entry) == CLKS_FALSE) { + clks_log(CLKS_LOG_ERROR, "KELF", "APP LOAD FAILED"); + clks_log(CLKS_LOG_ERROR, "KELF", path); + return; + } + + slot = &clks_kelf_apps[clks_kelf_app_count]; + clks_memset(slot, 0, sizeof(*slot)); + + slot->loaded = CLKS_TRUE; + clks_kelf_copy_name(slot->path, sizeof(slot->path), path); + slot->runtime_image = runtime; + slot->runtime_size = runtime_size; + slot->entry = entry; + + clks_kelf_app_count++; + + clks_log(CLKS_LOG_INFO, "KELF", "APP READY"); + clks_log(CLKS_LOG_INFO, "KELF", path); + clks_log_hex(CLKS_LOG_INFO, "KELF", "RUNTIME_SIZE", runtime_size); +} + +void clks_kelf_init(void) { + clks_memset(clks_kelf_apps, 0, sizeof(clks_kelf_apps)); + clks_kelf_app_count = 0ULL; + clks_kelf_total_runs_count = 0ULL; + clks_kelf_rr_index = 0ULL; + clks_kelf_last_dispatch_tick = 0ULL; + + clks_kelf_probe_path("/system/elfrunner.elf"); + clks_kelf_probe_path("/system/memc.elf"); + + clks_log(CLKS_LOG_INFO, "KELF", "EXECUTOR ONLINE"); + clks_log_hex(CLKS_LOG_INFO, "KELF", "APP_COUNT", clks_kelf_app_count); +} + +void clks_kelf_tick(u64 tick) { + struct clks_kelf_app *app; + + if (clks_kelf_app_count == 0ULL) { + return; + } + + if (tick - clks_kelf_last_dispatch_tick < 200ULL) { + return; + } + + clks_kelf_last_dispatch_tick = tick; + app = &clks_kelf_apps[clks_kelf_rr_index % clks_kelf_app_count]; + clks_kelf_rr_index++; + + if (app->loaded == CLKS_FALSE || app->entry == CLKS_NULL) { + return; + } + + app->run_count++; + app->last_run_tick = tick; + app->last_ret = app->entry(tick, app->run_count); + clks_kelf_total_runs_count++; + + if ((app->run_count & 0x7ULL) == 1ULL) { + clks_log(CLKS_LOG_DEBUG, "KELF", "APP EXECUTED"); + clks_log(CLKS_LOG_DEBUG, "KELF", app->path); + clks_log_hex(CLKS_LOG_DEBUG, "KELF", "RET", app->last_ret); + } +} + +u64 clks_kelf_count(void) { + return clks_kelf_app_count; +} + +u64 clks_kelf_total_runs(void) { + return clks_kelf_total_runs_count; +} diff --git a/clks/kernel/kmain.c b/clks/kernel/kmain.c index 04e118b..26cb69f 100644 --- a/clks/kernel/kmain.c +++ b/clks/kernel/kmain.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,11 @@ static void clks_task_kworker(u64 tick) { phase = (phase + 1U) & 3U; } +static void clks_task_kelfd(u64 tick) { + clks_service_heartbeat(CLKS_SERVICE_KELF, tick); + clks_kelf_tick(tick); +} + void clks_kernel_main(void) { const struct limine_framebuffer *boot_fb; const struct limine_memmap_response *boot_memmap; @@ -76,7 +82,7 @@ void clks_kernel_main(void) { clks_tty_init(); } - clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE9 START"); + clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE10 START"); if (boot_fb == CLKS_NULL) { clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE"); @@ -144,6 +150,7 @@ void clks_kernel_main(void) { } clks_driver_init(); + clks_kelf_init(); clks_scheduler_init(); @@ -155,6 +162,10 @@ void clks_kernel_main(void) { clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KWORKER TASK"); } + if (clks_scheduler_add_kernel_task_ex("kelfd", 5U, clks_task_kelfd) == CLKS_FALSE) { + clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KELFD TASK"); + } + sched_stats = clks_scheduler_get_stats(); clks_log_hex(CLKS_LOG_INFO, "SCHED", "TASK_COUNT", sched_stats.task_count); diff --git a/clks/kernel/service.c b/clks/kernel/service.c index 8f0b500..750d76f 100644 --- a/clks/kernel/service.c +++ b/clks/kernel/service.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,9 @@ void clks_service_init(void) { clks_service_register(CLKS_SERVICE_SCHED, "scheduler", CLKS_SERVICE_STATE_READY); + clks_service_register(CLKS_SERVICE_KELF, + "kelf", + (clks_kelf_count() > 0ULL) ? CLKS_SERVICE_STATE_READY : CLKS_SERVICE_STATE_DEGRADED); clks_log(CLKS_LOG_INFO, "SRV", "KERNEL SERVICES ONLINE"); clks_log_hex(CLKS_LOG_INFO, "SRV", "COUNT", clks_service_count()); diff --git a/clks/kernel/syscall.c b/clks/kernel/syscall.c index abc5c10..ae89b90 100644 --- a/clks/kernel/syscall.c +++ b/clks/kernel/syscall.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -92,6 +93,10 @@ u64 clks_syscall_dispatch(void *frame_ptr) { struct clks_scheduler_stats stats = clks_scheduler_get_stats(); return stats.context_switch_count; } + case CLKS_SYSCALL_KELF_COUNT: + return clks_kelf_count(); + case CLKS_SYSCALL_KELF_RUNS: + return clks_kelf_total_runs(); default: return (u64)-1; } diff --git a/docs/stage10.md b/docs/stage10.md new file mode 100644 index 0000000..e97364e --- /dev/null +++ b/docs/stage10.md @@ -0,0 +1,39 @@ +# CLeonOS Stage10 + +## Stage Goal +- Upgrade ELF execution from "inspect-only" to "scheduler-driven kernel ELF execution". +- Build `/system/elfrunner.elf` and `/system/memc.elf` as kernel-ELF entry binaries. +- Add CLKS kernel ELF executor (`kelf`) that loads runtime image and dispatches ELF entry. +- Add `kelfd` scheduler task to periodically execute loaded kernel ELF apps. + +## Acceptance Criteria +- Kernel boots and prints `CLEONOS STAGE10 START`. +- KELF framework logs: + - `APP READY` for `/system/elfrunner.elf` and `/system/memc.elf` + - `EXECUTOR ONLINE` + - `APP_COUNT` > 0 +- Service framework includes KELF service and logs updated counts. +- Scheduler task count increases (idle + klogd + kworker + kelfd). +- System remains stable in interrupt-enabled idle loop. + +## Build Targets +- `make setup` +- `make userapps` +- `make iso` +- `make run` +- `make debug` + +## QEMU Command +- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio` + +## Common Bugs and Debugging +- `KELF APP LOAD FAILED`: + - Check `/system/*.elf` are built using `cleonos/c/kelf.ld` and are valid ELF64. +- No `APP READY` logs: + - Verify ramdisk staging copied system ELF files into `/system`. +- `kelfd` task missing: + - Confirm `clks_scheduler_add_kernel_task_ex("kelfd", ...)` is present in `kmain`. +- KELF syscall counters return `-1`: + - Ensure syscall IDs for `KELF_COUNT` and `KELF_RUNS` match kernel/user headers. +- Build errors in Makefile app targets: + - Verify `APP_ELFRUNNER`/`APP_MEMC` link with `KELF_LDFLAGS` not `USER_LDFLAGS`.