feat: jumping to userspace (currently only in dbg command with infinit jmp to self loop
This commit is contained in:
@@ -37,4 +37,6 @@ typedef struct {
|
||||
u16 iomap_base;
|
||||
} __attribute__((packed)) TSS;
|
||||
|
||||
extern TSS tss;
|
||||
|
||||
void gdt_init();
|
||||
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user