]> git.dujemihanovic.xyz Git - nameless-os.git/commitdiff
(VERY BROKEN) Enable paging
authorDuje Mihanović <duje.mihanovic@skole.hr>
Fri, 13 May 2022 12:17:31 +0000 (14:17 +0200)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Wed, 22 Jun 2022 16:03:18 +0000 (18:03 +0200)
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.

Makefile
include/arch/x86/mm/paging.h [new file with mode: 0644]
kernel/arch/x86/irq/sample_handler.c
kernel/arch/x86/mm/paging.c [new file with mode: 0644]
kernel/kernel.c

index aee8cc187a36d118823f8b1e66abedbbd4a99d87..5b40214989ee0e5d41683090ce6001711e582084 100644 (file)
--- 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 (file)
index 0000000..7d5d13f
--- /dev/null
@@ -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
index f4f4a4bfefad5aacf742f3c6ce2046c86eb1b85e..66a3223583249ef18041a7f6d7d5fb38245a9b08 100644 (file)
@@ -2,6 +2,7 @@
 #include <irq/i8259a.h>
 #include <io.h>
 #include <stdint.h>
+#include <mm/paging.h>
 
 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 (file)
index 0000000..9a4bc06
--- /dev/null
@@ -0,0 +1,13 @@
+#include <mm/paging.h>
+
+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" );
+}
index 4c6efd8692da90d7ab15cf782846b3194e9483f7..b274340cd2605ca7a905579cf06f0b32adbf8d99 100644 (file)
@@ -3,21 +3,48 @@
 #include <irq/idt.h>
 #include <irq/i8259a.h>
 #include <stdint.h>
+#include <mm/paging.h>
 
 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);
 }