Mercurial > lcfOS
diff cos/kernel/goto64.asm @ 20:b1fed2171e1a
Now working with 2 MB pages
author | windel |
---|---|
date | Mon, 28 Nov 2011 20:54:40 +0100 |
parents | 6129643f5c34 |
children | 5dd47d6eebac |
line wrap: on
line diff
--- 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: