changeset 20:b1fed2171e1a

Now working with 2 MB pages
author windel
date Mon, 28 Nov 2011 20:54:40 +0100
parents f454e3c592dd
children 66e9c332c845
files cos/Makefile cos/kernel/goto64.asm cos/kernel/handlers.c cos/kernel/kernel.c cos/kernel/kernel.h cos/linker.ld
diffstat 6 files changed, 142 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/cos/Makefile	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/Makefile	Mon Nov 28 20:54:40 2011 +0100
@@ -2,12 +2,10 @@
 
 all: bootdisk.img Makefile
 
-bootdisk.img: lcfosc.elf grub/menu.lst Makefile
-	objcopy -O binary lcfosc.elf lcfosc.bin
+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
-	mdir -i bootdisk.img
 
 CRT0 = kernel/goto64.o
 
@@ -28,8 +26,8 @@
 	kernel/handlers.o
 
 
-lcfosc.elf: $(CRT0) $(OBJECTS) linker.ld
-	ld -T linker.ld -o lcfosc.elf $(CRT0) $(OBJECTS)
+lcfosc.bin: $(CRT0) $(OBJECTS) linker.ld
+	ld -T linker.ld -o lcfosc.bin $(CRT0) $(OBJECTS)
 
 %.o : %.asm Makefile
 	nasm -f elf64 -o $@ $<
@@ -38,5 +36,5 @@
 	gcc $(CFLAGS) -o $@ -c $< -Wall -Wextra -Werror
 
 clean:
-	rm $(OBJECTS) $(CRT0) lcfosc.bin lcfosc.elf
+	rm $(OBJECTS) $(CRT0) lcfosc.bin
 
--- a/cos/kernel/goto64.asm	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/kernel/goto64.asm	Mon Nov 28 20:54:40 2011 +0100
@@ -5,9 +5,20 @@
 ; Loader assembly to load the 64 bits kernel just after this file.
 
 ; Assume that we are loaded at 1M (0x100000)
-;org 0x100000 ; this only works with flat bin output, not with elf64 output.
+
+; This file sets up long mode and creates paging tables.
+; Use 2 mbyte pages. Is this more efficient?
 
-bits 32 ; Start in 32 bits mode.
+; Intended memory map (copied from pure64), at the end of this file:
+; 0x0 : IDT, 256 entries
+; 0x1000 - 0x2000 : PML4 (Page map level 4)
+; 0x2000 - 0x3000 : PDPT (page directory pointer table)
+; 0x3000 - 0x4000 : PDT (page directory table)
+; 0x4000 - 0x5000 : PT (page table)
+; 0x5000 - 0xA000 : Stack
+
+bits 32 ; Start in 32 bits mode, as loaded by GRUB
+
 ; Multiboot header:
 ; Settings for multiboot header
 PAGE_ALIGN equ 1 << 0
@@ -30,30 +41,54 @@
 dd 0x0             ; bss_end_addr: zero indicates no bss segment present
 dd loader          ; entry_addr: jump to here
 
+; 32 bits temporary GDT:
+align 16                                                                        
+gdt32:
+dw 0x0000, 0x0000, 0x0000, 0x0000   ; Null desciptor
+dw 0xFFFF, 0x0000, 0x9A00, 0x00CF   ; 32-bit code desciptor
+dw 0xFFFF, 0x0000, 0x9200, 0x008F   ; 32-bit data desciptor
+gdt32_end:
+
+; 32 bits gdt pointer:
+align 16
+gdt32pointer:              ; Global Descriptors Table Register
+dw gdt32_end - gdt32 - 1      ; limit of GDT (size minus one)
+dq gdt32          ; linear address of GDT
+
 ; GDT, three entries: one for code, one for data
-GDT64:
-.Null: equ $ - GDT64
+align 16
+gdt64:
+.Null: equ $ - gdt64
 dq 0
-.Code: equ $ - GDT64
+.Code: equ $ - gdt64
 dw 0 ; Segment limit 15-0
 dw 0 ; Base 15 - 0
 db 0 ; Base 23 - 16
 db 10011000b ; access 0x98 (P=1 => Present)
 db 00100000b ; granularity 0x20 (L=1 => long mode)
 db 0
-.Data: equ $ - GDT64
+.Data: equ $ - gdt64
 dw 0
 dw 0
 db 0
 db 10010000b ; access ; 0x90
 db 00000000b ; granularity 0x00
 db 0
