Mercurial > lcfOS
changeset 40:24ce177e01e8
Added more malloc stuff. Added mem usage
author | windel |
---|---|
date | Tue, 24 Jan 2012 17:54:16 +0100 |
parents | 5c20bd53cccd |
children | 35cc54e078dd |
files | cos/kernel/handlers.c cos/kernel/kernel.h cos/kernel/malloc.c cos/kernel/mm.c cos/kernel/shell.c |
diffstat | 5 files changed, 218 insertions(+), 145 deletions(-) [+] |
line wrap: on
line diff
--- a/cos/kernel/handlers.c Mon Jan 16 21:38:55 2012 +0100 +++ b/cos/kernel/handlers.c Tue Jan 24 17:54:16 2012 +0100 @@ -1,43 +1,43 @@ #include "kernel.h" // Assembler wrapper prototypes: -void INT255(void); -void INT0(void); -void INT1(void); -void INT2(void); -void INT3(void); -void INT4(void); -void INT5(void); -void INT6(void); -void INT7(void); -void INT8(void); -void INT9(void); -void INT10(void); -void INT11(void); -void INT12(void); -void INT13(void); -void INT14(void); -void INT16(void); -void INT17(void); -void INT18(void); -void INT19(void); +extern void INT255(void); +extern void INT0(void); +extern void INT1(void); +extern void INT2(void); +extern void INT3(void); +extern void INT4(void); +extern void INT5(void); +extern void INT6(void); +extern void INT7(void); +extern void INT8(void); +extern void INT9(void); +extern void INT10(void); +extern void INT11(void); +extern void INT12(void); +extern void INT13(void); +extern void INT14(void); +extern void INT16(void); +extern void INT17(void); +extern void INT18(void); +extern void INT19(void); // Remapped irq assembler wrappers: -void INT32(void); -void INT33(void); -void INT34(void); -void INT35(void); -void INT36(void); -void INT37(void); -void INT38(void); -void INT39(void); -void INT40(void); -void INT41(void); -void INT42(void); -void INT43(void); -void INT44(void); -void INT45(void); -void INT46(void); -void INT47(void); +extern void INT32(void); +extern void INT33(void); +extern void INT34(void); +extern void INT35(void); +extern void INT36(void); +extern void INT37(void); +extern void INT38(void); +extern void INT39(void); +extern void INT40(void); +extern void INT41(void); +extern void INT42(void); +extern void INT43(void); +extern void INT44(void); +extern void INT45(void); +extern void INT46(void); +extern void INT47(void); // THE interrupt descriptor table: IDT_entry *idt = (IDT_entry*)0x5000; @@ -184,8 +184,8 @@ panic("No resolution to page fault!"); } + // Global isr handler: - // Hopefully, this function get called with the correct registers. void isr_handler(uint64_t* registers) { @@ -223,30 +223,3 @@ outb(0x20, 0x20); // EOI to master } -// Interrupt service routines: - -void INT14handler() -{ - uint64_t faulting_address; - - printf("Segfault!\n"); - - // Retrieve failed page from CR2: - asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); - - printf("INT14 called! Page fault for address 0x%X!\n", faulting_address); - - panic("Unhandled exception!"); -} - -void INT15handler() -{ - printf("INT15 called!\n"); - panic("Unhandled exception!"); -} - -void INTDEF_handler() -{ - panic("Default int handler called\n"); -} -
--- a/cos/kernel/kernel.h Mon Jan 16 21:38:55 2012 +0100 +++ b/cos/kernel/kernel.h Tue Jan 24 17:54:16 2012 +0100 @@ -147,7 +147,6 @@ uint64_t physicalAddress; } PD_t; - typedef struct { unsigned present : 1; @@ -181,6 +180,20 @@ // Make memmap a PML4 type: typedef PML4_t memmap_t; +// Malloc related functions +typedef struct { + uint64_t magic; + uint64_t state; + uint64_t size; +} heap_header_t; + +typedef struct +{ + heap_header_t *first_block; + uint64_t start_address; + uint64_t end_address; +} heap_t; + // Task related types: typedef struct { @@ -263,23 +276,25 @@ /* Global variables */ extern uint64_t kernel_end; extern uint64_t placement_address; +extern memmap_t* kernel_map; /* 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 alloc_frame(page_t *page); void loadPageTable(void* tableAddress); void switch_mapping(memmap_t* mapping); void enablePaging(); +// Malloc related: +void* kmalloc(uint64_t size); +void* kmalloc_a(uint64_t size); // Aligned on a 4 KiB page. +void kfree(void* ptr); +heap_t* create_heap(uint64_t location, uint64_t size); + // task related functions: void initialize_tasking(); void new_task();
--- a/cos/kernel/malloc.c Mon Jan 16 21:38:55 2012 +0100 +++ b/cos/kernel/malloc.c Tue Jan 24 17:54:16 2012 +0100 @@ -5,104 +5,153 @@ uint64_t placement_address = (uint64_t)&kernel_end; -void* kmalloc_int(uint64_t size) -{ - uint64_t tmp = placement_address; - placement_address += size; - return (void*)tmp; -} - -void* kmalloc_aligned_int(uint64_t size) -{ - if ( (placement_address | 0xFFF) != 0 ) - { - placement_address &= ~(0xFFF); - placement_address += 0x1000; - } - uint64_t tmp = placement_address; - placement_address += size; - return (void*)tmp; -} - - // ================= Other malloc // TODO: move this to user space? #define HEAP_MAGIC 0xc0ffee -#define HEAP_START 0x400000 -#define HEAP_SIZE 0x200000 #define HEAP_INUSE 1 #define HEAP_FREE 0 -typedef struct { - uint64_t magic; - uint64_t state; - uint64_t size; -} heap_t; - /* malloc and free divide the chunks of memory present at the heap of the kernel into smaller parts. The heap is located at: 0x */ -static heap_t* kernel_heap = (heap_t*) 0x400000; // 4 MB - 6 MB is heap +static heap_t* kernel_heap = 0; + +void expand_heap(heap_t *heap, uint64_t newsize); + /* Allocates 'size' bytes and returns the pointer if succesfull. + Before the kernel is initialized, placement malloc is used. Kernelpanic in case of failure.. */ - -void* kmalloc(uint64_t size) +static void* kmalloc_int(uint64_t size, uint64_t aligned) { - 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) + // Check if there exists a kernel heap. If not, use placement malloc for now. + if (kernel_heap == 0) { - if ((current->state == HEAP_FREE) && (current->size >= size)) + // Before that the heap is initialized, use placement malloc + if (aligned == 1) { - // Mark block as used: - current->state = HEAP_INUSE; + // Align placement address + if ( (placement_address | 0xFFF) != 0 ) + { + placement_address &= ~(0xFFF); + placement_address += 0x1000; + } + } + uint64_t tmp = placement_address; + placement_address += size; + return (void*)tmp; + } + else + { + // We have a kernel heap, search the heap for a block of suitable size. - // Insert a heap header if required: - if (current->size > size + sizeof(heap_t) + 1) + // Start at the beginning of our heap and search a free block: + heap_header_t *current = kernel_heap->first_block; + while (current->magic == HEAP_MAGIC) + { + if ((current->state == HEAP_FREE) && (current->size >= size)) { - // Calculate location of the inserted header: - heap_t *newheader = (heap_t*) (((char*)current)+size+sizeof(heap_t)); + // We found a hole with suitable size. Determine if split is of any use. + + // Insert a heap header if required: + if (current->size > size + sizeof(heap_t) + 1) + { + // Calculate location of the inserted header: + heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t)); - // Set the new header fields: - newheader->size = current->size - size - sizeof(heap_t); - newheader->state = HEAP_FREE; - newheader->magic = HEAP_MAGIC; + // Set the new header fields: + newheader->size = current->size - size - sizeof(heap_header_t); + newheader->state = HEAP_FREE; + newheader->magic = HEAP_MAGIC; - // Set the size of this block - current->size = size; + // Set the size of this block + current->size = size; + } + else + { + // We allocate this whole block + // Mark block as used: + current->state = HEAP_INUSE; + } + // Calculate the size of the block: + char *address = ((char*)current)+sizeof(heap_header_t); + return address; + } - else - { - // We allocate this whole block - } - // Calculate the size of the block: - char *address = ((char*)current)+sizeof(heap_t); - return address; - + // Goto next heap block: + current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t)); } - // Goto next heap block: - current = (heap_t*)(((char*) current) + current->size + sizeof(heap_t)); + + // We did not find a block large enough. Expand the heap and try again. + expand_heap(kernel_heap, 0x10000000); + return kmalloc_int(size, aligned); } - return 0x0; +} + +// Convenient wrappers: +void* kmalloc(uint64_t size) +{ + return kmalloc_int(size, 0); +} + +void* kmalloc_a(uint64_t size) +{ + return kmalloc_int(size, 1); } void kfree(void* ptr) { - printf("Free address %x\n", ptr); + printf("Free address %x\n", ptr); + if (kernel_heap == 0) + { + return; + } + else + { + // TODO + } + // TODO: free blocks: } -void init_heap(void) +heap_t* create_heap(uint64_t location, uint64_t size) { - // Initialize the kernel heap: - kernel_heap->magic = HEAP_MAGIC; - kernel_heap->state = HEAP_FREE; - kernel_heap->size = HEAP_SIZE - sizeof(heap_t); + // Make sure that the new heap location is mapped into the address space: + uint64_t i = 0; + while (i < size) + { + alloc_frame( get_page(location + i, kernel_map)); + i += 0x1000; + } + + // create new heap structure: + heap_t* h = (heap_t*)kmalloc(sizeof(heap_t)); + + // Create one big hole: + h->first_block = (heap_header_t*)location; // Place header at beginning of heap + h->first_block->magic = HEAP_MAGIC; + h->first_block->state = HEAP_FREE; + h->first_block->size = size - sizeof(heap_header_t); + return h; } +// Make the total heap bigger: +void expand_heap(heap_t *heap, uint64_t newsize) +{ + uint64_t oldsize = heap->end_address - heap->start_address; + if (newsize < oldsize) + { + panic("Cannot expand heap to a smaller size\n"); + } + + uint64_t i = oldsize; + while (i < newsize) + { + alloc_frame( get_page(heap->start_address + i, kernel_map)); + i += 0x1000; + } +} +
--- a/cos/kernel/mm.c Mon Jan 16 21:38:55 2012 +0100 +++ b/cos/kernel/mm.c Tue Jan 24 17:54:16 2012 +0100 @@ -6,13 +6,19 @@ #include "kernel.h" +#define HEAP_START 0xC000000000000000 +#define HEAP_INITIAL_SIZE 0x100000 + // Bitmap that keeps track of all the 4 kB memory pages in the system: static uint64_t *frames = 0; static uint64_t nframes = 0; memmap_t* kernel_map = 0; // kernel memory mapping +// TODO: determine if this is required. memmap_t* current_map = 0; // The currently active memory mapping +heap_t* kernel_heap = 0; + static void set_frame(uint64_t frame) { uint64_t idx = frame / 64; @@ -56,6 +62,24 @@ return (uint64_t) -1; } +void memory_status(void) +{ + // Determine amount of used memory. + uint64_t i, j; + uint64_t inuse = 0; + for (i = 0; i < nframes / 64; i++) + { + for (j = 0; j < 64; j++) + { + if ((frames[i] & (1UL<<j)) == (1UL<<j)) + { + inuse++; + } + } + } + printf("Memory: %d, in use: %d\n", nframes/0x100, inuse/0x100); +} + /* * Initializes the memory manager, allocating a bitmap once. */ @@ -63,22 +87,27 @@ { printf("Running with %d MB ram\n", total_mem_size / 1000000); + // Memory size is from address 0x100000 + total_mem_size += 0x100000; + // Only here placement malloc is used! // // Allocate and clear bits to remember which 4KiB-frames are in use: - nframes = (total_mem_size / 0x1000); // Calculate number of frames - frames = (uint64_t*)kmalloc_int( (nframes / 64) * sizeof(uint64_t) ); - memset(frames, 0, (nframes / 64) * sizeof(uint64_t)); + // Calculate number of frames. memory size is indicated from address 0x100000 + nframes = (total_mem_size) / 0x1000; // Calculate number of frames + int numbytes = ((nframes / 64) + 1) * sizeof(uint64_t); + frames = (uint64_t*)kmalloc(numbytes); + memset(frames, 0, numbytes); // Create kernel map: - kernel_map = (memmap_t*)kmalloc_aligned_int(sizeof(memmap_t)); + kernel_map = (memmap_t*)kmalloc_a(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) + while ( i <= placement_address + 0x100000) { page_t *page; @@ -98,6 +127,7 @@ switch_mapping(kernel_map); // TODO: set the use of placement malloc to invalid after here. + // kernel_heap = create_heap(HEAP_START, HEAP_INITIAL_SIZE); } void alloc_frame(page_t *page) @@ -130,6 +160,7 @@ { current_map = mapping; + // Load table address: asm volatile("mov %0, %%cr3" :: "r"(&mapping->table)); // Enable paging (and flush cache): @@ -152,7 +183,9 @@ else { // Create new table: - pdpt = (PDPT_t*)kmalloc_aligned_int(sizeof(PDPT_t)); + printf("Get page for address %x\n", address); + // TODO: make sure that this function calls kmalloc instead of placement malloc. + pdpt = (PDPT_t*)kmalloc_a(sizeof(PDPT_t)); memset(pdpt, 0, sizeof(PDPT_t)); // TODO: get function like virt2phys or something here @@ -173,7 +206,7 @@ else { // Create a new table: - pd = (PD_t*)kmalloc_aligned_int(sizeof(PD_t)); + pd = (PD_t*)kmalloc_a(sizeof(PD_t)); memset(pd, 0, sizeof(PD_t)); // Enter table into PDPT: @@ -195,7 +228,7 @@ else { // Create table: - pt = (PT_t*)kmalloc_aligned_int(sizeof(PD_t)); + pt = (PT_t*)kmalloc_a(sizeof(PD_t)); memset(pt, 0, sizeof(PT_t)); // Enter PT into PD:
--- a/cos/kernel/shell.c Mon Jan 16 21:38:55 2012 +0100 +++ b/cos/kernel/shell.c Tue Jan 24 17:54:16 2012 +0100 @@ -17,6 +17,8 @@ kfree(a); } +void memory_status(void); + void shell() { printf("Welcome!\n"); @@ -30,6 +32,7 @@ if (buffer[0] == 'x') { printf("System time in ms: %d\n", getTimeMS()); + memory_status(); } if (buffer[0] == 't') {