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')
     {