forked from PoliEcho-holding-org/kern
Implemented a basic syscall handler
This commit is contained in:
@@ -18,7 +18,8 @@ TODO
|
|||||||
[x] PIT
|
[x] PIT
|
||||||
[ ] RTC
|
[ ] RTC
|
||||||
[ ] HPET
|
[ ] HPET
|
||||||
[ ] System calls
|
[x] System calls
|
||||||
|
[ ] Separate syscall sources into individual files
|
||||||
[ ] Userspace
|
[ ] Userspace
|
||||||
[x] Processes/Tasks
|
[x] Processes/Tasks
|
||||||
[x] Scheduler
|
[x] Scheduler
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
System Calls
|
System Calls
|
||||||
============
|
============
|
||||||
|
|
||||||
|
System calls are a way of interfacing with the kernel from userspace.
|
||||||
|
|
||||||
|
Calling
|
||||||
|
-------
|
||||||
|
System calls are called via interrupt 0x80. Arguments can be passed through
|
||||||
|
registers in this order with EAX containing the system call number (see [Table](#Table))
|
||||||
|
and arguments in EBX, ECX, EDX, ESI, EDI and EBP respectively.
|
||||||
|
|
||||||
|
Table
|
||||||
|
-----
|
||||||
|
|
||||||
|
|
||||||
|
Syscalls
|
||||||
|
--------
|
||||||
|
|
||||||
pid_t fork(void);
|
pid_t fork(void);
|
||||||
Creates a child process.
|
Creates a child process.
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ typedef void (*isr_handler_ptr)(struct isr_int_frame* iframe);
|
|||||||
|
|
||||||
int isr_init(void);
|
int isr_init(void);
|
||||||
void isr_register(uint8_t i, isr_handler_ptr handler);
|
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)
|
// Assembly definitions (isr.s)
|
||||||
extern void isr_return(void);
|
extern void isr_return(void);
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
#ifndef _SYSCALL_H
|
#ifndef _SYSCALL_H
|
||||||
#define _SYSCALL_H
|
#define _SYSCALL_H
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
#include <isr.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
|
#endif
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ int boot_init_mb1(void* ptr, uint32_t magic) {
|
|||||||
// TODO: VBE table
|
// TODO: VBE table
|
||||||
// TODO: Framebuffer
|
// TODO: Framebuffer
|
||||||
|
|
||||||
|
debugf("[boot] Initiated with MultiBoot 1\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -85,7 +85,7 @@ void isr_send_eoi(uint8_t irq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Write fault handlers and make this more robust
|
// 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) {
|
if (iframe.interrupt < 32) {
|
||||||
// ISRs 0-31 - Exceptions
|
// ISRs 0-31 - Exceptions
|
||||||
if (iframe.error) debugf("[kernel] Error code: 0x%08x\n", iframe.error);
|
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);
|
if (irq_handlers[irq]) irq_handlers[irq](&iframe);
|
||||||
} else if (iframe.interrupt == 128) {
|
} else if (iframe.interrupt == 128) {
|
||||||
// ISR 128 - System call
|
// ISR 128 - System call
|
||||||
return syscall_handler(&iframe);
|
syscall_handler(&iframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-34
@@ -1,5 +1,6 @@
|
|||||||
#include <bootloader.h>
|
#include <bootloader.h>
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
|
#include <syscall.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <paging.h>
|
#include <paging.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
@@ -10,20 +11,16 @@
|
|||||||
#include <pmm.h>
|
#include <pmm.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
|
|
||||||
void test(void);
|
|
||||||
|
|
||||||
__noreturn
|
__noreturn
|
||||||
void kmain(void* ptr, uint32_t magic) {
|
void kmain(void* ptr, uint32_t magic) {
|
||||||
if (boot_init_mb1(ptr, magic) != 0) panic("Unsupported bootloader.");
|
|
||||||
|
|
||||||
// Serial console for debugging
|
// Serial console for debugging
|
||||||
if (serial_init(COM1) != 0) panic("Failed to initialize Serial driver.");
|
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
|
// System init
|
||||||
if (gdt_init() != 0) panic("Failed to initalize GDT.");
|
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 (isr_init() != 0) panic("Failed to initalize ISRs.");
|
||||||
if (pag_init() != 0) panic("Failed to initalize Paging.");
|
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");
|
tty_puts("kern.\n\n");
|
||||||
|
|
||||||
if (timer_init() != 0) panic("Failed to initialize timer.");
|
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.");
|
if (task_init() != 0) panic("Failed to initialize tasking.");
|
||||||
|
|
||||||
// Create a temporary test task
|
char* s = "Hello, World!";
|
||||||
task_create(task_create_id(), (uint32_t)test, 1, pag_get_pagedir(), 0, NULL);
|
__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: Interprocess communication
|
||||||
// TODO: Load & run /sbin/init
|
// TODO: Load & run /sbin/init
|
||||||
|
|
||||||
panic("kmain() reached end.");
|
// We don't want to halt
|
||||||
}
|
while (1);
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ int serial_init(int dev) {
|
|||||||
if (inb(dev + 0) != 0xAE) return 1;
|
if (inb(dev + 0) != 0xAE) return 1;
|
||||||
outb(dev + 4, 0x0F); // non-loopback, IRQs enabled, OUT#1 and OUT#2 bits enabled
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -34,7 +34,7 @@ void pit_phase(uint8_t ch, uint8_t mode, uint32_t hz) {
|
|||||||
uint32_t div = PIT_DIV / hz;
|
uint32_t div = PIT_DIV / hz;
|
||||||
outb(PIT_CH0 + ch, div & 0xFF);
|
outb(PIT_CH0 + ch, div & 0xFF);
|
||||||
outb(PIT_CH0 + ch, div >> 8);
|
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();
|
sti();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ int tty_init(void) {
|
|||||||
tty_ctx.buf = (uint8_t*)KERNEL_FRAMEBUF;
|
tty_ctx.buf = (uint8_t*)KERNEL_FRAMEBUF;
|
||||||
tty_clear();
|
tty_clear();
|
||||||
|
|
||||||
|
debugf("[tty] Initiated %dx%d VGA display to TTY.\n", VGA_WIDTH, VGA_HEIGHT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user