From: Duje Mihanović Date: Fri, 13 May 2022 12:17:31 +0000 (+0200) Subject: (VERY BROKEN) Enable paging X-Git-Url: https://git.dujemihanovic.xyz/duje/dujemihanovic.xyz?a=commitdiff_plain;h=decdee1c65279a5f4f8fcc558aff45d6dd1793a3;p=nameless-os.git (VERY BROKEN) Enable paging This code (somewhat) successfully enables paging and identity maps addresses 0xB8000-0xBFFFF and 0x100000-0x10FFFF. I say somewhat because enabling paging for some reason completely breaks interrupt and exception handling, making the CPU triple fault on any keypress or other exception. For that reason, DO NOT USE THIS. --- diff --git a/Makefile b/Makefile index aee8cc1..5b40214 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,10 @@ QEMU = qemu-system-i386 -monitor stdio export GIT_REV = $(shell git describe --long HEAD) -CFLAGS = -std=gnu89 -g -Iinclude/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GIT_REV)\" +CFLAGS = -g -Iinclude/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GIT_REV)\" + +KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/sample_handler.o kernel/arch/x86/mm/paging.o kernel/kernel.o -KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/sample_handler.o kernel/kernel.o BOOTLOADER_OBJ = boot/x86/mbr boot/x86/vbr-fat32 boot/x86/stage3/LOADER.BIN default: kernel/kernel.elf bootloader diff --git a/include/arch/x86/mm/paging.h b/include/arch/x86/mm/paging.h new file mode 100644 index 0000000..7d5d13f --- /dev/null +++ b/include/arch/x86/mm/paging.h @@ -0,0 +1,38 @@ +#ifndef X86_PAGING_H +#define X86_PAGING_H + +struct page_directory_entry { + unsigned p: 1, + rw: 1, + us: 1, + pwt: 1, + pcd: 1, + a: 1, + ignored: 1, + ps: 1, + ignored2: 4, + page_table_addr: 20; +} __attribute__((packed)); + +struct page_table_entry { + unsigned p: 1, + rw: 1, + us: 1, + pwt: 1, + pcd: 1, + a: 1, + d: 1, + pat: 1, + g: 1, + ignored: 3, + page_frame_addr: 20; +} __attribute__((packed)); + +struct pf_errcode { + unsigned p: 1, wr: 1, us: 1, rsvd: 1, id: 1, pk: 1, ss: 1, hlat: 1, reserved: 7, sgx: 1, reserved2: 15; +} __attribute__((packed)); + +extern inline void slice_linear_addr(void *address, short *pde, short *pte, short *offset); +extern inline void enable_paging(); + +#endif diff --git a/kernel/arch/x86/irq/sample_handler.c b/kernel/arch/x86/irq/sample_handler.c index f4f4a4b..66a3223 100644 --- a/kernel/arch/x86/irq/sample_handler.c +++ b/kernel/arch/x86/irq/sample_handler.c @@ -2,6 +2,7 @@ #include #include #include +#include typedef uint32_t uword_t; @@ -11,6 +12,13 @@ struct interrupt_frame { uword_t flags; }; +struct fault_frame { + uint32_t error_code; + uintptr_t eip; + uint16_t cs; + uint32_t eflags; +}; + struct abort_frame; __attribute__((interrupt)) @@ -21,6 +29,28 @@ void keyb_handler(struct interrupt_frame *frame) inb(0x60); } +__attribute__((interrupt)) +void pf_handler(struct fault_frame *frame) +{ + struct pf_errcode *errcode = &(frame->error_code); + kprint("A page fault occurred!\n", VGA_COLOR_DARK_RED); + if (errcode->p) { + kprint("Attempted to access non-present page\n", 0); + } + if (errcode->wr) { + kprint("Kernel attempted to write to page\n", 0); + } else kprint("Kernel attempted to read from page\n", 0); + if (errcode->id) { + kprint("Fault occurred while fetching instruction\n", 0); + } + int cr2; + asm ("mov %%cr2, %0": "=a" (cr2)); + kprint("CR2: ", 0); + kprintd(cr2); +halt: + asm ("cli; hlt"); + goto halt; +} __attribute__((interrupt)) void double_fault(struct abort_frame *frame) diff --git a/kernel/arch/x86/mm/paging.c b/kernel/arch/x86/mm/paging.c new file mode 100644 index 0000000..9a4bc06 --- /dev/null +++ b/kernel/arch/x86/mm/paging.c @@ -0,0 +1,13 @@ +#include + +inline void slice_linear_addr(void *address, short *pde, short *pte, short *offset) +{ + *pde = (int) address >> 22; + *pte = ((int) address >> 12) & 0x3ff; + *offset = (int) address & 0xfff; +} + +inline void enable_paging(struct page_directory_entry page_dir) +{ + asm ("mov %0, %%eax; mov %%eax, %%cr3; mov %%cr0, %%eax; or $0x80000000, %%eax; mov %%eax, %%cr0": : "m" (page_dir) : "eax" ); +} diff --git a/kernel/kernel.c b/kernel/kernel.c index 4c6efd8..b274340 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -3,21 +3,48 @@ #include #include #include +#include extern void double_fault(struct abort_frame *frame); extern void keyb_handler(struct interrupt_frame *frame); -struct idt_descriptor idt[256] __attribute__((aligned(0x10))); -struct idtr idtr __attribute__((aligned(0x10))); +extern void pf_handler(struct fault_frame *frame); +static struct idt_descriptor idt[256] __attribute__((aligned(0x10))); +static struct idtr idtr __attribute__((aligned(0x10))); + +static struct page_directory_entry page_dir[1024] __attribute__((aligned(0x1000))); +static struct page_table_entry page_table[1024] __attribute__((aligned(0x1000))); void kmain(void) { screen_clear(); kprint("Welcome to Nameless OS!\nRunning revision: ", 0); kprint(GIT_COMMIT, 0); - kprint("\n", 0); + kprint("\nEnabling paging...\n", 0); + for (int i=0xb8; i < 0xc0; i++) { + page_table[i].p = 1; + page_table[i].rw = 0; + page_table[i].us = 0; + page_table[i].page_frame_addr = i; + } + for (int i=0x100; i < 0x102; i++) { + page_table[i].p = 1; + page_table[i].rw = 0; + page_table[i].us = 0; + page_table[i].page_frame_addr = i; + } + for (int i=0x102; i < 0x110; i++) { + page_table[i].p = 1; + page_table[i].rw = 1; + page_table[i].us = 0; + page_table[i].page_frame_addr = i; + } + page_dir[0].p = 1; + page_dir[0].page_table_addr = (int) &page_table >> 12; + enable_paging(page_dir); kprint("Preparing IDT...\n", 0); - idt_set_descriptor(idt, 0x8, 0x8, (uint32_t) double_fault, IDT_TRAP_GATE, 0x0); - idt_set_descriptor(idt, 0x21, 0x8, (uint32_t) keyb_handler, IDT_INTERRUPT_GATE, 0x0); + idt_set_descriptor(idt, 8, 0x8, (uint32_t) double_fault, IDT_INTERRUPT_GATE, 0x0); + idt_set_descriptor(idt, 14, 0x8, (uint32_t) pf_handler, IDT_INTERRUPT_GATE, 0x0); + idt_set_descriptor(idt, 33, 0x8, (uint32_t) keyb_handler, IDT_INTERRUPT_GATE, 0x0); kprint("IDT prepared, loading...\n", 0); populate_idtr(&idtr, idt); load_idt(idtr); @@ -27,5 +54,12 @@ void kmain(void) pic_unmask(1); asm volatile ("sti"); kprint("All done\n", 0); + struct idtr curr_idtr; + asm ("sidt %0": "=m" (curr_idtr)); + kprintw(curr_idtr.limit); + kprintd(curr_idtr.base); + //kprint("Gonna force a double fault\n", 0); + //int test = 1/0; + //int test2 = *(int *) (0xa0000000); while(1); }