]> git.dujemihanovic.xyz Git - nameless-os.git/commitdiff
Enable paging in bootloader
authorDuje Mihanović <duje.mihanovic@skole.hr>
Fri, 17 Jun 2022 08:57:56 +0000 (10:57 +0200)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Wed, 22 Jun 2022 16:03:18 +0000 (18:03 +0200)
This makes interrupt handling functional. The keyboard handler also tries to
read from an unmapped address to demonstrate the page fault handler.

Makefile
boot/x86/stage3/loader.s
boot/x86/stage3/paging.s [new file with mode: 0644]
include/arch/x86/mm/paging.h
kernel/arch/x86/irq/sample_handler.c
kernel/arch/x86/mm/paging.c [deleted file]
kernel/kernel.c
kernel/linker.ld

index 5b40214989ee0e5d41683090ce6001711e582084..c823fc4d53015e5c1e7e9f783f4ebf2be3b7af80 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ export GIT_REV = $(shell git describe --long HEAD)
 
 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
 
index ec08c61bd0f5d00644cf471ebe26274f93153c9e..2967c6ee7b1d9f00c1d9fb1ef732f02a10c3847e 100644 (file)
@@ -160,7 +160,11 @@ bits 32
        mov ss, ax
        mov fs, ax
        mov gs, ax
-       call 0x100000
+
+       call load_paging_structs
+       call enable_paging
+
+       call 0xc0000000
        hlt
        jmp $-1
 
@@ -186,3 +190,5 @@ ss_s: db "SS: ", 0
 space: db " ", 0
 hex_delm: db "0x", 0
 newline: db 0xd, 0xa, 0
