# HG changeset patch # User windel # Date 1322510080 -3600 # Node ID b1fed2171e1a54b7bc76adb163187448576dbadf # Parent f454e3c592dd27b757b62c467394658db5b0b566 Now working with 2 MB pages diff -r f454e3c592dd -r b1fed2171e1a cos/Makefile --- 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 diff -r f454e3c592dd -r b1fed2171e1a cos/kernel/goto64.asm --- 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: diff -r f454e3c592dd -r b1fed2171e1a cos/kernel/handlers.c --- 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; } diff -r f454e3c592dd -r b1fed2171e1a cos/kernel/kernel.c --- 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) diff -r f454e3c592dd -r b1fed2171e1a cos/kernel/kernel.h --- 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; diff -r f454e3c592dd -r b1fed2171e1a cos/linker.ld --- 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 = .; } }