From 55ea8fc53379bf0a2947cab1f7ef3c4853c03c60 Mon Sep 17 00:00:00 2001 From: Karina Date: Thu, 29 Jan 2026 21:25:45 +0400 Subject: [PATCH] feat(userspace): userspace support build: updated CMakeLists to build and copy to initramfs wip(syscalls): initial syscalls chore(ksh/kfetch): minor changes chore(gitignore): added initramfs/* --- .gitignore | 3 +- CMakeLists.txt | 3 +- initramfs/test.txt | 1 - initramfs/test1.txt | 1 - kernel/inc/arch/x86_64/cpuinfo.h | 10 ++-- kernel/inc/arch/x86_64/syscall.h | 20 ++++++++ kernel/inc/core/loader.h | 9 ++++ kernel/inc/core/userspace.h | 6 +++ kernel/inc/drivers/shitgui.h | 10 +--- kernel/src/arch/x86_64/cpuinfo.c | 16 +++++- kernel/src/arch/x86_64/entry.asm | 1 + kernel/src/arch/x86_64/syscall.asm | 70 +++++++++++++++++++++++++ kernel/src/arch/x86_64/syscall.c | 66 ++++++++++++++++++++++++ kernel/src/core/loader.c | 82 ++++++++++++++++++++++++++++++ kernel/src/core/scheduler.c | 2 + kernel/src/core/userspace.c | 34 +++++++++++++ kernel/src/drivers/shitgui.c | 63 ----------------------- kernel/src/kmain.c | 26 ++++++++-- kernel/src/shell/builtins.c | 2 +- kernel/src/shell/dbgcmd.c | 50 +----------------- userspace/CMakeLists.txt | 10 ++++ userspace/init/CMakeLists.txt | 32 ++++++++++++ userspace/init/src/entry.asm | 17 +++++++ 23 files changed, 399 insertions(+), 135 deletions(-) delete mode 100644 initramfs/test.txt delete mode 100644 initramfs/test1.txt create mode 100644 kernel/inc/arch/x86_64/syscall.h create mode 100644 kernel/inc/core/loader.h create mode 100644 kernel/inc/core/userspace.h create mode 100644 kernel/src/arch/x86_64/syscall.asm create mode 100644 kernel/src/arch/x86_64/syscall.c create mode 100644 kernel/src/core/loader.c create mode 100644 kernel/src/core/userspace.c create mode 100644 userspace/CMakeLists.txt create mode 100644 userspace/init/CMakeLists.txt create mode 100644 userspace/init/src/entry.asm diff --git a/.gitignore b/.gitignore index 482cbfe..a4f93d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .cache build* .venv -initrd/image.cpio \ No newline at end of file +initrd/image.cpio +initramfs/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a8e00f8..3224749 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ add_compile_definitions(TERMOS_VERSION=\"${KERNEL_VERSION}\") add_subdirectory(bootloader) add_subdirectory(kernel) +add_subdirectory(userspace) if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE) set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img") @@ -41,7 +42,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE) COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR} COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\"" WORKING_DIRECTORY ${INITRAMFS_SRC_DIR} - DEPENDS ${INIT_FILES} + DEPENDS ${INIT_FILES} init VERBATIM COMMENT "Packing initramfs to cpio..." ) diff --git a/initramfs/test.txt b/initramfs/test.txt deleted file mode 100644 index 50cbc93..0000000 --- a/initramfs/test.txt +++ /dev/null @@ -1 +0,0 @@ -Meow!! \ No newline at end of file diff --git a/initramfs/test1.txt b/initramfs/test1.txt deleted file mode 100644 index 9190902..0000000 --- a/initramfs/test1.txt +++ /dev/null @@ -1 +0,0 @@ -Nyaaa \ No newline at end of file diff --git a/kernel/inc/arch/x86_64/cpuinfo.h b/kernel/inc/arch/x86_64/cpuinfo.h index 01e3b6b..98acf32 100644 --- a/kernel/inc/arch/x86_64/cpuinfo.h +++ b/kernel/inc/arch/x86_64/cpuinfo.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 0xKarinyash - +#pragma once #include #define CPU_FEAT_FPU (1ULL << 0) @@ -24,7 +24,11 @@ #define CPU_FEAT_HYPERVISOR (1ULL << 30) typedef struct { - i32 features; + u64 user_rsp; + u64 kernel_rsp; + u64 self; + + u64 features; char vendor[13]; u32 family; u32 model; @@ -32,5 +36,5 @@ typedef struct { extern cpu_info g_cpu; -void cpuinfo_init(); +void cpuinfo_init(u64 kernel_stack_top); bool cpu_has(u64 feature); \ No newline at end of file diff --git a/kernel/inc/arch/x86_64/syscall.h b/kernel/inc/arch/x86_64/syscall.h new file mode 100644 index 0000000..5fb2b39 --- /dev/null +++ b/kernel/inc/arch/x86_64/syscall.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +#define MSR_EFER 0xC0000080 +#define MSR_STAR 0xC0000081 +#define MSR_LSTAR 0xC0000082 +#define MSR_FMASK 0xC0000084 +#define MSR_KERNEL_GS_BASE 0xC0000102 + +#define EFER_SCE 0x01 // System Call Enable + +typedef enum { + SYS_EXIT, + SYS_EXEC, + SYS_WRITE, +} syscalls; + +void syscall_init(); \ No newline at end of file diff --git a/kernel/inc/core/loader.h b/kernel/inc/core/loader.h new file mode 100644 index 0000000..d57cdc7 --- /dev/null +++ b/kernel/inc/core/loader.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +#include + +bool exec_init(const char* path); +void init_task_entry(); \ No newline at end of file diff --git a/kernel/inc/core/userspace.h b/kernel/inc/core/userspace.h new file mode 100644 index 0000000..54b6597 --- /dev/null +++ b/kernel/inc/core/userspace.h @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +void jump_to_userspace(void* entry, void* user_stack_top); \ No newline at end of file diff --git a/kernel/inc/drivers/shitgui.h b/kernel/inc/drivers/shitgui.h index c5e754d..2a334fe 100644 --- a/kernel/inc/drivers/shitgui.h +++ b/kernel/inc/drivers/shitgui.h @@ -26,16 +26,8 @@ typedef struct { const unsigned char* base; } SG_Font; -typedef struct { - SG_Context *ctx; - SG_Point pos; - const char *title; -} SG_Window; - void sg_init(SG_Context *ctx); u32 sg_get_pixel(SG_Context *ctx, SG_Point *p); void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img); void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color); -void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font); -SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position); -void composer_task(); \ No newline at end of file +void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font); \ No newline at end of file diff --git a/kernel/src/arch/x86_64/cpuinfo.c b/kernel/src/arch/x86_64/cpuinfo.c index 6552402..321b92b 100644 --- a/kernel/src/arch/x86_64/cpuinfo.c +++ b/kernel/src/arch/x86_64/cpuinfo.c @@ -4,6 +4,9 @@ #include "types.h" #include +#define MSR_GS_BASE 0xC0000101 +#define MSR_KERNEL_GS_BASE 0xC0000102 + cpu_info g_cpu = {0}; static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) { @@ -13,7 +16,18 @@ static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u3 ); } -void cpuinfo_init() { +static inline void wrmsr(u32 msr, u64 val) { + u32 low = (u32)val; + u32 high = (u32)(val >> 32); + __asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr)); +} + +void cpuinfo_init(u64 kernel_stack_top) { + g_cpu.kernel_rsp = kernel_stack_top; + g_cpu.self = (u64)&g_cpu; + wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu); + + u32 eax, ebx, ecx, edx; cpuid(0, 0, &eax, &ebx, &ecx, &edx); diff --git a/kernel/src/arch/x86_64/entry.asm b/kernel/src/arch/x86_64/entry.asm index e7ea1eb..743a9b5 100644 --- a/kernel/src/arch/x86_64/entry.asm +++ b/kernel/src/arch/x86_64/entry.asm @@ -27,6 +27,7 @@ stack_guard: global stack_bottom stack_bottom: resb 16384 +global stack_top stack_top: section .text.entry diff --git a/kernel/src/arch/x86_64/syscall.asm b/kernel/src/arch/x86_64/syscall.asm new file mode 100644 index 0000000..e0c622e --- /dev/null +++ b/kernel/src/arch/x86_64/syscall.asm @@ -0,0 +1,70 @@ +; SPDX-License-Identifier: GPL-3.0-or-later +; Copyright (c) 2026 0xKarinyash + +bits 64 + +extern syscall_dispatch +global syscall_entry + +section .text + +syscall_entry: + swapgs + mov [gs:0], rsp ; saving users rsp in g_cpu.user_rsp + mov rsp, [gs:8] ; load kernel rsp from g_cpu.kernel_rsp + + push qword [gs:0] + push r11 ; rflags + push rcx ; rip + + push rbp + push rbx + push rdi + push rsi + push rdx + push r10 + push r8 + push r9 + push r12 + push r13 + push r14 + push r15 + + ; preparing c code + ; c waits rdi, rsi, rdx, rcx, r8, r9 + ; user sent rax, rdi, rsi, rdx, r10, r8 (rax=id) + + mov r9, r8 ; 6th arg + mov r8, r10 ; 5th arg + mov rcx, rdx ; 4th arg + mov rdx, rsi ; 3rd arg + mov rsi, rdi ; 2nd arg + mov rdi, rax ; 1st arg (id) + + call syscall_dispatch + + ; restoring context except RAX (result there) + pop r15 + pop r14 + pop r13 + pop r12 + pop r9 + pop r8 + pop r10 + pop rdx + pop rsi + pop rdi + pop rbx + pop rbp + pop rcx ; rip + pop r11 ; rflags + add rsp, 8 ; skip rsp + + mov [gs:8], rsp + mov rsp, [gs:0] + swapgs + + o64 sysret + + + diff --git a/kernel/src/arch/x86_64/syscall.c b/kernel/src/arch/x86_64/syscall.c new file mode 100644 index 0000000..788a7e1 --- /dev/null +++ b/kernel/src/arch/x86_64/syscall.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#include +#include +#include +#include +#include +#include + +static inline void wrmsr(u32 msr, u64 val) { + u32 low = (u32)val; + u32 high = (u32)(val >> 32); + __asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr)); +} + +static inline u64 rdmsr(u32 msr) { + u32 low, high; + __asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr)); + return ((u64)high << 32) | low; +} + +extern void syscall_entry(); + +void syscall_init() { + u64 efer = rdmsr(MSR_EFER); + wrmsr(MSR_EFER, efer | 1); // Enabling SCE in EFER. Just enabling 0 bit + + // setting up STAR + // 32:47 kernel selector (0x08) + // 48:64 user selector (0x01 cuz sysret adds +16 for CS and +8 for SS) + u64 star = (0x13ULL << 48) | (0x08ULL << 32); + wrmsr(MSR_STAR, star); + + wrmsr(MSR_LSTAR, (u64)syscall_entry); // setting handler adress + + // masking flags (IA32_FMASK) + // 9 bit for finterrupts in syscall (IF) and few more necessary flags + wrmsr(MSR_FMASK, 0x200); // masking only IF + + if (g_cpu.kernel_rsp == 0) { + void* stack_phys = pmm_alloc_page(); + g_cpu.kernel_rsp = (u64)stack_phys + HHDM_OFFSET + 4096; + } + + wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu); +} + +u64 syscall_dispatch(u64 id, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) { + switch (id) { + case SYS_EXIT: { + kprintf("\n[Dewar] process exited with code %d", arg1); + while(1) __asm__ ("hlt"); // stub + return 0; + } + case SYS_EXEC: { + kprintf("\n[Dewar] process called exec syscall"); + return 0; // stub as well + } + case SYS_WRITE: { + kprintf("%s", (char*)arg1); + return 0; + } + default: kprintf("[Dewar] Unknown syscall %d\n", id); return -1; + } +} \ No newline at end of file diff --git a/kernel/src/core/loader.c b/kernel/src/core/loader.c new file mode 100644 index 0000000..e98bdb8 --- /dev/null +++ b/kernel/src/core/loader.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +extern u64* pml4_kernel; + +bool exec_init(const char* path) { + kprintf("[Loader] loading %s...\n", path); + fs_node* file = vfs_open(path); + if (!file) { + kprintf("[Loader] Error: %s not found in initramfs!\n", path); + return false; + } + + u64 virt_code = 0x400000; + u64 virt_stack = 0x800000; + u64 stack_size = 8192; + + u64 bytes_left = file->len; + u64 offset = 0; + u64 page_idx = 0; + + while (bytes_left > 0) { + void* phys = pmm_alloc_page(); + if (!phys) { + kprintf("Loader: OOM!\n"); + return false; + } + + vmm_map_page(pml4_kernel, (u64)phys, virt_code + (page_idx * 4096), PTE_PRESENT | PTE_RW | PTE_USER); + + void* k_ptr = (void*)(HHDM_OFFSET + (u64)phys); + memset(k_ptr, 0, 4096); + + u64 chunk = (bytes_left > 4096) ? 4096 : bytes_left; + vfs_read(file, offset, chunk, (u8*)k_ptr); + + bytes_left -= chunk; + offset += chunk; + page_idx++; + } + + for (u64 i = 0; i < (stack_size / 4096); i++) { + void* phys = pmm_alloc_page(); + vmm_map_page(pml4_kernel, (u64)phys, virt_stack + (i * 4096), PTE_PRESENT | PTE_RW | PTE_USER); + memset((void*)(HHDM_OFFSET + (u64)phys), 0, 4096); + } + + __asm__ volatile( + "mov %%cr3, %%rax\n\t" + "mov %%rax, %%cr3\n\t" + ::: "rax", "memory" + ); + + kprintf("[Loader] Transferring control to userspace...\n"); + jump_to_userspace((void*)virt_code, (void*)(virt_stack + stack_size)); + + return true; // unreachable +} + +void init_task_entry() { + if (!exec_init("/init")) { + kprintf("FATAL: Could not load /init\n"); + sched_spawn(ksh); + + while(1) __asm__("hlt"); + } +} \ No newline at end of file diff --git a/kernel/src/core/scheduler.c b/kernel/src/core/scheduler.c index a9eed8b..7b2a713 100644 --- a/kernel/src/core/scheduler.c +++ b/kernel/src/core/scheduler.c @@ -4,6 +4,7 @@ #include #include #include +#include #include task* curr_task = nullptr; @@ -68,6 +69,7 @@ u64 sched_next(u64 curr_rsp) { curr_task = next; tss.rsp0 = curr_task->kernel_stack_top; + g_cpu.kernel_rsp = curr_task->kernel_stack_top; return curr_task->rsp; } diff --git a/kernel/src/core/userspace.c b/kernel/src/core/userspace.c new file mode 100644 index 0000000..0604bfb --- /dev/null +++ b/kernel/src/core/userspace.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#include +#include + +#define USER_DS (0x18 | 3) +#define USER_CS (0x20 | 3) +#define RFLAGS_IF 0x202 + +void jump_to_userspace(void* entry, void* user_stack_top) { + __asm__ volatile ( + "mov %0, %%ds\n" + "mov %0, %%es\n" + "mov %0, %%fs\n" + :: "r" ((u64)USER_DS) : "memory" + ); + + __asm__ volatile ( + "pushq %0\n" // SS (User Data Selector) + "pushq %1\n" // RSP (User Stack Pointer) + "pushq %2\n" // RFLAGS + "pushq %3\n" // CS (User Code Selector) + "pushq %4\n" // RIP (Entry Point) + "iretq\n" + : + : "r" ((u64)USER_DS), + "r" ((u64)user_stack_top), + "r" ((u64)RFLAGS_IF), + "r" ((u64)USER_CS), + "r" ((u64)entry) + : "memory" + ); +} \ No newline at end of file diff --git a/kernel/src/drivers/shitgui.c b/kernel/src/drivers/shitgui.c index e3bf7f9..6bd11de 100644 --- a/kernel/src/drivers/shitgui.c +++ b/kernel/src/drivers/shitgui.c @@ -8,11 +8,8 @@ #include #define SHITGUI_TRANSPARENCY_KEY 0xFF00FF -#define SHITGUI_MAX_WINDOWS_AMOUNT 64 SG_Context* main_context; -SG_Window* windows[SHITGUI_MAX_WINDOWS_AMOUNT]; // нет блять линукс -u64 windows_amount = 0; void sg_init(SG_Context *ctx) { main_context = ctx; @@ -85,64 +82,4 @@ void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Fon } } } -} - -SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position) { - if (windows_amount >= SHITGUI_MAX_WINDOWS_AMOUNT) return nullptr; - SG_Context* ctx = nullptr; - u32* fb = nullptr; - SG_Window* window = nullptr; - - ctx = (SG_Context*)malloc(sizeof(SG_Context)); - if (!ctx) goto fail; // goto is GOOD for cleaning up in C stfu. - // Mainline linux kernel contains 100k gotos - - fb = malloc(size->x * size->y * sizeof(u32)); - if (!fb) goto fail; - memset(fb, 0, size->x * size->y * sizeof(u32)); - - window = (SG_Window*)malloc(sizeof(SG_Window)); - if (!window) goto fail; - - ctx->fb = fb; - ctx->height = size->y; - ctx->width = size->x; - ctx->pitch = size->x; - - - window->ctx = ctx; - window->title = title; - window->pos.x = position->x; - window->pos.y = position->y; - - windows[windows_amount] = window; - windows_amount++; - - return window; - -fail: - if (ctx) free(ctx); - if (fb) free(fb); - if (window) free(window); - - return nullptr; -} - -void render_window(SG_Context *ctx, SG_Window *window) { - SG_Image img = {0}; - img.buffer = window->ctx->fb; - if (!img.buffer) panic("No img buffer found"); - img.height = window->ctx->height; - img.width = window->ctx->width; - - sg_put_img(ctx, &window->pos, &img); -} - -void composer_task() { - while (true) { - for (u64 i = 0; i < windows_amount; i++) { - render_window(main_context, windows[i]); - } - yield(1); - } } \ No newline at end of file diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 431215c..115025a 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -2,7 +2,7 @@ // Copyright (c) 2025 0xKarinyash #include "bootinfo.h" -#include "core/rand.h" + #include #include @@ -15,11 +15,14 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include @@ -32,6 +35,7 @@ #define BG_COLOR 0x111111 extern u64 _kernel_end; +extern void* stack_top; static SG_Context sg_ctx; void kmain(Bootinfo* info) { @@ -42,7 +46,7 @@ void kmain(Bootinfo* info) { if (info->magic != BOOTINFO_MAGIC) panic("Corrupt bootinfo!"); - cpuinfo_init(); + cpuinfo_init((u64)&stack_top); kprintf("Got CPUINFO\n"); rng_init(); kprintf("RNG initialized\n"); @@ -64,6 +68,7 @@ void kmain(Bootinfo* info) { kprintf("Scheduler initialized\n"); sg_init(&sg_ctx); kprintf("Shitgui initialized\n"); + syscall_init(); info = (Bootinfo*)PHYS_TO_HHDM((u64)info); @@ -85,9 +90,20 @@ void kmain(Bootinfo* info) { show_splash(&sg_ctx); - sched_spawn(composer_task); - sched_spawn(ksh); - if (!info->initramfs.addr) kprintf("^rWARNING^!: Failed to load ^yinitramfs^!, VFS is empty.\n\n"); + bool staying_in_ksh = false; + if (!info->initramfs.addr) { + kprintf("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n"); + staying_in_ksh = true; + } + + kprintf("Press any key to stay in ^gksh^!. \nPress ^yenter^! to continue booting in ring 3\n"); + char c = '\n'; + c = console_getc(); + if (c != '\n') staying_in_ksh = true; + + if (staying_in_ksh) sched_spawn(ksh); + else sched_spawn(init_task_entry); + __asm__ volatile("sti"); while (true) __asm__ volatile("hlt"); diff --git a/kernel/src/shell/builtins.c b/kernel/src/shell/builtins.c index d8caaec..f9143a0 100644 --- a/kernel/src/shell/builtins.c +++ b/kernel/src/shell/builtins.c @@ -35,7 +35,7 @@ void cmd_kfetch() { kprintf("^p %s ^!\t\t^gUptime^!: %d seconds\n^!", ascii_logo[4], uptime_s); kprintf("^p %s ^!\t\t^gShell^!: ksh\n^!", ascii_logo[5]); kprintf("^p %s ^!\t\t^gDE^!: shitgui\n^!", ascii_logo[6]); - kprintf("^p %s ^!\t\t^gCPU^!: %s\n^!", ascii_logo[7], g_cpu.vendor); + kprintf("^p %s ^!\t\t^gCPU^!: %s (^yFamily^!: %d; ^yModel^!: %d)\n^!", ascii_logo[7], g_cpu.vendor, g_cpu.family, g_cpu.model); kprintf("\n\n"); } diff --git a/kernel/src/shell/dbgcmd.c b/kernel/src/shell/dbgcmd.c index 5c6c8fa..6fec36f 100644 --- a/kernel/src/shell/dbgcmd.c +++ b/kernel/src/shell/dbgcmd.c @@ -1,57 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2025 0xKarinyash -// contents of this file will be changed CONSTANTLY -// im just testing new stuff here +// Copyright (c) 2026 0xKarinyash -#include "mm/vmm.h" -#include #include #include -extern u64* pml4_kernel; - -#define USER_DS (0x18 | 3) -#define USER_CS (0x20 | 3) -#define RFLAGS_IF 0x202 - -void jump_to_userspace(void* entry, void* user_stack_top) { - __asm__ volatile ( - "mov %0, %%ds\n" - "mov %0, %%es\n" - "mov %0, %%fs\n" - "mov %0, %%gs\n" - :: "r" ((u64)USER_DS) : "memory" - ); - - __asm__ volatile ( - "pushq %0\n" // SS (User Data Selector) - "pushq %1\n" // RSP (User Stack Pointer) - "pushq %2\n" // RFLAGS - "pushq %3\n" // CS (User Code Selector) - "pushq %4\n" // RIP (Entry Point) - "iretq\n" // jump - : - : "r" ((u64)USER_DS), - "r" ((u64)user_stack_top), - "r" ((u64)RFLAGS_IF), - "r" ((u64)USER_CS), - "r" ((u64)entry) - : "memory" - ); -} - u64 debug() { - void* phys_code = pmm_alloc_page(); - void* phys_stack = pmm_alloc_page(); - u64 virt_code = 0x400000; - u64 virt_stack = 0x800000; - - vmm_map_page(pml4_kernel, (u64)phys_code, virt_code, PTE_PRESENT | PTE_RW | PTE_USER); - vmm_map_page(pml4_kernel, (u64)phys_stack, virt_stack, PTE_PRESENT | PTE_RW | PTE_USER); - u8* kernel_view = (u8*)(HHDM_OFFSET + phys_code); - kernel_view[0] = 0xEB; // jmp - kernel_view[1] = 0xFE; // to self - kprintf("Jumping to userspace. Goodbye."); - jump_to_userspace((void*)virt_code, (void*)(virt_stack + 4096)); return 0; } \ No newline at end of file diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt new file mode 100644 index 0000000..2d9caf3 --- /dev/null +++ b/userspace/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20) +project(termOSuserspace LANGUAGES C ASM_NASM) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + +message(STATUS "Building termOS's userspace") + +add_subdirectory(init) \ No newline at end of file diff --git a/userspace/init/CMakeLists.txt b/userspace/init/CMakeLists.txt new file mode 100644 index 0000000..d30d8cb --- /dev/null +++ b/userspace/init/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.20) +project(termOSinit LANGUAGES C ASM_NASM) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + +message(STATUS "Building termOS's init") + +file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS + "src/*.asm" + "src/*.c" +) + +add_executable(init ${INIT_SOURCES}) +set_target_properties(init PROPERTIES + SUFFIX "" + LINKER_LANGUAGE C +) + +target_link_options(init PRIVATE + -nostdlib + -static + -Wl,--oformat=binary + -Wl,-Ttext=0x400000 + -Wl,-e,start +) + +add_custom_command(TARGET init POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_SOURCE_DIR}/initramfs/init + COMMENT "Installing init binary to initramfs" +) \ No newline at end of file diff --git a/userspace/init/src/entry.asm b/userspace/init/src/entry.asm new file mode 100644 index 0000000..9e49484 --- /dev/null +++ b/userspace/init/src/entry.asm @@ -0,0 +1,17 @@ +[BITS 64] + +start: + mov rax, 2 ; SYS_WRITE + mov rdi, msg_hello ; Адрес строки + syscall + + mov rax, 1 ; SYS_EXEC + syscall + + mov rax, 0 ; SYS_EXIT + mov rdi, 1337 + syscall + + jmp $ + +msg_hello: db "Hello from init!", 0xA, 0 \ No newline at end of file