From faa6ce0757094cfcc167034f87d68ef3f2d6c938 Mon Sep 17 00:00:00 2001 From: rami Date: Wed, 3 Jul 2024 21:55:44 -0400 Subject: [PATCH] enable paging --- include/kernel/kernel.h | 53 ++++++++++++++++++++++++++++++++++ kernel/init.asm | 19 ++++++++++++ kernel/kernel.c | 64 +++++++++++++++++++++++++++++++++++------ 3 files changed, 128 insertions(+), 8 deletions(-) diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h index 23b8b07..b956688 100644 --- a/include/kernel/kernel.h +++ b/include/kernel/kernel.h @@ -16,4 +16,57 @@ typedef struct { uint64_t ticks; } kernel_ctx_t; +#define GDT_NULL 0 +#define GDT_KERNEL_CODE 1 +#define GDT_KERNEL_DATA 2 +#define GDT_USER_CODE 3 +#define GDT_USER_DATA 4 + +#define RING0 0 +#define RING3 3 + +#define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p) + +struct gdt_entry { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; +} __attribute__((packed)); +typedef struct gdt_entry gdt_t; + +struct tss_entry { + uint32_t prev_tss; // The previous TSS - with hardware task switching this is used + uint32_t esp0; // The stack pointer to load when we change to kernel mode + uint32_t ss0; // The stack segment to load when we change to kernel mode + uint32_t esp1; // Unused... + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; // The value to load into ES when we change to kernel mode + uint32_t cs; // The value to load into CS when we change to kernel mode + uint32_t ss; // The value to load into SS when we change to kernel mode + uint32_t ds; // The value to load into DS when we change to kernel mode + uint32_t fs; // The value to load into FS when we change to kernel mode + uint32_t gs; // The value to load into GS when we change to kernel mode + uint32_t ldt; // Unused... + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); +typedef struct tss_entry tss_t; + + #endif diff --git a/kernel/init.asm b/kernel/init.asm index e06490a..a7da8b8 100644 --- a/kernel/init.asm +++ b/kernel/init.asm @@ -75,6 +75,23 @@ jmp_user_mode: iret +global flush_tss +flush_tss: + ltr [esp+4] + ret + +global enable_paging +enable_paging: + push eax + mov eax, [esp+4] + mov cr3, eax + + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + pop eax + ret + extern exception_handler %macro isr_err_stub 1 isr_stub_%+%1: @@ -174,6 +191,8 @@ gdt_user_data: db 0b11110010 db 0b11001111 db 0x00 +tss: + dq 0 gdt_end: gdtp: diff --git a/kernel/kernel.c b/kernel/kernel.c index 8d09321..7a45e72 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -5,18 +5,19 @@ #include #include #include +#include kernel_ctx_t ctx = {0}; struct idt_entry idt[256] = {0}; struct idtr idtr = {0}; +tss_t tss = {0}; extern uint32_t isr_stub_table[32]; extern void pit_isr(void); extern void jmp_user_mode(uint32_t esp, uint32_t eip); - -void test_entry(void) { - for (;;) {} -} +extern void flush_tss(uint32_t segment_selector); +extern gdt_t gdt[6]; +extern void enable_paging(uint32_t *page_directory); void exception_handler(int_stack_frame_t r) { LOG("Exception 0x%X (0x%X) has occurred\nEAX: 0x%08X\nECX: 0x%08X\nEDX: 0x%08X\nEBX: 0x%08X\nESI: 0x%08X\nEDI: 0x%08X\nEBP: 0x%08X\nESP: 0x%08X\n", @@ -31,6 +32,15 @@ void sleep(int delay) { cpu_relax; } +typedef struct { + uint32_t eip; + uint32_t esp; + uint32_t cr3; +} task_t; + +__attribute__((aligned(4096))) uint32_t page_dir[1024]; +__attribute__((aligned(4096))) uint32_t page_tab[1024]; + void kernel(multiboot_info_t *info) { if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map @@ -47,21 +57,59 @@ void kernel(multiboot_info_t *info) { for (int i = 0; i < 32; i++) { idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT); } - idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT); + idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(1, 0), INT_GATE_32 | INT_RING0 | INT_PRESENT); idtr.size = (sizeof(struct idt_entry) * 256) - 1; idtr.base = (uint32_t) idt; asm volatile ("lidt %0" :: "m"(idtr)); pic_remap(PIC_1_START, PIC_2_START); - //asm volatile ("sti" ::); + /* + asm volatile ("sti" ::); ctx.ticks = 0; - //pit_init(); + pit_init(); + + uint32_t base = (uint32_t)&tss; + uint32_t limit = base + sizeof(tss_t); + gdt[5].base_low = base & 0xFFFF; + gdt[5].base_middle = (base >> 16) & 0xFF; + gdt[5].base_high = (base >> 24) & 0xFF; + gdt[5].limit_low = limit & 0xFFFF; + gdt[5].granularity = (limit >> 16) & 0x0F; + gdt[5].granularity |= 0x40; + gdt[5].access = 0x89; + tss.ss0 = GDT_SEGMENT_SELECTOR(2, RING0); + tss.esp0 = 0; + tss.cs = GDT_SEGMENT_SELECTOR(3, RING3); + tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(4, RING3); + flush_tss(GDT_SEGMENT_SELECTOR(5, RING3)); + */ + +#define PAGE_PRESENT (1<<0) +#define PAGE_RW (1<<1) +#define PAGE_USER (1<<2) + +#define PAGE_DIR_INDEX(x) (((x) >> 22) & 0x3FF) +#define PAGE_TAB_INDEX(x) (((x) >> 12) & 0x3FF) +#define PAGE_OFFSET(x) ((x) & 0xFFF) + + LOG("Page directory: %08X -- Page table: %08X\n", page_dir, page_tab); + + for (int i = 0; i < 1024; i++) { + page_tab[i] = (i * 0x1000) | PAGE_PRESENT | PAGE_RW | PAGE_USER; + } + + for (int i = 0; i < 1024; i++) { + page_dir[i] = ((uint32_t)page_tab) | PAGE_PRESENT | PAGE_RW | PAGE_USER; + } + + enable_paging(page_dir); uint32_t stack = (uint32_t)mmap_find_first_free_block(); multi_mod_t *init = (multi_mod_t *)info->moduleaddress; - LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X", init->mod_start, stack+0x1000); + LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", init->mod_start, stack+0x1000); + jmp_user_mode(stack+0x1000, init->mod_start); halt: