# HG changeset patch # User windel # Date 1325183641 -3600 # Node ID 7e3bdcb391dcf82577f26f37025af2aeb64dafe0 # Parent 47b7df514243944ddf5cabb29cd506d35ef3accc Added get_page function to mm diff -r 47b7df514243 -r 7e3bdcb391dc cos/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/Makefile Thu Dec 29 19:34:01 2011 +0100 @@ -0,0 +1,9 @@ +# vim: set noexpandtab: + +all: bootdisk.img Makefile + +bootdisk.img: kernel/lcfos.bin grub/menu.lst Makefile + cp grub/emptybootdisk.img bootdisk.img + mcopy -D o -i bootdisk.img kernel/lcfos.bin :: + mcopy -D o -i bootdisk.img grub/menu.lst ::/grub + diff -r 47b7df514243 -r 7e3bdcb391dc cos/grub/menu.lst --- a/cos/grub/menu.lst Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/grub/menu.lst Thu Dec 29 19:34:01 2011 +0100 @@ -1,6 +1,6 @@ default 0 timeout 3 -title lcfosc +title lcfos root (fd0) -kernel /lcfosc.bin +kernel /lcfos.bin diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/Makefile --- a/cos/kernel/Makefile Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/Makefile Thu Dec 29 19:34:01 2011 +0100 @@ -1,11 +1,6 @@ # vim: set noexpandtab: -all: bootdisk.img Makefile - -bootdisk.img: lcfosc.bin grub/menu.lst Makefile - cp grub/emptybootdisk.img bootdisk.img - mcopy -D o -i bootdisk.img lcfosc.bin :: - mcopy -D o -i bootdisk.img grub/menu.lst ::/grub +all: lcfos.bin Makefile CRT0 = goto64.o @@ -15,13 +10,13 @@ OBJECTS = video.o snprintf.o kernel.o asmcode.o handlers.o keyboard.o \ klib.o malloc.o task.o mm.o timer.o -lcfosc.bin: $(CRT0) $(OBJECTS) link.ld - ld -T link.ld -s -o lcfosc.bin $(CRT0) $(OBJECTS) +lcfos.bin: $(CRT0) $(OBJECTS) link.ld + ld -T link.ld -s -o lcfos.bin $(CRT0) $(OBJECTS) -%.o : %.asm Makefile +%.o : %.asm nasm -f elf64 -o $@ $< -%.o : %.c Makefile +%.o : %.c gcc $(CFLAGS) -o $@ -c $< clean: diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/asmcode.asm --- a/cos/kernel/asmcode.asm Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/asmcode.asm Thu Dec 29 19:34:01 2011 +0100 @@ -11,11 +11,6 @@ pop rax jmp rax -global magicBochsBreak -magicBochsBreak: - xchg bx, bx - ret - global loadIDT loadIDT: extern idtP diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/handlers.c --- a/cos/kernel/handlers.c Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/handlers.c Thu Dec 29 19:34:01 2011 +0100 @@ -229,6 +229,8 @@ { uint64_t faulting_address; + printf("Segfault!\n"); + // Retrieve failed page from CR2: asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); @@ -298,7 +300,7 @@ void INTDEF_handler() { - printf("Default int handler called\n"); + panic("Default int handler called\n"); } diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/kernel.c --- a/cos/kernel/kernel.c Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/kernel.c Thu Dec 29 19:34:01 2011 +0100 @@ -1,6 +1,6 @@ #include "kernel.h" -void testMalloc() +static void testMalloc() { char *a, *b; @@ -17,11 +17,18 @@ // A test program that prints 'Hoi' to the screen: unsigned char hello_program[] = {0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x10, 0x48, 0xc7, 0x45, 0xf8, 0x0, 0x80, 0xb, 0x0, 0x48, 0x8b, 0x45, 0xf8, 0xc6, 0x0, 0x48, 0x48, 0x8b, 0x45, 0xf8, 0x48, 0x83, 0xc0, 0x2, 0xc6, 0x0, 0x6f, 0x48, 0x8b, 0x45, 0xf8, 0x48, 0x83, 0xc0, 0x4, 0xc6, 0x0, 0x69, 0xeb, 0xfe, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7a, 0x52, 0x0, 0x1, 0x78, 0x10, 0x1, 0x1b, 0xc, 0x7, 0x8, 0x90, 0x1, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0xb0, 0xff, 0xff, 0xff, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x41, 0xe, 0x10, 0x86, 0x2, 0x43, 0xd, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; +/* This routine initializes the kernel. + * We are left here in 64-bit long mode with the first 6 MB identity mapped. + * */ void kmain() { - init_screen(); - setupIDT(); - init_heap(); + init_screen(); + setupIDT(); + // init_heap(); + + // Assume first 16MB: + // TODO: get size from grub + init_memory(0x1000000); //new_task(hello_program); @@ -49,11 +56,16 @@ printf(" x: print system time in ms\n"); printf(" r: reboot\n"); printf(" t: test\n"); + printf(" b: break\n"); } if (strncmp(buffer, "r", 1)) { reboot(); } + if (strncmp(buffer, "b", 1)) + { + magicBochsBreak(); + } } } diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/kernel.h --- a/cos/kernel/kernel.h Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/kernel.h Thu Dec 29 19:34:01 2011 +0100 @@ -4,6 +4,8 @@ // Include common functions, available to all! #define NULL ((void*)0) +/* Types */ + // Type defs: typedef unsigned char uint8_t; typedef unsigned short uint16_t; @@ -26,75 +28,6 @@ uint64_t base; } __attribute__((packed)) idtPointer; -// memory alloc functions: -void init_heap(); -void* kmalloc(uint64_t size); -void kfree(void* ptr); - -void* kmalloc_int(uint64_t size); - -// task related functions: -void initialize_tasking(); -void new_task(); -void task_scheduler(); - -// STDout funcs: -void printf(const char* fmt, ... ); -void memset(void* ptr, uint8_t value, uint64_t num); -void memcpy(void* dst, void* src, uint64_t num); -int strncmp(const char* s1, const char* s2, int size); - -// Screen related: -void clear_screen(); -void init_screen(); -void print_string(const char *); -void set_cursor(int newrow, int newcol); -void get_cursor(int *therow, int *thecol); -void set_color(int forecolor, int backcolor); - -// For IO ports: -uint8_t inb(uint16_t); -uint16_t inw(uint16_t); -void outb(uint16_t, uint8_t); - -// Interrupt functions: -void setupIDT(void); -void PICremap(void); - -// ASM helper: -void loadIDT(void); -uint64_t read_rip(); - -// Panic exit: -void halt(void); -void panic(char *msg); -void reboot(void); - -// Bochs xchg bx,bx breakpoint: -void magicBochsBreak(); - -// Assembler util functions: -void doCPUID(int eax, int *ebx, int *ecx, int *edx); - -// Keyboard driver: -void keyboardDriverUpdate(unsigned char scancode); -void getline(char *buffer, int len); - -// Timer: -void timerDriverUpdate(void); -uint64_t getTimeMS(); - -// Memory functions: -void mappage(uint64_t address); - -void loadPageTable(void* tableAddress); - -// Variable argument list things: -#define va_start(v,l) __builtin_va_start(v,l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v,l) __builtin_va_arg(v,l) -typedef __builtin_va_list va_list; - // Multiboot structs: struct multiboot_aout_symbol_table { uint32_t tabsize; @@ -124,6 +57,108 @@ uint32_t type; }; +// Memory manager structures: +typedef struct +{ + uint64_t present : 1; + uint64_t rw : 1; + uint64_t us : 1; // user or supervisor + uint64_t pwt : 1; // page level write-through + uint64_t pcd : 1; // page cache disable + uint64_t accessed : 1; + uint64_t ignored : 1; + uint64_t ps : 1; // must be 0. + uint64_t ignored2 : 4; + // 12 bits so far + uint64_t address : 48; // address of page directory pointer table. + uint64_t ignored3 : 11; + uint64_t xd : 1; // execute disable +} PML4E_t; // 64 bits wide, PML4 table must be 4096 byte aligned. + +typedef struct +{ + // Must be 12 bits aligned! + PML4E_t table[512]; + uint64_t physicalAddress; // Physical address of the table above +} PML4_t; + +typedef struct +{ + uint64_t present : 1; + uint64_t rw : 1; + uint64_t us : 1; // user or supervisor + uint64_t pwt : 1; // page level write-through + uint64_t pcd : 1; // page cache disable + uint64_t accessed : 1; + uint64_t ignored : 1; + uint64_t ps : 1; // page size, must be 0, otherwise maps a 1 GB page. + uint64_t ignored2 : 4; + // 12 bits so far + uint64_t address : 48; // address of page directory table. + uint64_t ignored3 : 11; + uint64_t xd : 1; // execute disable +} PDPTE_t; // Page directory pointer table entry, 64 bits wide. 4-kB aligned. + +// Page directory pointer table: +typedef struct +{ + PDPTE_t table[512]; + uint64_t physicalAddress; +} PDPT_t; + +typedef struct +{ + uint64_t present : 1; + uint64_t rw : 1; + uint64_t us : 1; // user or supervisor + uint64_t pwt : 1; + uint64_t pcd : 1; // page cache disable + uint64_t accessed : 1; + uint64_t ignored : 1; + uint64_t ps : 1; // page size, must be 0, otherwise maps a 2-MB page. + uint64_t ignored2 : 4; + // 12 bits so far + uint64_t address : 48; // address of page table. + uint64_t ignored3 : 11; + uint64_t xd : 1; // execute disable +} PDE_t; + +// Page directory: +typedef struct +{ + PDE_t table[512]; + uint64_t physicalAddress; +} PD_t; + +typedef struct +{ + uint64_t present : 1; + uint64_t rw : 1; + uint64_t us : 1; // user or supervisor + uint64_t pwt : 1; + uint64_t pcd : 1; // page cache disable + uint64_t accessed : 1; + uint64_t dirty : 1; + uint64_t pat : 1; // memory type? + uint64_t g : 1; // Global? + uint64_t ignored : 3; + + uint64_t address : 48; + uint64_t ignored2 : 11; + uint64_t xd : 1; +} page_t; + +// Page table: +typedef struct +{ + page_t table[512]; + uint64_t physicalAddress; +} PT_t; + +// Make memmap a PML4 type: +typedef PML4_t memmap_t; + +// Task related types: typedef struct { char name[32]; // Name of the console @@ -135,6 +170,7 @@ uint32_t kstack; uint32_t ustack; + // For task switching: uint64_t cr3; uint64_t rip; uint64_t rsp; @@ -153,12 +189,78 @@ console_t *console; } task_t; -// Memory manager functions: -typedef struct -{ - // TODO: other members here. - uint64_t frame; -} page_t; +// Variable argument list things: +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +typedef __builtin_va_list va_list; + +/* Global variables */ +extern uint64_t kernel_end; +extern uint64_t placement_address; + +/* Procedures */ + +// memory functions: +// TODO: remove some redundant API functions: +void init_heap(); +void init_memory(uint64_t total_mem_size); +page_t* get_page(uint64_t address, memmap_t*); +void* kmalloc(uint64_t size); +void kfree(void* ptr); +void* kmalloc_int(uint64_t size); +void* kmalloc_aligned_int(uint64_t size); +void mappage(uint64_t address); +void loadPageTable(void* tableAddress); +void switch_mapping(memmap_t* mapping); +void enablePaging(); + +// task related functions: +void initialize_tasking(); +void new_task(); +void task_scheduler(); + +// STDout funcs: +void printf(const char* fmt, ... ); +void memset(void* ptr, uint8_t value, uint64_t num); +void memcpy(void* dst, void* src, uint64_t num); +int strncmp(const char* s1, const char* s2, int size); + +// Screen related: +void clear_screen(); +void init_screen(); +void print_string(const char *); +void set_cursor(int newrow, int newcol); +void get_cursor(int *therow, int *thecol); +void set_color(int forecolor, int backcolor); + +// For IO ports: +uint8_t inb(uint16_t); +uint16_t inw(uint16_t); +void outb(uint16_t, uint8_t); + +// Interrupt functions: +void setupIDT(void); +void PICremap(void); +void loadIDT(void); + +// ASM helper: +uint64_t read_rip(); + +// Helpers: +void halt(void); +void panic(char *msg); +void reboot(void); +void magicBochsBreak(); +void doCPUID(int eax, int *ebx, int *ecx, int *edx); + +// Keyboard driver: +void keyboardDriverUpdate(unsigned char scancode); +void getline(char *buffer, int len); + +// Timer: +void timerDriverUpdate(void); +uint64_t getTimeMS(); #endif diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/klib.c --- a/cos/kernel/klib.c Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/klib.c Thu Dec 29 19:34:01 2011 +0100 @@ -1,5 +1,10 @@ #include "kernel.h" +void magicBochsBreak() +{ + asm volatile("xchg %bx, %bx"); +} + void panic(char *msg) { printf("Kernel panic: "); diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/link.ld --- a/cos/kernel/link.ld Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/link.ld Thu Dec 29 19:34:01 2011 +0100 @@ -20,6 +20,6 @@ *(.bss) } - end = .; + kernel_end = .; } diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/malloc.c --- a/cos/kernel/malloc.c Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/malloc.c Thu Dec 29 19:34:01 2011 +0100 @@ -1,8 +1,9 @@ #include "kernel.h" // ================= Placement malloc: -extern uint64_t end; -uint64_t placement_address = (uint64_t)&end; +// Assume here that nothing gets ever kfree'd. This makes it simple! + +uint64_t placement_address = (uint64_t)&kernel_end; void* kmalloc_int(uint64_t size) { @@ -52,6 +53,8 @@ void* kmalloc(uint64_t size) { + return kmalloc_int(size); + // Start at the beginning of our heap and search a free block: heap_t *current = kernel_heap; while (current->magic == HEAP_MAGIC) diff -r 47b7df514243 -r 7e3bdcb391dc cos/kernel/mm.c --- a/cos/kernel/mm.c Wed Dec 28 13:38:43 2011 +0100 +++ b/cos/kernel/mm.c Thu Dec 29 19:34:01 2011 +0100 @@ -1,4 +1,3 @@ - /* Memory manager functions, * * Uses a bitmap to keep track of 4k pages that are in use. @@ -7,17 +6,20 @@ #include "kernel.h" -uint64_t *frames = 0; -uint64_t nframes = 0; +static uint64_t *frames = 0; +static uint64_t nframes = 0; -void set_frame(uint64_t frame) +memmap_t* kernel_map = 0; // kernel memory mapping +memmap_t* current_map = 0; // The currently active memory mapping + +static void set_frame(uint64_t frame) { uint64_t idx = frame / 64; uint64_t off = frame % 64; frames[idx] |= (0x1 << off); } -void clear_frame(uint64_t frame) +static void clear_frame(uint64_t frame) { uint64_t idx = frame / 64; uint64_t off = frame % 64; @@ -31,7 +33,7 @@ return (frames[idx] & (0x1 << off)); } -uint64_t first_frame() +static uint64_t first_frame() { uint64_t i, j; for (i = 0; i < nframes / 64; i++) @@ -48,28 +50,161 @@ } } } - return 0xFFFFFFFFFFFFFFFF; + + // No frame found: + return (uint64_t) -1; } // Memory manager functions: void init_memory(uint64_t total_mem_size) { - frames = (uint64_t*)kmalloc_int( ( total_mem_size / 4096 ) / 8 ); + // Allocate and clear bits to remember which 4kb-frames are in use: + nframes = (total_mem_size / 0x1000); + frames = (uint64_t*)kmalloc_int( (nframes / 64) * sizeof(uint64_t) ); + memset(frames, 0, (nframes / 64) * sizeof(uint64_t)); + + // Create kernel map: + kernel_map = (memmap_t*)kmalloc_aligned_int(sizeof(memmap_t)); + memset(kernel_map, 0, sizeof(memmap_t)); + + // Identity map lower memory and mark as used by the kernel. + // Mark as used by the kernel: + uint64_t i; + i = 0; + while ( i <= placement_address) + { + page_t *page; + + page = get_page(i, kernel_map); // Get page for address + page->address = i >> 12; // Set the address of this page. + page->present = 1; + page->rw = 1; + page->us = 1; // Make all things accessable for users for now. + + set_frame(i / 0x1000); + + i += 0x1000; // Increase a 4 k frame + } + + // Set the created mapping as active: + // switch_mapping(kernel_map); + // TODO: debug crash after enable of new memory map + // TODO: set the use of placement malloc to invalid after here. } -void alloc_frame() +void alloc_frame(page_t *page) { + if (page->address != 0) + { + return; + } uint64_t idx = first_frame(); if (idx == (uint64_t) -1) { panic("No more memory!"); } set_frame(idx); + + page->present = 1; + page->rw = 1; + page->us = 0; + page->address = idx; // set address in frame number, the byte address is 0x1000 times this value. } void free_frame(page_t *page) { - clear_frame(page->frame / 0x1000); - page->frame = 0; + clear_frame(page->address / 0x1000); + page->address = 0; + page->present = 0; +} + +void switch_mapping(memmap_t* mapping) +{ + current_map = mapping; + printf("Switching to use of other at %x\n", &mapping->table); + + asm volatile("mov %0, %%cr3" :: "r"(&mapping->table)); + + // Enable paging (and flush cache): + uint64_t cr0; + asm volatile("mov %%cr0, %0": "=r"(cr0)); + cr0 |= 0x80000000; + asm volatile("mov %0, %%cr0":: "r"(cr0)); } +/* Get a page for a virtual address, and create other tables if required */ +page_t* get_page(uint64_t address, memmap_t *mapping) +{ + // Retrieve the correct PDP (page dir pointer table): + uint64_t pml4index = (address >> 39) & 0x1FF; + PDPT_t *pdpt = 0; + if (mapping->table[pml4index].present == 1) + { + pdpt = (PDPT_t*)((uint64_t)mapping->table[pml4index].address << 12); + } + else + { + // Create new table: + pdpt = (PDPT_t*)kmalloc_aligned_int(sizeof(PDPT_t)); + printf("Creating PDPT %x\n", pdpt); + memset(pdpt, 0, sizeof(PDPT_t)); + + // TODO: get function like virt2phys or something here + uint64_t address = (uint64_t)pdpt; // get the physical address + mapping->table[pml4index].address = address >> 12; // shift right + mapping->table[pml4index].rw = 1; + mapping->table[pml4index].us = 1; + mapping->table[pml4index].present = 1; + } + + uint64_t pdptindex = (address >> 30) & 0x1FF; + // Retrieve the correct page directory: + PD_t *pd = 0; + if (pdpt->table[pdptindex].present == 1) + { + pd = (PD_t*)((uint64_t)pdpt->table[pdptindex].address << 12); + } + else + { + printf("Creating PD\n"); + // Create a new table: + pd = (PD_t*)kmalloc_aligned_int(sizeof(PD_t)); + memset(pd, 0, sizeof(PD_t)); + + // Enter table into PDPT: + // TODO: make virt2phys function: + uint64_t address = (uint64_t)pd; + pdpt->table[pdptindex].address = address >> 12; + pdpt->table[pdptindex].rw = 1; + pdpt->table[pdptindex].us = 1; + pdpt->table[pdptindex].present = 1; + } + + // Retrieve the correct page table: + uint64_t pdindex = (address >> 21) & 0x1FF; + PT_t *pt = 0; + if (pd->table[pdindex].present == 1) + { + pt = (PT_t*)((uint64_t)pd->table[pdindex].address << 12); + } + else + { + printf("Creating PT\n"); + // Create table: + pt = (PT_t*)kmalloc_aligned_int(sizeof(PD_t)); + memset(pt, 0, sizeof(PT_t)); + + // Enter PT into PD: + uint64_t address = (uint64_t)pt; + pd->table[pdindex].address = address >> 12; + pd->table[pdindex].rw = 1; + pd->table[pdindex].us = 1; + pd->table[pdindex].present = 1; + } + + // Finally get the page from the directory: + // TODO: convert from physical address to virtual address: + uint64_t ptindex = (address >> 12) & 0x1FF; + return &pt->table[ptindex]; +} +