feat: jumping to userspace (currently only in dbg command with infinit jmp to self loop

This commit is contained in:
Karina
2026-01-29 01:10:14 +04:00
parent ae27f28d04
commit 992c249fae
10 changed files with 93 additions and 44 deletions
+2 -1
View File
@@ -5,4 +5,5 @@ kernel/data
*.md
tools/
bootloader/
bootloader/src/uefi
bootloader/src/uefi
initramfs/
+1
View File
@@ -58,6 +58,7 @@ if(QEMU_EXE)
-net none
-serial stdio
-m 512M
-s
DEPENDS image
)
endif()
+2
View File
@@ -37,4 +37,6 @@ typedef struct {
u16 iomap_base;
} __attribute__((packed)) TSS;
extern TSS tss;
void gdt_init();
+3 -2
View File
@@ -8,9 +8,10 @@ typedef struct task {
struct task* next;
u32 id;
u32 sleep_ticks;
} task_t;
u64 kernel_stack_top;
} task;
void sched_init();
task_t* sched_spawn(void(*entry)());
task* sched_spawn(void(*entry)());
u64 sched_next(u64 curr_rsp);
void yield(u64 ticks);
+16 -7
View File
@@ -4,8 +4,9 @@
// just fucking kill me already
#include <gdt.h>
#define GDT_ENTIRES 7
GDTDescriptor gdt[5];
GDTDescriptor gdt[GDT_ENTIRES];
GDTPtr gdt_ptr;
TSS tss;
u8 double_fault_stack[4096] = {0};
@@ -40,7 +41,7 @@ void write_tss(int num) {
extern void gdt_flush(u64 gdt_ptr_addr); // entry.asm
void gdt_init() {
gdt_ptr.limit = (sizeof(GDTDescriptor) * 5) - 1;
gdt_ptr.limit = (sizeof(GDTDescriptor) * GDT_ENTIRES) - 1;
gdt_ptr.base = (u64)&gdt;
// 0: Null
@@ -53,17 +54,25 @@ void gdt_init() {
// 0x20 = 0010 0000 bit 5 is "Long mode"
// 2: Kernel Data (Ring 0)
// Access: 0x92 (Present, Ring0, Read/Write)
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 can't exec
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // hack. zeroifying tss struct
// 3: User Data (Ring 3)
// Access: 0xF2 (Present, Ring3, Read/Write)
gdt_set_gate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
// 4: User Code (Ring 3)
// Access: 0xFA (Present, Ring3, RWX)
gdt_set_gate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // zeroifying tss struct
tss.iomap_base = sizeof(TSS);
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
write_tss(3);
write_tss(5);
gdt_flush((u64)&gdt_ptr);
// telling cpu that TSS info located at gdt[3]; offset = 3 * 8 = 24 = 0x18
__asm__ volatile ("ltr %%ax" :: "a" (0x18));
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
}
+1 -1
View File
@@ -133,7 +133,7 @@ __attribute__((noreturn)) void panic_exception(Registers *regs) {
u64 user = (regs->err_code & (1 << 2)) != 0;
u64 reserved = (regs->err_code & (1 << 3)) != 0;
u64 instruction = (regs->err_code & (1 << 4)) != 0;
kprintf("\t\t\t[^bP^!] ^yReason^! %s\n", present ? "Page Protection violation" : "Non-present page");
kprintf("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
kprintf("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
kprintf("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
if (reserved) kprintf("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
+9 -7
View File
@@ -4,14 +4,15 @@
#include <core/panic.h>
#include <core/scheduler.h>
#include <mm/heap.h>
#include <gdt.h>
task_t* curr_task = nullptr;
task* curr_task = nullptr;
u32 next_pid = 1;
extern void irq0_handler();
void sched_init() {
task_t* kt = (task_t*)malloc(sizeof(task_t));
task* kt = (task*)malloc(sizeof(task));
kt->id = 0;
kt->sleep_ticks = 0;
@@ -20,8 +21,8 @@ void sched_init() {
curr_task = kt;
}
task_t* sched_spawn(void(*entry)()) {
task_t* t = (task_t*)malloc(sizeof(task_t));
task* sched_spawn(void(*entry)()) {
task* t = (task*)malloc(sizeof(task));
if (!t) return nullptr;
u64 stack_size = 16384;
@@ -44,8 +45,8 @@ task_t* sched_spawn(void(*entry)()) {
t->id = next_pid++;
t->sleep_ticks = 0;
t->next = curr_task->next;
t->kernel_stack_top = (u64)stack_base + stack_size;
curr_task->next = t;
return t;
}
@@ -53,7 +54,7 @@ u64 sched_next(u64 curr_rsp) {
if (!curr_task) return curr_rsp;
curr_task->rsp = curr_rsp;
task_t* it = curr_task->next;
task* it = curr_task->next;
do {
if (it->sleep_ticks > 0) it->sleep_ticks--;
@@ -62,10 +63,11 @@ u64 sched_next(u64 curr_rsp) {
if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--;
task_t* next = curr_task->next;
task* next = curr_task->next;
while (next != curr_task && next->sleep_ticks > 0) next = next->next; // what the fuck i just wrote
curr_task = next;
tss.rsp0 = curr_task->kernel_stack_top;
return curr_task->rsp;
}
+2 -2
View File
@@ -63,10 +63,10 @@ void kmain(Bootinfo* info) {
fs_node* root = cpio_mount(PHYS_TO_HHDM(info->initramfs.addr), info->initramfs.size);
vfs_init(root);
kprintf("VFS initialized");
kprintf("VFS initialized\n");
u32 *fb = (u32*)info->framebuffer.base;
if (!fb) return serial_write("No framebuffer found!!");
if (!fb) return kprintf("No framebuffer found!!");
sg_ctx.fb = fb;
sg_ctx.height = info->framebuffer.height;
+11 -4
View File
@@ -18,7 +18,6 @@ extern u64 _kernel_end;
extern u8* bitmap;
extern u64 bitmap_size_g;
extern GDTDescriptor gdt[];
extern TSS tss[];
extern IDTEntry idt[];
extern u8 double_fault_stack[];
extern u8 stack_guard;
@@ -37,12 +36,16 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
u64* pml4_virt = pml4;
if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4);
u64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
u64* addr = pmm_alloc_page();
if (!addr) return nullptr;
u64* addr_virt = get_table_virt((u64)addr);
memset(addr_virt, 0, PAGE_SIZE);
pml4_virt[pml4_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
pml4_virt[pml4_idx] = (u64)addr | table_flags;
} else {
pml4_virt[pml4_idx] |= (flags & PTE_USER);
}
u64* pdpt = (u64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
@@ -53,7 +56,9 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
if (!addr) return nullptr;
u64* addr_virt = get_table_virt((u64)addr);
memset(addr_virt, 0, PAGE_SIZE);
pdpt_virt[pdpt_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
pdpt_virt[pdpt_idx] = (u64)addr | table_flags;
} else {
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
}
u64* pd = (u64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
@@ -64,7 +69,9 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
if (!addr) return nullptr;
u64* addr_virt = get_table_virt((u64)addr);
memset(addr_virt, 0, PAGE_SIZE);
pd_virt[pd_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
pd_virt[pd_idx] = (u64)addr | table_flags;
} else {
pd_virt[pd_idx] |= (flags & PTE_USER);
}
u64* pt = (u64*)PTE_GET_ADDR(pd_virt[pd_idx]);
+46 -20
View File
@@ -3,29 +3,55 @@
// contents of this file will be changed CONSTANTLY
// im just testing new stuff here
#include <drivers/console.h>
#include "mm/vmm.h"
#include <mm/pmm.h>
#include <shell/dbgcmd.h>
#include <fs/vfs.h>
#include <mm/memory.h>
#include <drivers/console.h>
extern u64* pml4_kernel;
#define USER_DS (0x18 | 3)
#define USER_CS (0x20 | 3)
#define RFLAGS_IF 0x202
void jump_to_userspace(void* entry, void* user_stack_top) {
__asm__ volatile (
"mov %0, %%ds\n"
"mov %0, %%es\n"
"mov %0, %%fs\n"
"mov %0, %%gs\n"
:: "r" ((u64)USER_DS) : "memory"
);
__asm__ volatile (
"pushq %0\n" // SS (User Data Selector)
"pushq %1\n" // RSP (User Stack Pointer)
"pushq %2\n" // RFLAGS
"pushq %3\n" // CS (User Code Selector)
"pushq %4\n" // RIP (Entry Point)
"iretq\n" // jump
:
: "r" ((u64)USER_DS),
"r" ((u64)user_stack_top),
"r" ((u64)RFLAGS_IF),
"r" ((u64)USER_CS),
"r" ((u64)entry)
: "memory"
);
}
u64 debug() {
kprintf("Debug: Trying to open /test1.txt...\n");
fs_node* file = vfs_open("/test1.txt");
if (file == nullptr) {
kprintf("Error: File not found! Check initrd or filename.\n");
return 1;
}
kprintf("Success!\n");
kprintf("\tFilename: %s\n", file->name);
kprintf("\tSize: %d bytes\n", file->len);
char buf[64];
memset(buf, 0, 64);
vfs_read(file, 0, 63, (u8*)buf);
kprintf("\tContent: %s\n", buf);
void* phys_code = pmm_alloc_page();
void* phys_stack = pmm_alloc_page();
u64 virt_code = 0x400000;
u64 virt_stack = 0x800000;
vmm_map_page(pml4_kernel, (u64)phys_code, virt_code, PTE_PRESENT | PTE_RW | PTE_USER);
vmm_map_page(pml4_kernel, (u64)phys_stack, virt_stack, PTE_PRESENT | PTE_RW | PTE_USER);
u8* kernel_view = (u8*)(HHDM_OFFSET + phys_code);
kernel_view[0] = 0xEB; // jmp
kernel_view[1] = 0xFE; // to self
kprintf("Jumping to userspace. Goodbye.");
jump_to_userspace((void*)virt_code, (void*)(virt_stack + 4096));
return 0;
}