From 2dc45e8cac33313e847f6097cbe2ba3bb3ceab2a Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 28 Feb 2015 20:42:57 -0500 Subject: Implement paging --- OBJ | 1 + bochs.cfg | 2 +- drivers/gfx.c | 2 ++ 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 +++++++++++++++++++++++++++++++++++++++++++++++++ libc/include/stdlib.h | 4 +++ libc/stdlib.c | 7 ++++++ 11 files changed, 144 insertions(+), 1 deletion(-) 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 diff --git a/OBJ b/OBJ index 1bc9ae6..2d81e14 100644 --- a/OBJ +++ b/OBJ @@ -18,6 +18,7 @@ drivers/tty.o kernel/fpu.o kernel/gdt-as.o kernel/gdt.o +kernel/heap.o kernel/idt-as.o kernel/idt.o kernel/io.o diff --git a/bochs.cfg b/bochs.cfg index e22e703..dd579e2 100644 --- a/bochs.cfg +++ b/bochs.cfg @@ -26,7 +26,7 @@ cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, f cpuid: tbm=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, smep=0, smap=0, mwait=1 print_timestamps: enabled=0 debugger_log: - -magic_break: enabled=0 +magic_break: enabled=1 port_e9_hack: enabled=1 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 diff --git a/drivers/gfx.c b/drivers/gfx.c index 028a5e5..3417fda 100644 --- a/drivers/gfx.c +++ b/drivers/gfx.c @@ -541,5 +541,7 @@ bool gfx_init(struct vbe_info_t *vbe_mode_info) gfx_reset(); } + printf("Real FB addr: 0x%x\n", (uint32_t)real_framebuffer); + return true; } 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); +} diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 49116df..ffe9073 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -2,6 +2,7 @@ #define _STDLIB_H_ #include +#include /* this is by no means standards-compliant... but who cares? :P */ @@ -18,5 +19,8 @@ void srand(unsigned int); int abs(int); void *malloc(size_t); int snprintf(char*, int, const char*, ...); +void assert_fail(const char*, const char*, int); + +#define assert(x) if(!(x))assert_fail(__func__, __FILE__, __LINE__); #endif diff --git a/libc/stdlib.c b/libc/stdlib.c index c6a9c3d..bb30039 100644 --- a/libc/stdlib.c +++ b/libc/stdlib.c @@ -2,6 +2,7 @@ #include #include #include +#include "panic.h" /* adapted from */ char* itoa(int val, int base) @@ -150,3 +151,9 @@ int snprintf(char *buf, int sz, const char *fmt, ...) va_end(ap); return 0; } + +void assert_fail(const char *func, const char *file, int line) +{ + printf("\nAssertion failed in function %s in file %s, line %d\n", func, file, line); + panic("assertion failed!\n"); +} -- cgit v1.1