Files
RockOS/kernel/syscall.c

176 lines
4.9 KiB
C
Raw Normal View History

2026-06-17 18:16:47 -05:00
#include <stdint.h>
#include <stddef.h>
2026-06-17 18:16:47 -05:00
#include <drivers/pty/pty.h>
#include "lib/memory.h"
#include "lib/ringbuf.h"
#include "memory/mm.h"
#include "process.h"
#include "scheduler.h"
#include "vfs.h"
2026-06-17 18:16:47 -05:00
#include <drivers/vga/vga.h>
2026-07-01 20:00:22 -05:00
#include <lib/print.h>
#include <lib/string.h>
2026-07-01 20:00:22 -05:00
typedef struct registers {
2026-07-07 18:52:22 -05:00
uint32_t ds; // push %ds
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pushal
uint32_t eip, cs, eflags, useresp, ss; // pushed by cpu
} __attribute__((packed)) registers_t;
2026-06-17 18:16:47 -05:00
static int32_t sys_exit(int status) {
process_t* task = current_task();
task->state = STATE_DEAD;
kprintf("exiting task %d with status %d\n", task->pid, status);
exit();
return 0;
}
static int32_t sys_write(int fd, const void* buf, size_t count) {
if (fd < 0 || fd >= MAX_PROCESS_FDS) return -1;
file_t* f = current_task()->fd_table[fd];
if (!f || !f->node) return -1;
uint32_t rd = f->node->write(f->node, f->offset, count, (uint8_t*)buf);
f->offset += rd;
return rd;
2026-06-17 18:16:47 -05:00
}
static int32_t sys_read(int fd, void* buf, size_t count) {
if (fd < 0 || fd >= MAX_PROCESS_FDS) return -1;
file_t* f = current_task()->fd_table[fd];
if (!f || !f->node) return -1;
uint32_t rd = f->node->read(f->node, f->offset, count, (uint8_t*)buf);
f->offset += rd;
return rd;
}
static int32_t sys_open(const char* filename, int flags) {
return -1;
}
static int32_t sys_close(int fd) {
return -1;
}
static int32_t sys_brk(uint32_t new_break) {
process_t* current = current_task();
if (new_break == 0) {
return current->heap_end;
}
if (new_break < current->heap_end) {
current->heap_end = new_break;
return current->heap_end;
}
uint32_t page_start = (current->heap_end + 4095) & ~4095;
uint32_t page_end = (new_break + 4095) & ~4095;
for (uint32_t addr = page_start; addr < page_end; addr += 4096) {
// 1. Allocate a physical frame using your PMM (Physical Memory Manager)
void* phys = p_alloc_frame();
// 2. Map it into the current page directory using your VMM (Virtual Memory Manager)
map_page(addr, (uint32_t)phys, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
}
current->heap_end = new_break;
return current->heap_end;
}
static int32_t sys_pty(int* slave_fd) {
pty_t* pty = (pty_t*)kalloc(sizeof(pty_t));
ring_buf_init(&pty->master_rb);
ring_buf_init(&pty->slave_rb);
vfs_node_t* master =(vfs_node_t*)kalloc(sizeof(vfs_node_t));
master->flags = VFS_CHARDEVICE;
master->size = 0;
master->read = pty_master_read;
master->write = pty_master_write;
master->finddir = NULL;
master->data = pty;
vfs_node_t* slave =(vfs_node_t*)kalloc(sizeof(vfs_node_t));
slave->flags = VFS_CHARDEVICE;
slave->size = 0;
slave->read = pty_slave_read;
slave->write = pty_slave_write;
slave->finddir = NULL;
slave->data = pty;
file_t* fmaster = (file_t*)kalloc(sizeof(file_t));
fmaster->node = master;
fmaster->offset = 0;
fmaster->flags = 0;
file_t* fslave = (file_t*)kalloc(sizeof(file_t));
fslave->node = slave;
fslave->offset = 0;
fslave->flags = 0;
*slave_fd = alloc_fd(fslave);
return alloc_fd(fmaster);
}
static int32_t sys_fork(registers_t* parent_regs) {
process_t* parent = current_task();
2026-07-07 18:52:22 -05:00
process_t* child = kalloc(sizeof(process_t));
if (!child) {
return -1;
}
child->pid = get_next_pid();
child->state = STATE_READY;
child->flags = parent->flags;
child->heap_end = parent->heap_end;
child->sleep = 0;
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
child->fd_table[i] = parent->fd_table[i];
}
uint32_t kstack_size = 4096;
void* kstack_alloc = kalloc(kstack_size);
child->kstack_top = (uint32_t)kstack_alloc + kstack_size;
registers_t* child_regs = (registers_t*)(child->kstack_top - sizeof(registers_t));
2026-07-07 18:52:22 -05:00
memcpy(parent_regs, child_regs, sizeof(registers_t));
child_regs->eax = 0;
child->esp = (uint32_t)child_regs;
2026-07-07 18:52:22 -05:00
kprintf("child registers for PID %d\n", child->pid);
kprintf("\tEIP: 0x%x\n", child_regs->eip);
// uint32_t cr3 = (uint32_t)clone_task_pd();
child->cr3 = parent->cr3;
add_task(child);
return child->pid;
}
2026-07-07 18:52:22 -05:00
void syscall(registers_t* regs) {
int32_t ret;
switch(regs->eax) {
2026-07-07 18:52:22 -05:00
case 1: ret = sys_exit(regs->ebx); break;
case 3: ret = sys_read(regs->ebx, (void*)regs->ecx, regs->edx); break;
case 4: ret = sys_write(regs->ebx, (const void*)regs->ecx, regs->edx); break;
case 5: ret = sys_open((const char*)regs->ebx, regs->ecx); break;
case 6: ret = sys_close(regs->ebx); break;
case 12: ret = sys_brk(regs->ebx); break;
case 20: ret = sys_pty((int*)regs->ebx); break;
case 21: ret = sys_fork(regs); break;
default: ret = -1;
}
2026-07-07 18:52:22 -05:00
regs->eax = ret;
2026-06-17 18:16:47 -05:00
}