This commit is contained in:
2026-04-10 20:40:28 +08:00
parent 30b2a126c5
commit d023ee8459
13 changed files with 404 additions and 20 deletions

13
clks/include/clks/kelf.h Normal file
View 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

View File

@@ -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 {

View File

@@ -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
View 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;
}

View File

@@ -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);

View File

@@ -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());

View File

@@ -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;
}