1
0
Fork 0

feat: Added syscalls and began on usermode support, still no scheduler

This commit is contained in:
Kevin Alavik 2025-06-01 18:43:06 +02:00
parent 49867193d5
commit e7b9f44384
Signed by: cmpsb
GPG key ID: 10D1CC0526FDC6D7
8 changed files with 140 additions and 2 deletions

View file

@ -0,0 +1,24 @@
global flush_tss
global jump_user
extern test_user
flush_tss:
mov ax, 5 * 8
ltr ax
ret
; void jump_user(uint64_t addr, uint64_t stack)
jump_user:
mov ax, 0x23 ; Ring 3 data with bottom 2 bits set for ring 3
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax ; SS is handled by iretq
; Set up the stack frame iretq expects
push 0x23 ; Data selector
push rsi ; Stack
pushf ; Rflags
push 0x1B ; Code selector (ring 3 code with bottom 2 bits set for ring 3)
push rdi ; Instruction address to return to
iretq

View file

@ -1,8 +1,11 @@
/* EMK 1.0 Copyright (c) 2025 Piraterna */
#include <arch/gdt.h>
#include <util/log.h>
#include <lib/string.h>
gdt_entry_t gdt[5];
gdt_entry_t gdt[7];
gdt_ptr_t gdt_ptr;
tss_entry_t tss;
void gdt_init()
{
@ -18,6 +21,34 @@ void gdt_init()
gdt_flush(gdt_ptr);
}
void flush_tss(void);
void tss_init(uint64_t stack)
{
log_early("Initializing TSS with RSP0 = 0x%.16llx", stack);
memset(&tss, 0, sizeof(tss_entry_t));
tss.rsp0 = stack;
tss.io_map_base = sizeof(tss_entry_t);
uint64_t base = (uint64_t)&tss;
uint32_t limit = sizeof(tss_entry_t) - 1;
gdt_system_entry_t tss_entry = {
.limit_low = limit & 0xFFFF,
.base_low = base & 0xFFFF,
.base_middle = (base >> 16) & 0xFF,
.access = GDT_TSS,
.granularity = (limit >> 16) & 0x0F,
.base_high = (base >> 24) & 0xFF,
.base_upper = base >> 32,
.reserved = 0,
};
memcpy(&gdt[5], &tss_entry, sizeof(gdt_system_entry_t));
gdt_flush(gdt_ptr);
flush_tss();
}
void gdt_flush(gdt_ptr_t gdt_ptr)
{
__asm__ volatile(

View file

@ -39,6 +39,37 @@ typedef struct gdt_entry
uint8_t base_high;
} __attribute__((packed)) gdt_entry_t;
typedef struct gdt_system_entry
{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
uint32_t base_upper;
uint32_t reserved;
} __attribute__((packed)) gdt_system_entry_t;
typedef struct tss_entry
{
uint32_t reserved0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t reserved1;
uint64_t ist1;
uint64_t ist2;
uint64_t ist3;
uint64_t ist4;
uint64_t ist5;
uint64_t ist6;
uint64_t ist7;
uint64_t reserved2;
uint16_t reserved3;
uint16_t io_map_base;
} __attribute__((packed)) tss_entry_t;
typedef struct gdt_ptr
{
uint16_t limit;
@ -49,5 +80,7 @@ extern gdt_ptr_t gdt_ptr;
void gdt_init();
void gdt_flush(gdt_ptr_t gdt_ptr);
void tss_init(uint64_t rsp0);
extern void jump_user(uint64_t addr, uint64_t stack);
#endif // GDT_H

View file

@ -7,6 +7,8 @@
#include <sys/kpanic.h>
#include <arch/smp.h>
#include <stdbool.h>
#include <arch/gdt.h>
#include <sys/syscall.h>
struct idt_entry __attribute__((aligned(16))) idt_descriptor[256] = {0};
idt_intr_handler real_handlers[256] = {0};
@ -20,6 +22,19 @@ struct __attribute__((packed)) idt_ptr
struct idt_ptr idt_ptr = {sizeof(idt_descriptor) - 1, (uint64_t)&idt_descriptor};
void syscall_handler(struct register_ctx *ctx)
{
log_user("syscall(%lu, 0x%.16lx, 0x%.16lx, 0x%.16lx, 0x%.16lx) from 0x%.16llx @ CPU %d",
ctx->rax,
ctx->rdi,
ctx->rsi,
ctx->rdx,
ctx->rcx,
ctx->rip, get_cpu_local()->cpu_index);
log_user("warning: No systemcall handlers available, dropping syscall...");
ctx->rax = -1;
}
void idt_default_interrupt_handler(struct register_ctx *ctx)
{
kpanic(ctx, NULL);
@ -50,6 +65,9 @@ void idt_init()
SET_GATE(i, stubs[i], IDT_INTERRUPT_GATE);
}
SET_GATE(0x80, stubs[0x80], IDT_INTERRUPT_GATE | GDT_ACCESS_RING3);
real_handlers[0x80] = syscall_handler;
__asm__ volatile(
"lidt %0"
: : "m"(idt_ptr) : "memory");

View file

@ -59,6 +59,7 @@ void smp_entry(struct limine_mp_info *smp_info)
idt_init();
pmset(kernel_pagemap);
lapic_enable();
tss_init(kstack_top);
atomic_fetch_add(&started_cpus, 1);
log_early("CPU %d (LAPIC ID %u) is up", cpu->cpu_index, lapic_id);
@ -74,6 +75,7 @@ void smp_init(void)
log_early("%u CPUs detected", cpu_count);
lapic_enable();
tss_init(kstack_top);
for (uint32_t i = 0; i < cpu_count; i++)
{

View file

@ -23,6 +23,7 @@
#include <sys/apic/lapic.h>
#include <sys/apic/ioapic.h>
#include <dev/pit.h>
#include <sys/syscall.h>
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
__attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = {
@ -72,6 +73,11 @@ void tick(struct register_ctx *)
log_early("tick on CPU %d", get_cpu_local()->cpu_index);
}
void user_func()
{
syscall(69, 69, 420, 420);
}
void emk_entry(void)
{
__asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top));
@ -210,7 +216,10 @@ void emk_entry(void)
ioapic_init();
/* Setup timer */
pit_init(tick);
pit_init(NULL);
/* Call our user space function */
user_func(); // No good way to run in usermode, yet
/* Finished */
log_early("%s", LOG_SEPARATOR);

20
kernel/src/sys/syscall.h Normal file
View file

@ -0,0 +1,20 @@
/* EMK 1.0 Copyright (c) 2025 Piraterna */
#ifndef SYSCALL_H
#define SYSCALL_H
#include <stdint.h>
/* TODO: Implement syscalls */
static inline long
syscall(uint64_t number, uint64_t arg1, uint64_t arg2, uint64_t arg3)
{
long ret;
__asm__ volatile(
"int $0x80"
: "=a"(ret)
: "a"(number), "D"(arg1), "S"(arg2), "d"(arg3)
: "memory");
return ret;
}
#endif // SYSCALL_H

View file

@ -6,5 +6,6 @@
#define log_early(fmt, ...) kprintf("early: " fmt "\n", ##__VA_ARGS__)
#define log_panic(fmt, ...) kprintf("panic: " fmt "\n", ##__VA_ARGS__)
#define log_user(fmt, ...) kprintf("user: " fmt "\n", ##__VA_ARGS__)
#endif // LOG_H