+
+%include "paging.s"
diff --git a/boot/x86/stage3/paging.s b/boot/x86/stage3/paging.s
new file mode 100644 (file)
index 0000000..004da84
--- /dev/null
@@ -0,0 +1,80 @@
+; Code for enabling paging before calling the kernel
+; Identity maps the VGA framebuffer memory and high-half maps the kernel memory
+bits 32
+
+section .text
+
+; The problem with this code is that it assumes that the kernel's various
+; sections occupy a certain number of pages. As of writing it is correct, but as
+; the kernel grows this code may fail to map those pages, which is not good. The
+; solution to this is to use ELF instead of a flat binary. This was not done
+; before because it would require paging, but now that paging works using ELF is
+; a possibility which must be exploited.
+
+enable_paging:
+       push eax
+       mov eax, cr0
+       or eax, 0x80000000
+       mov cr0, eax
+       pop eax
+       ret
+
+load_paging_structs:
+       push eax
+       push ebx
+       xor ebx, ebx
+.pt_low_loop:
+       mov eax, ebx
+       shl eax, 12
+       or eax, 1|2 ; P and R/W flags
+       mov [page_table_low+ebx*4], eax
+       inc ebx
+       cmp ebx, 0x100
+       jl .pt_low_loop
+
+       xor ebx, ebx
+.pt_high_ro_loop:
+       mov eax, ebx
+       add eax, 0x100
+       shl eax, 12
+       or eax, 1 ; P flag
+       mov [page_table_high+ebx*4], eax
+       inc ebx
+       cmp ebx, 0x2
+       jl .pt_high_ro_loop
+
+       mov ebx, 0x2
+.pt_high_rw_loop:
+       mov eax, ebx
+       add eax, 0x100
+       shl eax, 12
+       or eax, 1|2 ; P and R/W flags
+       mov [page_table_high+ebx*4], eax
+       inc ebx
+       cmp ebx, 0x9
+       jl .pt_high_rw_loop
+
+       mov eax, page_table_low
+       and eax, 0xfffff000
+       or eax, 1|2
+       mov [page_directory], eax
+
+       mov eax, page_table_high
+       and eax, 0xfffff000
+       or eax, 1|2
+       mov [page_directory+768*4], eax
+
+       mov eax, page_directory
+       mov cr3, eax
+       pop ebx
+       pop eax
+       ret
+
+section .data
+align 4096
+page_table_low:
+       times 1024 dd 0
+page_table_high:
+       times 1024 dd 0
+page_directory:
+       times 1024 dd 0
index 7d5d13f7697874824e1710d5a8157f47327729ad..a4bdf227b498e9cb6292f8e8c81002adf1615fb0 100644 (file)
@@ -32,7 +32,4 @@ 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 66a3223583249ef18041a7f6d7d5fb38245a9b08..0ba022287400813058340d07504939dcc347e508 100644 (file)
@@ -13,7 +13,7 @@ struct interrupt_frame {
 };
 
 struct fault_frame {
-       uint32_t error_code;
+       struct pf_errcode error_code;
        uintptr_t eip;
        uint16_t cs;
        uint32_t eflags;
@@ -27,28 +27,33 @@ void keyb_handler(struct interrupt_frame *frame)
        pic_send_eoi(1);
        kprint("Got a keyboard interrupt!\n", 0);
        inb(0x60);
+       int a = *(int *) (0xa0000000);
 }
 
 __attribute__((interrupt))
 void pf_handler(struct fault_frame *frame)
 {
-       struct pf_errcode *errcode = &(frame->error_code);
+       int address;
+       struct pf_errcode errcode = frame->error_code;
+       asm ("mov %%cr2, %0": "=a" (address));
        kprint("A page fault occurred!\n", VGA_COLOR_DARK_RED);
-       if (errcode->p) {
-               kprint("Attempted to access non-present page\n", 0);
+       kprint("Faulting address: ", 0);
+       kprintd(address);
+       kprint("\n", 0);
+       if (!errcode.p) {
+               kprint("Address points to non-mapped 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) {
+       if (errcode.wr) {
+               kprint("Fault occurred while writing to memory\n", 0);
+       } else {
+               kprint("Fault occurred while reading from memory\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);
+       asm("cli");
 halt:
-       asm ("cli; hlt");
+       asm("hlt");
        goto halt;
 }
 
diff --git a/kernel/arch/x86/mm/paging.c b/kernel/arch/x86/mm/paging.c
deleted file mode 100644 (file)
index 9a4bc06..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#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 b274340cd2605ca7a905579cf06f0b32adbf8d99..060051c25782f3317f426f0ea44362e420a98b80 100644 (file)
@@ -11,36 +11,13 @@ 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("\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("\n", 0);
        kprint("Preparing IDT...\n", 0);
        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);
@@ -54,12 +31,5 @@ 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);
 }
index 82f6e4af44dc08723874e8fbe5e6983ec161c6a4..1a0107f226754fbc6597d075c5681746b1c94d9f 100644 (file)
@@ -3,16 +3,16 @@ OUTPUT_FORMAT(binary)
 
 SECTIONS
 {
-       . = 0x100000;
+       . = 0xc0000000;
        __KERNEL_BASE__ = .;
 
-       .text : ALIGN(4K) {
+       .text : AT(ADDR(.text) - 0xbf000000) ALIGN(4K) {
                __TEXT_BASE__ = .;
                kernel/entry.o (.text)
                *(.text)
                __TEXT_END__ = .;
        }
-       .rodata : ALIGN(4K) {
+       .rodata : AT(ADDR(.rodata) - 0xbf000000) ALIGN(4K) {
                __RODATA_BASE__ = .;
                *(.rodata)
                __RODATA_END__ = .;
@@ -27,12 +27,12 @@ SECTIONS
         * matter yet because we (currently) assume that the NX bit is not
         * supported anyway. */
 
-       .data : ALIGN(4K) {
+       .data : AT(ADDR(.data) - 0xbf000000) ALIGN(4K) {
                __DATA_BASE__ = .;
                *(.data)
                __DATA_END__ = .;
        }
-       .bss : ALIGN(4K) {
+       .bss : AT(ADDR(.bss) - 0xbf000000) ALIGN(4K) {
                __BSS_BASE__ = .;
                *(.bss)
                /* Reserving 16KiB for the stack. A __STACK_TOP__ is not really