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 */
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
#include <arch/gdt.h>
|
#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;
|
gdt_ptr_t gdt_ptr;
|
||||||
|
tss_entry_t tss;
|
||||||
|
|
||||||
void gdt_init()
|
void gdt_init()
|
||||||
{
|
{
|
||||||
|
@ -18,6 +21,34 @@ void gdt_init()
|
||||||
gdt_flush(gdt_ptr);
|
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)
|
void gdt_flush(gdt_ptr_t gdt_ptr)
|
||||||
{
|
{
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
|
|
|
@ -39,6 +39,37 @@ typedef struct gdt_entry
|
||||||
uint8_t base_high;
|
uint8_t base_high;
|
||||||
} __attribute__((packed)) gdt_entry_t;
|
} __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
|
typedef struct gdt_ptr
|
||||||
{
|
{
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
|
@ -49,5 +80,7 @@ extern gdt_ptr_t gdt_ptr;
|
||||||
|
|
||||||
void gdt_init();
|
void gdt_init();
|
||||||
void gdt_flush(gdt_ptr_t gdt_ptr);
|
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
|
#endif // GDT_H
|
|
@ -7,6 +7,8 @@
|
||||||
#include <sys/kpanic.h>
|
#include <sys/kpanic.h>
|
||||||
#include <arch/smp.h>
|
#include <arch/smp.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <arch/gdt.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
struct idt_entry __attribute__((aligned(16))) idt_descriptor[256] = {0};
|
struct idt_entry __attribute__((aligned(16))) idt_descriptor[256] = {0};
|
||||||
idt_intr_handler real_handlers[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};
|
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)
|
void idt_default_interrupt_handler(struct register_ctx *ctx)
|
||||||
{
|
{
|
||||||
kpanic(ctx, NULL);
|
kpanic(ctx, NULL);
|
||||||
|
@ -50,6 +65,9 @@ void idt_init()
|
||||||
SET_GATE(i, stubs[i], IDT_INTERRUPT_GATE);
|
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(
|
__asm__ volatile(
|
||||||
"lidt %0"
|
"lidt %0"
|
||||||
: : "m"(idt_ptr) : "memory");
|
: : "m"(idt_ptr) : "memory");
|
||||||
|
|
|
@ -59,6 +59,7 @@ void smp_entry(struct limine_mp_info *smp_info)
|
||||||
idt_init();
|
idt_init();
|
||||||
pmset(kernel_pagemap);
|
pmset(kernel_pagemap);
|
||||||
lapic_enable();
|
lapic_enable();
|
||||||
|
tss_init(kstack_top);
|
||||||
|
|
||||||
atomic_fetch_add(&started_cpus, 1);
|
atomic_fetch_add(&started_cpus, 1);
|
||||||
log_early("CPU %d (LAPIC ID %u) is up", cpu->cpu_index, lapic_id);
|
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);
|
log_early("%u CPUs detected", cpu_count);
|
||||||
|
|
||||||
lapic_enable();
|
lapic_enable();
|
||||||
|
tss_init(kstack_top);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cpu_count; i++)
|
for (uint32_t i = 0; i < cpu_count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <sys/apic/lapic.h>
|
#include <sys/apic/lapic.h>
|
||||||
#include <sys/apic/ioapic.h>
|
#include <sys/apic/ioapic.h>
|
||||||
#include <dev/pit.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 LIMINE_BASE_REVISION(3);
|
||||||
__attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = {
|
__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);
|
log_early("tick on CPU %d", get_cpu_local()->cpu_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void user_func()
|
||||||
|
{
|
||||||
|
syscall(69, 69, 420, 420);
|
||||||
|
}
|
||||||
|
|
||||||
void emk_entry(void)
|
void emk_entry(void)
|
||||||
{
|
{
|
||||||
__asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top));
|
__asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top));
|
||||||
|
@ -210,7 +216,10 @@ void emk_entry(void)
|
||||||
ioapic_init();
|
ioapic_init();
|
||||||
|
|
||||||
/* Setup timer */
|
/* Setup timer */
|
||||||
pit_init(tick);
|
pit_init(NULL);
|
||||||
|
|
||||||
|
/* Call our user space function */
|
||||||
|
user_func(); // No good way to run in usermode, yet
|
||||||
|
|
||||||
/* Finished */
|
/* Finished */
|
||||||
log_early("%s", LOG_SEPARATOR);
|
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_early(fmt, ...) kprintf("early: " fmt "\n", ##__VA_ARGS__)
|
||||||
#define log_panic(fmt, ...) kprintf("panic: " 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
|
#endif // LOG_H
|
Loading…
Add table
Add a link
Reference in a new issue