sys: Refactor GDT initialization, enhance syscall handling, and improve user mode entry
Finally we got usermode working again, It took awhile but we got it done. A few things we did in this commit: - Simplified GDT entry initialization in gdt.c for kernel and user segments. - Fixed TSS structure for task switching. - Implemented cr2 handling in a page fault. - Enhanced user stack setup in usermode.c to return the correct RSP. - Improved syscall implementation in syscall.c, including new syscall numbers. - Updated syscall entry to correctly handle context switching and argument passing. - Refactored init.c to demonstrate file operations using syscalls. - Added new syscalls for file operations in syscalls.h. - Modified VFS to handle leading slashes in paths correctly. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
+17
-29
@@ -50,39 +50,27 @@ void x86_64_GDT_Initialize(void) {
|
||||
|
||||
// null desc
|
||||
memset(&gdt.entries[0], 0, sizeof(struct gdt_desc));
|
||||
// Kernel code 0x08
|
||||
gdt.entries[1].limit = 0xFFFF;
|
||||
gdt.entries[1].base_low = 0;
|
||||
gdt.entries[1].base_mid = 0;
|
||||
gdt.entries[1].base_hi = 0;
|
||||
gdt.entries[1].access = 0b10011010;
|
||||
gdt.entries[1].granularity = 0b00100000;
|
||||
// Kernel code
|
||||
gdt.entries[1].limit = 0xFFFF;
|
||||
gdt.entries[1].access = 0x9A;
|
||||
gdt.entries[1].granularity = 0x20;
|
||||
|
||||
// Kernel data 0x10
|
||||
gdt.entries[2].limit = 0xFFFF;
|
||||
gdt.entries[2].base_low = 0;
|
||||
gdt.entries[2].base_mid = 0;
|
||||
gdt.entries[2].base_hi = 0;
|
||||
gdt.entries[2].access = 0b10010010;
|
||||
gdt.entries[2].granularity = 0b00100000;
|
||||
// Kernel data
|
||||
gdt.entries[2].limit = 0xFFFF;
|
||||
gdt.entries[2].access = 0x92;
|
||||
gdt.entries[2].granularity = 0x00;
|
||||
|
||||
// User data 0x1B
|
||||
gdt.entries[3].limit = 0xFFFF;
|
||||
gdt.entries[3].base_low = 0;
|
||||
gdt.entries[3].base_mid = 0;
|
||||
gdt.entries[3].base_hi = 0;
|
||||
gdt.entries[3].access = 0b11110010;
|
||||
gdt.entries[3].granularity = 0b00100000;
|
||||
// User data
|
||||
gdt.entries[3].limit = 0xFFFF;
|
||||
gdt.entries[3].access = 0xF2;
|
||||
gdt.entries[3].granularity = 0x00;
|
||||
|
||||
// User code 0x23
|
||||
gdt.entries[4].limit = 0xFFFF;
|
||||
gdt.entries[4].base_low = 0;
|
||||
gdt.entries[4].base_mid = 0;
|
||||
gdt.entries[4].base_hi = 0;
|
||||
gdt.entries[4].access = 0b11111010;
|
||||
gdt.entries[4].granularity = 0b00100000;
|
||||
// User code
|
||||
gdt.entries[4].limit = 0xFFFF;
|
||||
gdt.entries[4].access = 0xFA;
|
||||
gdt.entries[4].granularity = 0x20;
|
||||
|
||||
// TSS
|
||||
// TSS 0x28
|
||||
gdt.tss.length = sizeof(struct tss);
|
||||
gdt.tss.flags1 = 0b10001001;
|
||||
|
||||
|
||||
@@ -30,5 +30,7 @@ struct tss {
|
||||
uint16_t iomap_base;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct tss kernel_tss;
|
||||
|
||||
void x86_64_GDT_Initialize(void);
|
||||
void gdt_load_tss(size_t addr);
|
||||
@@ -6,13 +6,13 @@
|
||||
gdt_reload:
|
||||
lgdt [rip + gdt_pointer]
|
||||
|
||||
push 8
|
||||
push 0x08
|
||||
lea rax, [rip + .flush]
|
||||
push rax
|
||||
lretq
|
||||
|
||||
.flush:
|
||||
mov eax, 0x10
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
#include "idt.h"
|
||||
#define MODULE "ISR"
|
||||
|
||||
static inline uint64_t x86_64_read_cr2(void)
|
||||
{
|
||||
uint64_t value;
|
||||
__asm__ volatile ("mov %%cr2, %0" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
ISRHandler g_ISRHandlers[256];
|
||||
static const char* const g_Exceptions[] = {
|
||||
@@ -52,8 +58,44 @@ void x86_64_ISR_Initialize(void)
|
||||
x86_64_IDT_DisableGate(0x80); // syscall gate if you want
|
||||
}
|
||||
|
||||
void page_fault_handler(Registers* regs, uint64_t cr2)
|
||||
{
|
||||
|
||||
|
||||
// You can decode error bits here:
|
||||
// bit 0: present
|
||||
// bit 1: write
|
||||
// bit 2: user-mode
|
||||
// bit 3: reserved overwrite
|
||||
// bit 4: instruction fetch
|
||||
|
||||
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
|
||||
|
||||
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
|
||||
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
|
||||
|
||||
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
|
||||
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
|
||||
|
||||
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
|
||||
|
||||
log_crit("PAGEFAULT", "Fault at address %lx (rip=%lx, err=%x)",
|
||||
cr2, regs->rip, regs->error);
|
||||
|
||||
log_crit(MODULE, "KERNEL PANIC!");
|
||||
|
||||
x86_64_Panic(); // or attempt recovery
|
||||
}
|
||||
|
||||
void __attribute__((used)) x86_64_ISR_Handler(Registers* regs)
|
||||
{
|
||||
if (regs->interrupt == 14)
|
||||
{
|
||||
uint64_t cr2 = x86_64_read_cr2();
|
||||
page_fault_handler(regs, cr2);
|
||||
|
||||
}
|
||||
|
||||
if (g_ISRHandlers[regs->interrupt])
|
||||
g_ISRHandlers[regs->interrupt](regs);
|
||||
else if (regs->interrupt >= 32)
|
||||
|
||||
+42
-24
@@ -22,54 +22,73 @@ static uint64_t user_stack_phys_base = 0;
|
||||
|
||||
extern struct pagemap *kernel_pagemap;
|
||||
|
||||
static void setup_user_stack()
|
||||
uintptr_t setup_user_stack(void)
|
||||
{
|
||||
// Allocate contiguous physical pages for the stack
|
||||
user_stack_phys_base = (uint64_t)pmm_alloc(USER_STACK_PAGES);
|
||||
|
||||
if (!user_stack_phys_base) {
|
||||
printf("Failed to allocate user stack pages!\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
uintptr_t stack_bottom = USER_STACK_TOP - USER_STACK_SIZE;
|
||||
uintptr_t virt = stack_bottom;
|
||||
|
||||
for (int i = 0; i < USER_STACK_PAGES; i++) {
|
||||
uint64_t phys = user_stack_phys_base + i * PAGE_SIZE;
|
||||
uintptr_t virt = stack_bottom + i * PAGE_SIZE;
|
||||
uintptr_t phys = user_stack_phys_base + i * PAGE_SIZE;
|
||||
|
||||
if (!vmm_map_page(kernel_pagemap, virt, phys,
|
||||
PAGE_READ | PAGE_WRITE | PAGE_USER, Size4KiB)) {
|
||||
printf("Failed to map user stack at 0x%lx\n", virt);
|
||||
if (!vmm_map_page(kernel_pagemap,
|
||||
virt,
|
||||
phys,
|
||||
PAGE_READ | PAGE_WRITE | PAGE_USER,
|
||||
Size4KiB))
|
||||
{
|
||||
printf("Failed mapping user stack page\n");
|
||||
for (;;);
|
||||
}
|
||||
virt += PAGE_SIZE;
|
||||
}
|
||||
// Zero the stack
|
||||
memset((void*)stack_bottom, 0, USER_STACK_SIZE);
|
||||
}
|
||||
|
||||
// zero physical page through HHDM
|
||||
//memset((void *)(phys + g_hhdm_offset), 0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
uintptr_t rsp = USER_STACK_TOP;
|
||||
|
||||
rsp &= ~0xFULL;
|
||||
|
||||
return rsp;
|
||||
}
|
||||
|
||||
|
||||
// usermode.c
|
||||
__attribute__((naked))
|
||||
void enter_user_mode(uint64_t rip, uint64_t rsp)
|
||||
{
|
||||
asm volatile (
|
||||
asm volatile(
|
||||
"cli\n\t"
|
||||
"mov $0x1B, %%ax\n\t" // User data segment
|
||||
"mov $0x1B, %%ax\n\t"
|
||||
"mov %%ax, %%ds\n\t"
|
||||
"mov %%ax, %%es\n\t"
|
||||
"mov %%ax, %%fs\n\t"
|
||||
"mov %%ax, %%gs\n\t"
|
||||
|
||||
"push $0x1B\n\t" // SS (user data)
|
||||
"push %1\n\t" // RSP
|
||||
// SS
|
||||
"pushq $0x1B\n\t"
|
||||
|
||||
// RSP
|
||||
"pushq %1\n\t"
|
||||
|
||||
// RFLAGS
|
||||
"pushfq\n\t"
|
||||
"pop %%rax\n\t"
|
||||
"or $0x200, %%rax\n\t" // Enable interrupts
|
||||
"push %%rax\n\t" // RFLAGS
|
||||
"push $0x23\n\t" // CS (user code)
|
||||
"push %0\n\t" // RIP
|
||||
"or $0x200, %%rax\n\t"
|
||||
"push %%rax\n\t"
|
||||
|
||||
// CS
|
||||
"pushq $0x23\n\t"
|
||||
|
||||
// RIP
|
||||
"pushq %0\n\t"
|
||||
|
||||
"iretq\n\t"
|
||||
:
|
||||
: "r"(rip), "r"(rsp)
|
||||
@@ -91,10 +110,9 @@ void start_userspace(void)
|
||||
for(;;);
|
||||
}
|
||||
|
||||
setup_user_stack();
|
||||
uintptr_t rsp = setup_user_stack();
|
||||
|
||||
printf("Jumping to user entry: 0x%lx with stack top 0x%lx\n",
|
||||
(uint64_t)entry, USER_STACK_TOP);
|
||||
printf("Entering usermode RIP=%p RSP=%p\n", entry, (void*)rsp);
|
||||
|
||||
enter_user_mode((uint64_t)entry, USER_STACK_TOP);
|
||||
enter_user_mode((uint64_t)entry, (rsp & ~0xFULL));
|
||||
}
|
||||
Reference in New Issue
Block a user