-.Pointer: ; GDT pointer
-dw $ - GDT64 - 1 ; Limit
-dq GDT64 ; Base
+gdt64end:
+
+;SYS64_NULL_SEL equ $-gdt64    ; Null Segment                                    
+; dq 0x0000000000000000 
+; SYS64_CODE_SEL equ $-gdt64    ; Code segment, read/execute, nonconforming
+; dq 0x0020980000000000      ; 0x00209A0000000000 
+; SYS64_DATA_SEL equ $-gdt64    ; Data segment, read/write, expand down
+; dq 0x0000900000000000      ; 0x0020920000000000
+; gdt64_end: 
+
+gdt64pointer: ; GDT pointer
+dw gdt64end - gdt64 - 1 ; Limit (size)
+dq gdt64 ; Base
 
 ; Start of loader code:
-global loader
 loader:
 
 ; Check that the CPU supports long mode:
@@ -65,51 +100,72 @@
 cpuid
 bt edx, 29
 jnc no_long_mode
-jmp long_mode
+jmp cpu_has_long_mode
 
 no_long_mode:
 hlt
 
-long_mode:
+cpu_has_long_mode:
 
-; Prepare paging:
-; PML4T - 0x1000
-; PDPT - 0x2000
-; PDT - 0x3000
-; PT - 0x4000
+lgdt [gdt32pointer]         ; Reload a valid temporary 32 bits GDT, overload GRUB gdt.
+mov ax, 0x10
+mov ds, ax
+mov es, ax
+mov fs, ax
+mov gs, ax
+mov ss, ax
+jmp 8:start32            ; make sure CS is loaded.
+start32:
 
-; Clear the tables:
+cld   ; clear direction?
+
+; Clear the paging tables 0x1000, 0x2000, 0x3000 and 0x4000:
 mov edi, 0x1000
-mov cr3, edi ; CR3 is the page table address!
 xor eax, eax
 mov ecx, 4096
 rep stosd
-mov edi, cr3 ; restore edi
 
-mov DWORD [edi], 0x2003 ; present and readwrite, points to first PDPT
-add edi, 0x1000
-mov DWORD [edi], 0x3003 ; present and readwrite, points to first PDT
-add edi, 0x1000
-mov DWORD [edi], 0x4003 ; present and readwrite, points to first PT
-add edi, 0x1000
+; Create PML4 table:
+mov edi, 0x1000 
+mov eax, 0x2003
+stosd
+
+; Create PDP (page directory pointer) table:
+mov edi, 0x2000
+mov eax, 0x3003 ; PDPT entry, present and read/write
+stosd
 
-; identity map the first two megabytes:
-mov ebx, 0x00000003
-mov ecx, 512
-; Fill all PT entries at 0x4000
-SetEntry:
-mov DWORD [edi], ebx
-add ebx, 0x1000
-add edi, 8
-loop SetEntry
+; Create PD (page directory) table
+mov edi, 0x3000
+; First entry:
+mov eax, 0x8F ; PD entry, present (bit 0), read write (bit 1) and bit 7, page size=2MB
+stosd
+xor eax, eax
+stosd
 
-; Enable paging:
+; Second entry:
+mov eax, 0x20008f
+stosd
+xor eax, eax
+stosd
+
+; Third entry:
+mov eax, 0x40008f
+stosd
+xor eax, eax
+stosd
+; 6 MB mapped in total now.
+
+mov edi, 0x1000   ; Set load address
+mov cr3, edi      ; CR3 is the PML4 base address!
+
+; Enable address extension:
 mov eax, cr4
 or eax, 1 << 5 ; PAE-bit is bit 5
 mov cr4, eax
 
 ; Load the GDT:
-lgdt [GDT64.Pointer]
+lgdt [gdt64pointer]
 
 ; Set LM-bit (Long Mode bit):
 mov ecx, 0xC0000080
@@ -122,13 +178,12 @@
 or eax, 0x80000000 ; Set bit 31 (PG-bit)
 mov cr0, eax
 
-
 ; Jump to 64 bits kernel:
-jmp GDT64.Code:Realm64
+jmp gdt64.Code:Realm64
 
 bits 64
+align 16
 
-; realm64
 Realm64:
 
 ; Clear segment registers:
@@ -139,33 +194,15 @@
 mov fs, ax
 mov gs, ax
 
-; Reoad the GDT:
-lgdt [GDT64.Pointer]
-
-; Done!
-
-; Setup stack pointer:
-mov rsp, stackEnd
-; Put a B upper left corner
-mov al, 66 ; 'B'
-mov [0xb8000], al
+lgdt [gdt64pointer]    ; Reload GDT in 64 bits mode
 
-; Jump to code that is glued after this file
-jmp einde
+mov rsp, 0xA000      ; Setup stack pointer.
 
