Implemented a basic syscall handler

This commit is contained in:
2025-05-07 13:25:18 +02:00
parent d6035dff80
commit 024dcfffcc
11 changed files with 110 additions and 42 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ typedef void (*isr_handler_ptr)(struct isr_int_frame* iframe);
int isr_init(void);
void isr_register(uint8_t i, isr_handler_ptr handler);
int isr_handle_interrupt(struct isr_int_frame iframe);
void isr_handle_interrupt(struct isr_int_frame iframe);
// Assembly definitions (isr.s)
extern void isr_return(void);
+8 -1
View File
@@ -1,8 +1,15 @@
#ifndef _SYSCALL_H
#define _SYSCALL_H
#include <kernel.h>
#include <isr.h>
int syscall_handler(struct isr_int_frame* iframe) { (void)iframe; return 1; }
#define SYSCALL_MAX 2
#define SYS_EXIT 0
#define SYS_TEST 1
int syscall_init(void);
void syscall_register(size_t idx, void* handler);
void syscall_handler(struct isr_int_frame* iframe);
#endif
+2
View File
@@ -79,6 +79,8 @@ int boot_init_mb1(void* ptr, uint32_t magic) {
// TODO: APM table
// TODO: VBE table
// TODO: Framebuffer
debugf("[boot] Initiated with MultiBoot 1\n");
return 0;
}
+2 -4
View File
@@ -85,7 +85,7 @@ void isr_send_eoi(uint8_t irq) {
}
// TODO: Write fault handlers and make this more robust
int isr_handle_interrupt(struct isr_int_frame iframe) {
void isr_handle_interrupt(struct isr_int_frame iframe) {
if (iframe.interrupt < 32) {
// ISRs 0-31 - Exceptions
if (iframe.error) debugf("[kernel] Error code: 0x%08x\n", iframe.error);
@@ -97,9 +97,7 @@ int isr_handle_interrupt(struct isr_int_frame iframe) {
if (irq_handlers[irq]) irq_handlers[irq](&iframe);
} else if (iframe.interrupt == 128) {
// ISR 128 - System call
return syscall_handler(&iframe);
syscall_handler(&iframe);
}
return 0;
}
+9 -34
View File
@@ -1,5 +1,6 @@
#include <bootloader.h>
#include <kmalloc.h>
#include <syscall.h>
#include <kernel.h>
#include <paging.h>
#include <serial.h>
@@ -10,20 +11,16 @@
#include <pmm.h>
#include <tty.h>
void test(void);
__noreturn
void kmain(void* ptr, uint32_t magic) {
if (boot_init_mb1(ptr, magic) != 0) panic("Unsupported bootloader.");
// Serial console for debugging
if (serial_init(COM1) != 0) panic("Failed to initialize Serial driver.");
debugf("\x1b[H\x1b[J\x1b[0mkern. \x1b[36m(serial console)\x1b[0m\n\n");
// Load structures from bootloader
if (boot_init_mb1(ptr, magic) != 0) panic("Unsupported bootloader.");
// System init
if (gdt_init() != 0) panic("Failed to initalize GDT.");
debugf("[gdt] Segment selectors: NULL: 0x%04x, KCODE: 0x%04x, KDATA: 0x%04x, UCODE: 0x%04x, UDATA: 0x%04x, TSS: 0x%04x\n",
GDT_NULL, GDT_KERNEL_CODE, GDT_KERNEL_DATA, GDT_USER_CODE, GDT_USER_DATA, GDT_TSS);
if (isr_init() != 0) panic("Failed to initalize ISRs.");
if (pag_init() != 0) panic("Failed to initalize Paging.");
@@ -36,38 +33,16 @@ void kmain(void* ptr, uint32_t magic) {
tty_puts("kern.\n\n");
if (timer_init() != 0) panic("Failed to initialize timer.");
if (syscall_init() != 0) panic("Failed to initialize syscalls.");
if (task_init() != 0) panic("Failed to initialize tasking.");
// Create a temporary test task
task_create(task_create_id(), (uint32_t)test, 1, pag_get_pagedir(), 0, NULL);
char* s = "Hello, World!";
__asm__ volatile("int $0x80" :: "a"(SYS_TEST), "b"(s));
size_t delay = 0;
while (1) {
delay++;
if (delay < 0x1FFFFFF) continue;
delay = 0;
tty_puts("[kernel] Hello!\n");
}
// TODO: Syscalls
// TODO: Interprocess communication
// TODO: Load & run /sbin/init
panic("kmain() reached end.");
}
// An imaginary second task
void test(void) {
size_t delay = 0;
while (1) {
delay++;
if (delay < 0x2FFFFFF) continue;
delay = 0;
tty_puts("[test] Hello!\n");
}
// We don't want to halt
while (1);
}
+2
View File
@@ -17,6 +17,8 @@ int serial_init(int dev) {
if (inb(dev + 0) != 0xAE) return 1;
outb(dev + 4, 0x0F); // non-loopback, IRQs enabled, OUT#1 and OUT#2 bits enabled
debugf("\x1b[H\x1b[JSerial display initiated!\n\n");
return 0;
}
+66
View File
@@ -0,0 +1,66 @@
#include <kernel.h>
#include <task.h>
#include <tty.h>
#include <syscall.h>
// Syscall table
void* syscalls[SYSCALL_MAX] = { 0 };
void sys_exit(int code) {
debugf("[syscall] Task #%d exited with code %d.\n", task_current->id, code);
task_kill(task_current->id);
}
void sys_test(char* msg) {
debugf("[syscall] Test: %s\n", msg);
}
int syscall_init(void) {
syscall_register(SYS_EXIT, (void*)sys_exit);
syscall_register(SYS_TEST, (void*)sys_test);
debugf("[syscall] Initiated syscalls!\n");
return 0;
}
void syscall_register(size_t idx, void* handler) {
if (idx > SYSCALL_MAX) {
debugf("[syscall] Failed to register syscall #%d.\n", idx);
return;
}
syscalls[idx] = handler;
}
void syscall_handler(struct isr_int_frame* iframe) {
size_t nr = iframe->eax;
if (nr > SYSCALL_MAX || !syscalls[nr]) {
iframe->eax = -1;
debugf("[syscall] Tried to call syscall #%d which doesn't exist.\n", nr);
return;
}
void* handler = syscalls[nr];
int ret;
debugf("0x%08x\n", &ret);
__asm__ volatile(
"push %1\n"
"push %2\n"
"push %3\n"
"push %4\n"
"push %5\n"
"push %6\n"
"call *%7\n"
"add $24, %%esp\n"
"mov %%eax, %0\n"
: "=a"(ret)
: "g"(iframe->ebp), "g"(iframe->edi), "g"(iframe->esi),
"g"(iframe->edx), "g"(iframe->ecx), "g"(iframe->ebx),
"g"(handler)
);
iframe->eax = ret;
}
+1 -1
View File
@@ -34,7 +34,7 @@ void pit_phase(uint8_t ch, uint8_t mode, uint32_t hz) {
uint32_t div = PIT_DIV / hz;
outb(PIT_CH0 + ch, div & 0xFF);
outb(PIT_CH0 + ch, div >> 8);
debugf("[PIT] Set PIT divisor to %d (%d Hz).\n", div, hz);
debugf("[pit] Set PIT divisor to %d (%d Hz).\n", div, hz);
sti();
}
+2
View File
@@ -28,6 +28,8 @@ int tty_init(void) {
tty_ctx.buf = (uint8_t*)KERNEL_FRAMEBUF;
tty_clear();
debugf("[tty] Initiated %dx%d VGA display to TTY.\n", VGA_WIDTH, VGA_HEIGHT);
return 0;
}