mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 10
This commit is contained in:
46
Makefile
46
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 $@)
|
||||
|
||||
8
cleonos/c/apps/elfrunner_kmain.c
Normal file
8
cleonos/c/apps/elfrunner_kmain.c
Normal file
@@ -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;
|
||||
}
|
||||
8
cleonos/c/apps/memc_kmain.c
Normal file
8
cleonos/c/apps/memc_kmain.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
29
cleonos/c/kelf.ld
Normal file
29
cleonos/c/kelf.ld
Normal file
@@ -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
|
||||
}
|
||||
13
clks/include/clks/kelf.h
Normal file
13
clks/include/clks/kelf.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef CLKS_KELF_H
|
||||
#define CLKS_KELF_H
|
||||
|
||||
#include <clks/types.h>
|
||||
|
||||
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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
254
clks/kernel/kelf.c
Normal file
254
clks/kernel/kelf.c
Normal file
@@ -0,0 +1,254 @@
|
||||
#include <clks/elf64.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/string.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
#include <clks/interrupts.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/kernel.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/pmm.h>
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <clks/driver.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/scheduler.h>
|
||||
#include <clks/service.h>
|
||||
@@ -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());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <clks/interrupts.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/scheduler.h>
|
||||
#include <clks/service.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
39
docs/stage10.md
Normal file
39
docs/stage10.md
Normal file
@@ -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`.
|
||||
Reference in New Issue
Block a user