-align 16
-dataEnd:
-; reserve bytes for stack:
-stackBegin:
-resb 1024
-stackEnd:
-
-einde:
 # XCHG BX, BX ; bochs breakpoint
 
-# Call kernel:
 extern kmain
-call kmain
+call kmain              ; Call kernel in C-code
+
 # Should we ever return, remain in endless loop:
 cli
 hang:
--- a/cos/kernel/handlers.c	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/kernel/handlers.c	Mon Nov 28 20:54:40 2011 +0100
@@ -35,7 +35,7 @@
 void INT34(void);
 
 // THE interrupt descriptor table:
-static IDT_entry idt[256];
+IDT_entry *idt = (IDT_entry*)0x0;
 volatile idtPointer idtP;
 
 void setIDTentry(int num, void (*handler)(), uint16_t selector, uint8_t flags)
@@ -232,11 +232,16 @@
   //uint32_t *pageTable = (uint32_t*)(pageDirectory[pageDirIndex] & 0xFFFFFC00);
 }
 
-void INT14handler(unsigned int address) 
+void INT14handler()
 {
-  printf("INT14 called! Page fault for address 0x%x!\n", address);
-  if ( (address & 0xF0000000) == 0xD0000000 ) {
-    mappage(address & 0xFFFFF000);
+  uint64_t faulting_address;
+
+  // 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);
+  if ( (faulting_address & 0xF0000000) == 0xD0000000 ) {
+    mappage(faulting_address & 0xFFFFF000);
     return;
   }
 
--- a/cos/kernel/kernel.c	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/kernel/kernel.c	Mon Nov 28 20:54:40 2011 +0100
@@ -131,16 +131,16 @@
   of the kernel into smaller parts.
   The heap is located at: 0x
 */
-static void* kernel_heap = (void*) 0xD0000000;
+static void* kernel_heap = (void*) 0x400000; // 4 MB - 6 MB is heap
 /* Allocates 'size' bytes and returns the pointer if succesfull.
    Kernelpanic in case of failure..
 */
-void* malloc(uint64_t size) {
+void* kmalloc(uint64_t size) {
   printf("Malloc %d bytes\n", size);
   return kernel_heap;
 }
 
-void free(void* ptr) {
+void kfree(void* ptr) {
   printf("Free address %x\n", ptr);
 }
 
@@ -150,6 +150,19 @@
 
 }
 
+void testMalloc()
+{
+   char *a, *b;
+   a = kmalloc(100);
+   printf("Got a at %x\n", a);
+   a[0] = 'A';
+   b = kmalloc(22);
+   printf("Got b at %x\n", b);
+   b[0] = 'B';
+   kfree(a);
+
+}
+
 void kmain()
 {
   init_screen();
@@ -157,6 +170,8 @@
 
   printf("Enabling interrupts .. ");
   setupIDT();
+  printf("Testing malloc");
+  testMalloc();
   printf("Entering mainloop!\n");
 
   while (1==1) 
--- a/cos/kernel/kernel.h	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/kernel/kernel.h	Mon Nov 28 20:54:40 2011 +0100
@@ -27,8 +27,8 @@
 } __attribute__((packed)) idtPointer;
 
 // memory alloc functions:
-void* malloc(uint64_t size);
-void free(void* ptr);
+void* kmalloc(uint64_t size);
+void kfree(void* ptr);
 
 // STDout funcs:
 void printf(const char* fmt, ... );
@@ -69,9 +69,7 @@
 void mappage(uint64_t address);
 
 int querymode(void);
-int getcs(void);
 void loadPageTable(void* tableAddress);
-void enablePaging(void);
 
 // Variable argument list things:
 #define va_start(v,l)	__builtin_va_start(v,l)
@@ -79,6 +77,7 @@
 #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;
   uint32_t strsize, addr, reserved;
--- a/cos/linker.ld	Sun Nov 27 21:38:38 2011 +0100
+++ b/cos/linker.ld	Mon Nov 28 20:54:40 2011 +0100
@@ -1,26 +1,23 @@
-ENTRY(loader)
+OUTPUT_FORMAT("binary")
 
 SECTIONS {
-  . = 0x00100000;
-
-  .text : {
+  .text 0x100000: 
+  {
     *(.text)
-   }
+  }
 
-  .rodata ALIGN (0x1000) : {
-    
+  .rodata ALIGN (4096) : 
+  {
     *(.rodata)
   }
 
-  .data ALIGN (0x1000) : {
+  .data ALIGN (4096) : 
+  {
     *(.data)
   }
 
   .bss : {
-    sbss = .;
-    *(COMMON)
     *(.bss)
-    ebss = .;
    }
 
 }