v0.5.3-pre: refactor syscall handlers and introduce libterm
Moved handlers to syscalls/, implemented libterm (malloc, stdio)
This commit is contained in:
@@ -23,6 +23,7 @@ file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||
"src/mm/*.c"
|
||||
"src/shell/*.c"
|
||||
"src/fs/*.c"
|
||||
"src/syscalls/*.c"
|
||||
|
||||
"data/*.c"
|
||||
)
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
|
||||
typedef enum {
|
||||
SYS_EXIT,
|
||||
SYS_EXEC,
|
||||
SYS_SPAWN,
|
||||
SYS_MEM,
|
||||
SYS_WRITE,
|
||||
SYS_READ,
|
||||
} syscalls;
|
||||
|
||||
void syscall_init();
|
||||
@@ -4,7 +4,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
#include <core/scheduler.h>
|
||||
|
||||
bool exec_init(process* p, const char* path);
|
||||
i32 process_spawn(const char* path, const char* name);
|
||||
void init_task_entry();
|
||||
@@ -15,6 +15,8 @@ typedef struct process {
|
||||
u64 pml4_phys;
|
||||
struct process* parent;
|
||||
char name[32];
|
||||
u64 heap_start;
|
||||
u64 heap_cur;
|
||||
} process;
|
||||
|
||||
typedef struct task {
|
||||
@@ -22,6 +24,7 @@ typedef struct task {
|
||||
struct task* next;
|
||||
u32 id;
|
||||
u32 sleep_ticks;
|
||||
process_state task_state; // reusing process_state cuz wn
|
||||
u64 kernel_stack_top;
|
||||
process* proc;
|
||||
} task;
|
||||
|
||||
@@ -13,6 +13,7 @@ void console_set_color(u32 color);
|
||||
void console_set_default_color(u32 color);
|
||||
void console_set_cursor_pos(SG_Point *p);
|
||||
char console_getc();
|
||||
void console_putc(char c);
|
||||
void kprint(const char *str);
|
||||
void kprintf(const char *fmt, ...);
|
||||
void kgets(char* buff, u32 lim);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 sys_write(u64 fd, u64 buff, u64 len);
|
||||
u64 sys_read(u64 fd, u64 buff, u64 count);
|
||||
@@ -0,0 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 sys_mem(u64 size);
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
u64 sys_exit(i32 code);
|
||||
u64 sys_spawn(const char* path);
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include "types.h"
|
||||
#include <types.h>
|
||||
#include <cpuinfo.h>
|
||||
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
|
||||
@@ -60,7 +60,6 @@ syscall_entry:
|
||||
pop r11 ; rflags
|
||||
add rsp, 8 ; skip rsp
|
||||
|
||||
mov [gs:8], rsp
|
||||
mov rsp, [gs:0]
|
||||
swapgs
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
|
||||
#include <syscalls/proc.h>
|
||||
#include <syscalls/mem.h>
|
||||
#include <syscalls/io.h>
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
@@ -47,20 +51,14 @@ void syscall_init() {
|
||||
}
|
||||
|
||||
u64 syscall_dispatch(u64 id, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) {
|
||||
__asm__ volatile("cli");
|
||||
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;
|
||||
}
|
||||
case SYS_EXIT: return sys_exit(arg1);
|
||||
case SYS_SPAWN: return sys_spawn((const char*)arg1);
|
||||
case SYS_MEM: return sys_mem(arg1);
|
||||
case SYS_WRITE: return sys_write(arg1, arg2, arg3);
|
||||
case SYS_READ: return sys_read(arg1, arg2, arg3);
|
||||
default: kprintf("[Dewar] Unknown syscall %d\n", id); return -1;
|
||||
}
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
+16
-13
@@ -19,27 +19,30 @@ u64 load_hot(process* proc, u8* data) {
|
||||
}
|
||||
|
||||
hot_segment* segments = (hot_segment*)(data + sizeof(hot_header));
|
||||
u64 kernel_cr3 = vmm_get_current_cr3();
|
||||
for (u64 i = 0; i < header->segments_count; i++) {
|
||||
hot_segment* seg = &segments[i];
|
||||
if (seg->memsz == 0) continue;
|
||||
|
||||
u64 start = seg->vaddr & ~(0xFFF);
|
||||
u64 end = (seg->vaddr + seg->memsz + 0xFFF) & ~(0xFFF);
|
||||
u64 start = seg->vaddr & ~(0xFFFULL);
|
||||
u64 end = (seg->vaddr + seg->memsz + 0xFFF) & ~(0xFFFULL);
|
||||
|
||||
for (u64 addr = start; addr < end; addr += PAGE_SIZE) {
|
||||
void* phys = pmm_alloc_page();
|
||||
vmm_map_page((u64*)proc->pml4_phys, (u64)phys, addr, PTE_USER | PTE_RW | PTE_PRESENT);
|
||||
}
|
||||
vmm_map_page((u64*)proc->pml4_phys, (u64)phys, addr, PTE_USER | PTE_RW | PTE_PRESENT);
|
||||
void* kernel_virt = (void*)((u64)phys + HHDM_OFFSET);
|
||||
memset(kernel_virt, 0, PAGE_SIZE);
|
||||
u64 page_overleap_start = (addr > seg->vaddr) ? addr : seg->vaddr;
|
||||
u64 page_overleap_end = (addr + PAGE_SIZE < seg->vaddr + seg->filesz)
|
||||
? (addr + PAGE_SIZE)
|
||||
: (seg->vaddr + seg->filesz);
|
||||
if (page_overleap_start < page_overleap_end) {
|
||||
u64 copy_size = page_overleap_end - page_overleap_start;
|
||||
u64 src_offset = seg->offset + (page_overleap_start - seg->vaddr);
|
||||
u64 dst_offset = page_overleap_start - addr;
|
||||
|
||||
load_cr3(proc->pml4_phys);
|
||||
if (seg->filesz > 0) memcpy((void*)seg->vaddr, data + seg->offset, seg->filesz);
|
||||
if (seg->memsz > seg->filesz) {
|
||||
u64 bss_start = seg->vaddr + seg->filesz;
|
||||
u64 bss_len = seg->memsz - seg->filesz;
|
||||
memset((void*)bss_start, 0, bss_len);
|
||||
memcpy((u8*)kernel_virt + dst_offset, data + src_offset, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
load_cr3(kernel_cr3);
|
||||
}
|
||||
|
||||
return header->entry_point;
|
||||
|
||||
+35
-15
@@ -20,28 +20,48 @@
|
||||
#include <types.h>
|
||||
|
||||
extern task* curr_task;
|
||||
extern u32 next_pid;
|
||||
|
||||
#define USER_STACK_TOP 0x70000000
|
||||
#define HEAP_START 0x40000000
|
||||
|
||||
void init_task_entry() {
|
||||
process* init_proc = (process*)malloc(sizeof(process));
|
||||
init_proc->pid = 1;
|
||||
init_proc->state = RUNNING;
|
||||
init_proc->pml4_phys = vmm_create_address_space();
|
||||
strcpy(init_proc->name, "init");
|
||||
i32 process_spawn(const char* path, const char* name) {
|
||||
fs_node* file = vfs_open(path);
|
||||
if (!file) return -1;
|
||||
|
||||
fs_node* file = vfs_open("/init");
|
||||
if (!file) panic("FATAL: /init not found!");
|
||||
process* new_proc = (process*)malloc(sizeof(process));
|
||||
if (!new_proc) return -2;
|
||||
memset(new_proc, 0, sizeof(process));
|
||||
new_proc->pid = next_pid++;
|
||||
new_proc->state = RUNNING;
|
||||
new_proc->pml4_phys = vmm_create_address_space();
|
||||
new_proc->heap_start = HEAP_START;
|
||||
new_proc->heap_cur = HEAP_START;
|
||||
strncpy(new_proc->name, name, 31);
|
||||
|
||||
u8* file_buffer = (u8*)malloc(file->len);
|
||||
if (!file_buffer) {
|
||||
free(new_proc);
|
||||
return -3;
|
||||
}
|
||||
vfs_read(file, 0, file->len, file_buffer);
|
||||
|
||||
u64 entry = load_hot(init_proc, file_buffer);
|
||||
if (!entry) panic("Invalid HOT executable");
|
||||
|
||||
free(file_buffer);
|
||||
vmm_setup_user_stack((u64*)init_proc->pml4_phys);
|
||||
sched_spawn((void(*)())entry, init_proc, true, USER_STACK_TOP);
|
||||
u64 entry = load_hot(new_proc, file_buffer);
|
||||
if (!entry) return -4;
|
||||
|
||||
while(1) { __asm__("sti; hlt"); }
|
||||
free(file_buffer);
|
||||
|
||||
vmm_setup_user_stack((u64*)new_proc->pml4_phys);
|
||||
sched_spawn((void(*)())entry, new_proc, true, USER_STACK_TOP);
|
||||
|
||||
return new_proc->pid;
|
||||
}
|
||||
|
||||
void init_task_entry() {
|
||||
i32 pid = process_spawn("/init", "init");
|
||||
if (pid < 0) {
|
||||
panic("FATAL: Failed to spawn /init");
|
||||
}
|
||||
|
||||
while (1) { __asm__("sti; hlt"); }
|
||||
}
|
||||
@@ -32,7 +32,6 @@ const char* fun_messages[] = {
|
||||
"Code have been eaten by Aliens",
|
||||
"That's all, folks!",
|
||||
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
|
||||
"Fatal error has been occurred.\n\t\t\t\t Your device will be terminated in 30 seconds.",
|
||||
"I'll be back",
|
||||
"Hastla la vista, baby",
|
||||
"Ti chego mne tut nagovoril...",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <core/string.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/memory.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <gdt.h>
|
||||
|
||||
@@ -17,6 +18,12 @@ extern u64 pml4_kernel_phys;
|
||||
|
||||
static process kernel_process;
|
||||
|
||||
void idle_task() {
|
||||
while (1) {
|
||||
__asm__ volatile ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void sched_init() {
|
||||
kernel_process.pid = 0;
|
||||
kernel_process.state = RUNNING;
|
||||
@@ -24,12 +31,15 @@ void sched_init() {
|
||||
strcpy(kernel_process.name, "kernel");
|
||||
|
||||
task* kt = (task*)malloc(sizeof(task));
|
||||
memset(kt, 0, sizeof(task));
|
||||
kt->id = 0;
|
||||
kt->proc = &kernel_process;
|
||||
kt->sleep_ticks = 0;
|
||||
kt->next = kt;
|
||||
kt->task_state = RUNNING;
|
||||
|
||||
curr_task = kt;
|
||||
sched_spawn(idle_task, &kernel_process, false, 0);
|
||||
}
|
||||
|
||||
task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_stack) {
|
||||
@@ -66,6 +76,7 @@ task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_s
|
||||
t->sleep_ticks = 0;
|
||||
t->next = curr_task->next;
|
||||
t->kernel_stack_top = (u64)stack_base + stack_size;
|
||||
t->task_state = RUNNING;
|
||||
curr_task->next = t;
|
||||
return t;
|
||||
}
|
||||
@@ -84,6 +95,12 @@ u64 sched_next(u64 curr_rsp) {
|
||||
if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--;
|
||||
|
||||
task* next = curr_task->next;
|
||||
while (next->task_state == DEAD) {
|
||||
// TODO: add gc here;
|
||||
next = next->next;
|
||||
if (next == curr_task) panic("no alive tasks");
|
||||
}
|
||||
|
||||
while (next != curr_task && next->sleep_ticks > 0) next = next->next; // what the fuck i just wrote
|
||||
|
||||
if (next->proc->pml4_phys != curr_task->proc->pml4_phys) load_cr3(next->proc->pml4_phys);
|
||||
|
||||
@@ -80,7 +80,7 @@ void console_set_cursor_pos(SG_Point *p) {
|
||||
s_cursor_pos.y = p->y;
|
||||
}
|
||||
|
||||
static void console_putc(char c) {
|
||||
void console_putc(char c) {
|
||||
serial_writec(c);
|
||||
if (!ctx_ptr) return;
|
||||
if (c == '\n') {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <syscalls/io.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
u64 sys_write(u64 fd, u64 buff, u64 len) {
|
||||
if (fd == 1 || fd == 2) {
|
||||
char* str = (char*)buff;
|
||||
for (u64 i = 0; i < len; i++) {
|
||||
console_putc(str[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 sys_read(u64 fd, u64 buff, u64 count) {
|
||||
char* buf = (char*)buff;
|
||||
if (fd == 0) {
|
||||
for (u64 i = 0; i < count; i++) {
|
||||
buf[i] = console_getc();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <syscalls/mem.h>
|
||||
|
||||
#include <core/scheduler.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/memory.h>
|
||||
|
||||
extern task* curr_task;
|
||||
|
||||
u64 sys_mem(u64 size) {
|
||||
if (size == 0) return 0;
|
||||
process* proc = curr_task->proc;
|
||||
u64 addr_to_ret = proc->heap_cur;
|
||||
|
||||
u64 pages_needed = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
|
||||
|
||||
for (u64 i = 0; i < pages_needed; i++) {
|
||||
void* phys = pmm_alloc_page();
|
||||
if (!phys) return 0;
|
||||
|
||||
vmm_map_page((u64*)proc->pml4_phys, (u64)phys, proc->heap_cur, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
memset((void*)PHYS_TO_HHDM((u64)phys), 0, PAGE_SIZE);
|
||||
|
||||
proc->heap_cur += 4096;
|
||||
}
|
||||
|
||||
return addr_to_ret;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <syscalls/proc.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <drivers/console.h>
|
||||
#include <core/loader.h>
|
||||
|
||||
extern task* curr_task;
|
||||
|
||||
u64 sys_exit(i32 code) {
|
||||
kprintf("\n[Dewar] process %s exited with code %d", curr_task->proc->name, code);
|
||||
curr_task->task_state = DEAD;
|
||||
sched_next(curr_task->rsp);
|
||||
while (1) { __asm__ ("hlt"); }
|
||||
}
|
||||
|
||||
|
||||
u64 sys_spawn(const char* path) {
|
||||
return process_spawn(path, path);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user