From 2dc45e8cac33313e847f6097cbe2ba3bb3ceab2a Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 28 Feb 2015 20:42:57 -0500 Subject: Implement paging --- kernel/heap.c | 45 ++++++++++++++++++++++++++++++++++ kernel/include/paging.h | 8 ++++++ kernel/linker.ld | 1 + kernel/main.c | 1 + kernel/paging-as.S | 9 +++++++ kernel/paging.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 129 insertions(+) create mode 100644 kernel/heap.c create mode 100644 kernel/include/paging.h create mode 100644 kernel/paging-as.S create mode 100644 kernel/paging.c (limited to 'kernel') diff --git a/kernel/heap.c b/kernel/heap.c new file mode 100644 index 0000000..d1f1021 --- /dev/null +++ b/kernel/heap.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include "paging.h" + +/* a simple pointer-arithmetic-based malloc */ + +/* a symbol put there by the linker */ +extern uint32_t link_mem_end; +uint32_t kmalloc_addr = &link_mem_end; + +static void *kmalloc_int(size_t sz, int align, void **phys) +{ + if(align) + { + kmalloc_addr += (PAGE_SIZE - 1); + kmalloc_addr &= PAGE_MASK; + } + if(phys) + *phys = (void*)kmalloc_addr; + void *ret = (void*)kmalloc_addr; + kmalloc_addr += sz; + assert(((uint32_t)ret & 0xFFF) == 0); + return ret; +} + +void *kmalloc(size_t sz) +{ + return kmalloc_int(sz, 0, NULL); +} + +void *kmalloc_a(size_t sz) +{ + return kmalloc_int(sz, 1, NULL); +} + +void *kmalloc_p(size_t sz, void **phys) +{ + return kmalloc_int(sz, 0, phys); +} + +void *kmalloc_ap(size_t sz, void **phys) +{ + return kmalloc_int(sz, 1, phys); +} diff --git a/kernel/include/paging.h b/kernel/include/paging.h new file mode 100644 index 0000000..0481069 --- /dev/null +++ b/kernel/include/paging.h @@ -0,0 +1,8 @@ +#define PAGE_PRESENT (1<<0) +#define PAGE_RW (1<<1) +#define PAGE_USER (1<<2) + +#define PAGE_MASK 0xFFFFF000 +#define PAGE_SIZE 0x1000 + +void paging_init(void); diff --git a/kernel/linker.ld b/kernel/linker.ld index 9b47325..c032991 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -41,4 +41,5 @@ SECTIONS /* The compiler may produce other sections, by default it will put them in a segment with the same name. Simply add stuff here as needed. */ + link_mem_end = .; } diff --git a/kernel/main.c b/kernel/main.c index 04ef369..005ac1d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -61,6 +61,7 @@ void main(struct multiboot_info_t *hdr, uint32_t magic) printf("GFX init\n"); bool gfx_status = gfx_init((struct vbe_info_t*)hdr->vbe_mode_info); + //bool gfx_status = false; printf("GFX init done.\n"); /* if graphical initialization fails, fall back to text mode */ diff --git a/kernel/paging-as.S b/kernel/paging-as.S new file mode 100644 index 0000000..cafaab4 --- /dev/null +++ b/kernel/paging-as.S @@ -0,0 +1,9 @@ + .global do_paging_enable +do_paging_enable: + movl 4(%esp), %eax # loads page directory address + mov %eax, %cr3 + mov %cr0, %eax + orl $0x80000000, %eax # set PG bit + sti + mov %eax, %cr0 + ret diff --git a/kernel/paging.c b/kernel/paging.c new file mode 100644 index 0000000..408ced8 --- /dev/null +++ b/kernel/paging.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include "frame.h" +#include "heap.h" +#include "isr.h" +#include "paging.h" +#include "panic.h" + +uint32_t *current_directory; + +static void page_fault(struct regs_t *regs) +{ + volatile uint32_t fault_addr; + asm("mov %%cr2, %0" : "=r"(fault_addr)); + printf("=== Page Fault ===\n"); + printf("Faulting address: 0x%x\n", fault_addr); + /* dump the regs */ + printf("EAX: 0x%x EBX: 0x%x\n", regs->eax, regs->ebx); + printf("ECX: 0x%x EDX: 0x%x\n", regs->ecx, regs->edx); + printf("ESP: 0x%x EBP: 0x%x\n", regs->esp, regs->ebp); + printf("ESI: 0x%x EDI: 0x%x\n", regs->esi, regs->edi); + printf("EIP: 0x%x\n", regs->eip); + panic("Page fault!\n"); +} + + void paging_switch_directory(uint32_t *dir) +{ + current_directory = dir; + extern void do_paging_enable(uint32_t); + do_paging_enable((uint32_t)current_directory); +} + +static uint32_t *identity_map_table(uint32_t start, int flags) +{ + /* make a page table */ + uint32_t *table = kmalloc_a(0x1000); + /* identity map 4MB */ + for(uint32_t i = start; i < start + 1024; ++i) + { + table[i - start] = (i * PAGE_SIZE) | flags; + } + return table; +} + +void paging_init(void) +{ + uint32_t *kernel_directory = kmalloc_a(0x1000); + memset(kernel_directory, 0, 0x1000); + /* blank the kernel directory */ + for(int i = 0; i < 1024; ++i) + { + kernel_directory[i] = PAGE_RW; + } + + /* identity map all 4GB */ + for(int i=0; i < 1024; ++i) + kernel_directory[i] = (uint32_t)identity_map_table(i * 1024, PAGE_PRESENT | PAGE_RW) | + PAGE_PRESENT | PAGE_RW; + + set_interrupt_handler(14, page_fault); + + paging_switch_directory(kernel_directory); +} -- cgit v1.1