feat: Added syscalls and began on usermode support, still no scheduler
This commit is contained in:
parent
49867193d5
commit
e7b9f44384
8 changed files with 140 additions and 2 deletions
24
kernel/src/arch/gdt-helper.asm
Normal file
24
kernel/src/arch/gdt-helper.asm
Normal 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
|
|
@ -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(
|
||||
|
|
|
@ -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
|
|
@ -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");
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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
20
kernel/src/sys/syscall.h
Normal 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
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue