diff --git a/Kernel/Idt.h b/Kernel/Idt.h index fc98049..202e55e 100644 --- a/Kernel/Idt.h +++ b/Kernel/Idt.h @@ -22,5 +22,5 @@ struct IdtPtr { void IdtInstall(); - +void IdtSetGate(uint8_t num, uint64_t base, uint16_t sel, uint8_t flags); #endif \ No newline at end of file diff --git a/Kernel/Kernel.c b/Kernel/Kernel.c index af3b553..82faf73 100644 --- a/Kernel/Kernel.c +++ b/Kernel/Kernel.c @@ -6,6 +6,7 @@ #include "Kernel.h" #include "Memory.h" #include "Process.h" +#include "Syscall.h" #include "Io.h" int CurrentLine = 0; int CurrentColumn = 0; @@ -120,16 +121,30 @@ void task2(void) { return; } void task3(void) { + // Test syscall + asm volatile( + "mov $2, %%rax\n" // SYS_WRITE + "mov $1, %%rbx\n" // stdout + "mov %0, %%rcx\n" // message + "mov $13, %%r8\n" // length + "int $0x80\n" + : + : "r"("Syscall test!") + : "rax", "rbx", "rcx", "r8" + ); + while (1) { - PrintKernelAt("T3 running", 12, 0); + PrintKernelAt("T3 syscall", 12, 0); + for(volatile int i = 0; i < 50000; i++); } - return; } void KernelMain(uint32_t magic, uint32_t info) { ClearScreen(); PrintKernel("VoidFrame Kernel - Version 0.0.1-alpha\n"); PrintKernel("Initializing IDT...\n"); IdtInstall(); + PrintKernel("Initializing System Calls...\n"); + SyscallInit(); PrintKernel("Initializing PIC...\n"); PicInstall(); PrintKernel("Initializing Memory...\n"); diff --git a/Kernel/Kernel.h b/Kernel/Kernel.h index 1ddecdf..999e0ab 100644 --- a/Kernel/Kernel.h +++ b/Kernel/Kernel.h @@ -1,5 +1,5 @@ -#ifndef VOIDFRAME_KERNEL_H -#define VOIDFRAME_KERNEL_H +#ifndef KERNEL_H +#define KERNEL_H extern int CurrentLine; extern int CurrentColumn; void ClearScreen(); diff --git a/Kernel/Syscall.c b/Kernel/Syscall.c new file mode 100644 index 0000000..a0a4e53 --- /dev/null +++ b/Kernel/Syscall.c @@ -0,0 +1,45 @@ +#include "Syscall.h" +#include "Kernel.h" +#include "Process.h" +#include "Idt.h" +extern void SyscallEntry(void); +uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3) { + switch (syscall_num) { + case SYS_EXIT: + // Terminate current process + GetCurrentProcess()->state = PROC_TERMINATED; + Schedule(); // Switch to next process + return 0; + + case SYS_WRITE: + // arg1 = fd (ignored for now), arg2 = buffer, arg3 = count + if (arg1 == 1) { // stdout + char* buffer = (char*)arg2; + for (uint64_t i = 0; i < arg3; i++) { + if (buffer[i] == '\0') break; + PrintKernelAt(&buffer[i], CurrentLine, CurrentColumn++); + if (CurrentColumn >= 80) { + CurrentLine++; + CurrentColumn = 0; + } + } + return arg3; + } + return -1; + + case SYS_READ: + // Not implemented yet + return 0; + + case SYS_GETPID: + return GetCurrentProcess()->pid; + + default: + return -1; + } +} + +void SyscallInit(void) { + // Install syscall interrupt (0x80) + IdtSetGate(0x80, (uint64_t)SyscallEntry, 0x08, 0x8E); +} \ No newline at end of file diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h new file mode 100644 index 0000000..5703153 --- /dev/null +++ b/Kernel/Syscall.h @@ -0,0 +1,16 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include "stdint.h" + +// System call numbers +#define SYS_EXIT 1 +#define SYS_WRITE 2 +#define SYS_READ 3 +#define SYS_GETPID 4 + +// System call handler +void SyscallInit(void); +uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3); + +#endif \ No newline at end of file diff --git a/Kernel/SyscallEntry.asm b/Kernel/SyscallEntry.asm new file mode 100644 index 0000000..fe550ae --- /dev/null +++ b/Kernel/SyscallEntry.asm @@ -0,0 +1,52 @@ +bits 64 + +extern SyscallHandler + +global SyscallEntry + +SyscallEntry: + ; Save all registers + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + ; System call convention: rax=syscall_num, rdi=arg1, rsi=arg2, rdx=arg3 + mov rdi, rax ; syscall number + mov rsi, rbx ; arg1 + mov rdx, rcx ; arg2 + mov rcx, r8 ; arg3 + + call SyscallHandler + + ; Return value in rax is already set + + ; Restore registers + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + add rsp, 8 ; Skip original rax (return value) + + iretq \ No newline at end of file diff --git a/meson.build b/meson.build index 6ae793a..c56115c 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ asm_sources = [ 'Kernel/IdtLoad.asm', 'Kernel/Interrupts.asm', 'Kernel/Switch.asm', + 'Kernel/SyscallEntry.asm', ] # C sources @@ -46,7 +47,8 @@ c_sources = [ 'Kernel/Cpu.c', 'Kernel/MemOps.c', 'Kernel/VMem.c', - 'Kernel/Process.c' + 'Kernel/Process.c', + 'Kernel/Syscall.c' ] # Compile assembly files