From 901b63b9ba646f0fd0f984baf7d2e39bd36cabf9 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Sun, 12 Apr 2026 19:55:42 +0800 Subject: [PATCH] Stage 26 v2 --- cleonos/c/apps/shell_main.c | 25 +++++++++++++-- clks/arch/x86_64/exec_stack_call.S | 19 ++++++++++++ clks/kernel/exec.c | 50 ++++++++++++++++++------------ clks/kernel/keyboard.c | 9 ++---- clks/kernel/kmain.c | 12 +++++-- clks/kernel/scheduler.c | 15 +++++++-- docs/stage26.md | 5 +-- ramdisk/shell/init.cmd | 3 +- 8 files changed, 102 insertions(+), 36 deletions(-) create mode 100644 clks/arch/x86_64/exec_stack_call.S diff --git a/cleonos/c/apps/shell_main.c b/cleonos/c/apps/shell_main.c index dc03a7d..b33f2e1 100644 --- a/cleonos/c/apps/shell_main.c +++ b/cleonos/c/apps/shell_main.c @@ -242,6 +242,18 @@ static int shell_resolve_exec_path(const char *arg, char *out_path, u64 out_size return 1; } +static int shell_path_is_under_system(const char *path) { + if (path == (const char *)0) { + return 0; + } + + if (path[0] != '/' || path[1] != 's' || path[2] != 'y' || path[3] != 's' || path[4] != 't' || path[5] != 'e' || path[6] != 'm') { + return 0; + } + + return (path[7] == '\0' || path[7] == '/') ? 1 : 0; +} + static void shell_cmd_help(void) { shell_writeln("commands:"); shell_writeln(" help"); @@ -319,12 +331,19 @@ static void shell_cmd_exec(const char *arg) { return; } + if (shell_path_is_under_system(path) != 0) { + shell_writeln("exec: /system/*.elf is kernel-mode (KELF), not user-exec"); + return; + } + status = cleonos_sys_exec_path(path); - if (status == 0ULL) { + if (status == (u64)-1) { + shell_writeln("exec: request failed"); + } else if (status == 0ULL) { shell_writeln("exec: request accepted"); } else { - shell_writeln("exec: request failed"); + shell_writeln("exec: returned non-zero status"); } } @@ -517,4 +536,4 @@ int cleonos_app_main(void) { shell_read_line(line, (u64)sizeof(line)); shell_execute_line(line); } -} \ No newline at end of file +} diff --git a/clks/arch/x86_64/exec_stack_call.S b/clks/arch/x86_64/exec_stack_call.S new file mode 100644 index 0000000..e58e29e --- /dev/null +++ b/clks/arch/x86_64/exec_stack_call.S @@ -0,0 +1,19 @@ +.intel_syntax noprefix + +.global clks_exec_call_on_stack_x86_64 +.type clks_exec_call_on_stack_x86_64, @function + +clks_exec_call_on_stack_x86_64: + mov r11, rsp + mov rsp, rsi + and rsp, -16 + sub rsp, 8 + mov [rsp], r11 + + call rdi + + mov rsp, [rsp] + ret + +.size clks_exec_call_on_stack_x86_64, .-clks_exec_call_on_stack_x86_64 +.section .note.GNU-stack,"",@progbits diff --git a/clks/kernel/exec.c b/clks/kernel/exec.c index c54adec..4f6ebb2 100644 --- a/clks/kernel/exec.c +++ b/clks/kernel/exec.c @@ -1,27 +1,45 @@ #include #include #include +#include #include -#include #include typedef u64 (*clks_exec_entry_fn)(void); -#define CLKS_EXEC_STATUS_UNSUPPORTED 0xFFFFFFFFFFFFFFFEULL +#define CLKS_EXEC_RUN_STACK_BYTES (64ULL * 1024ULL) + +#if defined(CLKS_ARCH_X86_64) +extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top); +#endif static u64 clks_exec_requests = 0ULL; static u64 clks_exec_success = 0ULL; -static clks_bool clks_exec_is_sync_unsupported(const char *path) { - if (path == CLKS_NULL) { +static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) { + if (entry_ptr == CLKS_NULL || out_ret == CLKS_NULL) { return CLKS_FALSE; } - if (clks_strcmp(path, "/shell/shell.elf") == 0) { +#if defined(CLKS_ARCH_X86_64) + { + void *stack_base = clks_kmalloc((usize)CLKS_EXEC_RUN_STACK_BYTES); + void *stack_top; + + if (stack_base == CLKS_NULL) { + clks_log(CLKS_LOG_WARN, "EXEC", "RUN STACK ALLOC FAILED"); + return CLKS_FALSE; + } + + stack_top = (void *)((u8 *)stack_base + (usize)CLKS_EXEC_RUN_STACK_BYTES); + *out_ret = clks_exec_call_on_stack_x86_64(entry_ptr, stack_top); + clks_kfree(stack_base); return CLKS_TRUE; } - - return CLKS_FALSE; +#else + *out_ret = ((clks_exec_entry_fn)entry_ptr)(); + return CLKS_TRUE; +#endif } void clks_exec_init(void) { @@ -49,17 +67,6 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) { return CLKS_FALSE; } - if (clks_exec_is_sync_unsupported(path) == CLKS_TRUE) { - clks_log(CLKS_LOG_WARN, "EXEC", "SYNC EXEC UNSUPPORTED FOR INTERACTIVE ELF"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - - if (out_status != CLKS_NULL) { - *out_status = CLKS_EXEC_STATUS_UNSUPPORTED; - } - - return CLKS_FALSE; - } - image = clks_fs_read_all(path, &image_size); if (image == CLKS_NULL || image_size == 0ULL) { @@ -93,7 +100,12 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) { clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry); clks_log_hex(CLKS_LOG_INFO, "EXEC", "PHNUM", (u64)info.phnum); - run_ret = ((clks_exec_entry_fn)entry_ptr)(); + if (clks_exec_invoke_entry(entry_ptr, &run_ret) == CLKS_FALSE) { + clks_log(CLKS_LOG_WARN, "EXEC", "EXEC RUN INVOKE FAILED"); + clks_log(CLKS_LOG_WARN, "EXEC", path); + clks_elf64_unload(&loaded); + return CLKS_FALSE; + } clks_log(CLKS_LOG_INFO, "EXEC", "RUN RETURNED"); clks_log(CLKS_LOG_INFO, "EXEC", path); diff --git a/clks/kernel/keyboard.c b/clks/kernel/keyboard.c index 770223b..fd3cdb9 100644 --- a/clks/kernel/keyboard.c +++ b/clks/kernel/keyboard.c @@ -174,9 +174,7 @@ void clks_keyboard_handle_scancode(u8 scancode) { clks_kbd_e0_prefix = CLKS_FALSE; if (ext != '\0' && clks_keyboard_shell_input_enabled() == CLKS_TRUE) { - if (clks_keyboard_queue_push(ext) == CLKS_TRUE) { - clks_shell_pump_input(1U); - } + (void)clks_keyboard_queue_push(ext); } return; @@ -204,9 +202,7 @@ void clks_keyboard_handle_scancode(u8 scancode) { char translated = clks_keyboard_translate_scancode(code); if (translated != '\0' && clks_keyboard_shell_input_enabled() == CLKS_TRUE) { - if (clks_keyboard_queue_push(translated) == CLKS_TRUE) { - clks_shell_pump_input(1U); - } + (void)clks_keyboard_queue_push(translated); } } } @@ -242,3 +238,4 @@ u64 clks_keyboard_push_count(void) { u64 clks_keyboard_pop_count(void) { return clks_kbd_pop_count; } + diff --git a/clks/kernel/kmain.c b/clks/kernel/kmain.c index 0cceac6..a2070ed 100644 --- a/clks/kernel/kmain.c +++ b/clks/kernel/kmain.c @@ -232,5 +232,13 @@ void clks_kernel_main(void) { clks_log(CLKS_LOG_INFO, "TTY", "CURSOR ENABLED"); clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER"); - clks_cpu_halt_forever(); -} \ No newline at end of file + for (;;) { + u64 tick_now = clks_interrupts_timer_ticks(); + clks_scheduler_dispatch_current(tick_now); +#if defined(CLKS_ARCH_X86_64) + __asm__ volatile("hlt"); +#elif defined(CLKS_ARCH_AARCH64) + __asm__ volatile("wfe"); +#endif + } +} diff --git a/clks/kernel/scheduler.c b/clks/kernel/scheduler.c index e105a9d..a892341 100644 --- a/clks/kernel/scheduler.c +++ b/clks/kernel/scheduler.c @@ -11,6 +11,7 @@ static u32 clks_task_count = 0; static u32 clks_current_task = 0; static u64 clks_total_timer_ticks = 0; static u64 clks_context_switch_count = 0; +static clks_bool clks_dispatch_active = CLKS_FALSE; static void clks_sched_copy_name(char *dst, const char *src) { u32 i = 0; @@ -43,6 +44,7 @@ void clks_scheduler_init(void) { clks_current_task = 0; clks_total_timer_ticks = 0; clks_context_switch_count = 0; + clks_dispatch_active = CLKS_FALSE; clks_scheduler_add_kernel_task_ex("idle", 1U, CLKS_NULL); @@ -94,6 +96,10 @@ void clks_scheduler_dispatch_current(u64 tick) { return; } + if (clks_dispatch_active == CLKS_TRUE) { + return; + } + current = &clks_tasks[clks_current_task]; if (current->state != CLKS_TASK_RUNNING && current->state != CLKS_TASK_READY) { @@ -105,7 +111,9 @@ void clks_scheduler_dispatch_current(u64 tick) { current->last_run_tick = tick; if (current->entry != CLKS_NULL) { + clks_dispatch_active = CLKS_TRUE; current->entry(tick); + clks_dispatch_active = CLKS_FALSE; } } @@ -117,6 +125,11 @@ void clks_scheduler_on_timer_tick(u64 tick) { } clks_total_timer_ticks = tick; + + if (clks_dispatch_active == CLKS_TRUE) { + return; + } + current = &clks_tasks[clks_current_task]; if (current->state == CLKS_TASK_RUNNING || current->state == CLKS_TASK_READY) { @@ -144,8 +157,6 @@ void clks_scheduler_on_timer_tick(u64 tick) { clks_context_switch_count++; } } - - clks_scheduler_dispatch_current(tick); } struct clks_scheduler_stats clks_scheduler_get_stats(void) { diff --git a/docs/stage26.md b/docs/stage26.md index 22556cf..cc8f701 100644 --- a/docs/stage26.md +++ b/docs/stage26.md @@ -12,6 +12,7 @@ - Updated CMake ramdisk placement rules: - `hello.elf` -> `/hello.elf` - Simplified user Rust library back to shared helper export (`cleonos_rust_guarded_len`). +- Added x86_64 exec stack bridge (`clks_exec_call_on_stack_x86_64`) so ELF entry runs on a dedicated execution stack instead of inheriting deep shell call stack. ## Acceptance Criteria - No `elfloader.elf` is generated or packed. @@ -19,6 +20,7 @@ - In kernel shell: - `elfloader` loads and executes `/hello.elf`, then returns status. - `elfloader /path/to/app.elf` works for other absolute/relative paths. +- `exec /shell/shell.elf` can take foreground control without immediate stack-chain crash. ## Build Targets - `make userapps` @@ -33,5 +35,4 @@ - If `elfloader` reports `file missing`, check ramdisk root packaging for `/hello.elf`. - If it reports `invalid elf64`, verify user app link script and ELF output format. - If it reports `exec failed`, inspect `EXEC` channel logs for load/entry/return status. -- `hello.elf` is supported in current synchronous exec mode. -- `/shell/shell.elf` is intentionally blocked in synchronous mode (interactive loop requires process/task context switching stage). +- For long-running interactive ELF (such as `shell.elf`), no `RUN RETURNED` log is expected unless the app exits. diff --git a/ramdisk/shell/init.cmd b/ramdisk/shell/init.cmd index da99fdd..2c62e92 100644 --- a/ramdisk/shell/init.cmd +++ b/ramdisk/shell/init.cmd @@ -7,6 +7,5 @@ ls / ls /shell ls /system cat /README.txt -run /system/elfrunner.elf -run /system/memc.elf +run /hello.elf stats