Mercurial > lcfOS
view cos/kernel/goto64.asm @ 18:6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
author | windel |
---|---|
date | Sun, 20 Nov 2011 20:35:51 +0100 |
parents | fcdae30b2782 |
children | b1fed2171e1a |
line wrap: on
line source
;#!/usr/bin/nasm ; ; See http://wiki.osdev.org/User:Stephanvanschaik/Setting_Up_Long_Mode ; 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. bits 32 ; Start in 32 bits mode. ; Multiboot header: ; Settings for multiboot header PAGE_ALIGN equ 1 << 0 MEM_INFO equ 1 << 1 KLUDGE equ 1 << 16 MAGIC equ 0x1BADB002 FLAGS equ PAGE_ALIGN | MEM_INFO | KLUDGE ; align and provide memory map CHECKSUM equ -(MAGIC+FLAGS) ; actual multiboot header: align 4 MultiBootHeader: dd MAGIC dd FLAGS dd CHECKSUM ; item below are present if bit 16 is set in flags dd MultiBootHeader ; physical address in file of header (will be 0x100000 if put at start) dd 0x100000 ; load_addr: load address, the address to start loading dd 0x0 ; load_end_addr: zero indicates to load whole file dd 0x0 ; bss_end_addr: zero indicates no bss segment present dd loader ; entry_addr: jump to here ; GDT, three entries: one for code, one for data GDT64: .Null: equ $ - GDT64 dq 0 .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 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 ; Start of loader code: global loader loader: ; Check that the CPU supports long mode: mov eax, 80000000h cpuid cmp eax, 80000000h jbe no_long_mode mov eax, 80000001h cpuid bt edx, 29 jnc no_long_mode jmp long_mode no_long_mode: hlt long_mode: ; Prepare paging: ; PML4T - 0x1000 ; PDPT - 0x2000 ; PDT - 0x3000 ; PT - 0x4000 ; Clear the tables: 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 ; 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 ; Enable paging: mov eax, cr4 or eax, 1 << 5 ; PAE-bit is bit 5 mov cr4, eax ; Load the GDT: lgdt [GDT64.Pointer] ; Set LM-bit (Long Mode bit): mov ecx, 0xC0000080 rdmsr or eax, 0x100 ; Set bit 8 (LM-bit) wrmsr ; Enable paging: mov eax, cr0 or eax, 0x80000000 ; Set bit 31 (PG-bit) mov cr0, eax ; Jump to 64 bits kernel: jmp GDT64.Code:Realm64 bits 64 ; realm64 Realm64: ; Clear segment registers: xor ax, ax mov ds, ax mov es, ax mov ss, ax 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 ; Jump to code that is glued after this file jmp einde align 16 dataEnd: ; reserve bytes for stack: stackBegin: resb 1024 stackEnd: einde: # XCHG BX, BX ; bochs breakpoint # Call kernel: extern kmain call kmain # Should we ever return, remain in endless loop: cli hang: hlt jmp hang