changeset 29:7e3bdcb391dc

Added get_page function to mm
author windel
date Thu, 29 Dec 2011 19:34:01 +0100
parents 47b7df514243
children 0148f55bfe24
files cos/Makefile cos/grub/menu.lst cos/kernel/Makefile cos/kernel/asmcode.asm cos/kernel/handlers.c cos/kernel/kernel.c cos/kernel/kernel.h cos/kernel/klib.c cos/kernel/link.ld cos/kernel/malloc.c cos/kernel/mm.c
diffstat 11 files changed, 369 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- /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
+
--- 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
 
--- 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:
--- 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
--- 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");
 }
 
 
--- 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();
+    }
   }
 }
 
--- 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
 
--- 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: ");
--- 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 = .;
 }
 
--- 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)
--- 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];
+}
+