Mercurial > lcfOS
diff cos/kernel/goto64.asm @ 9:92ace1ca50a8
64 bits kernel without interrupts but with printf in C
author | windel |
---|---|
date | Sun, 13 Nov 2011 12:47:47 +0100 |
parents | |
children | fcdae30b2782 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/goto64.asm Sun Nov 13 12:47:47 2011 +0100 @@ -0,0 +1,158 @@ +;#!/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 +dw 0 +dw 0 +db 0 +db 0 +db 0 +db 0 +.Code: equ $ - GDT64 +dw 0 +dw 0 +db 0 +db 10011000b ; access +db 00100000b ; granularity +db 0 +.Data: equ $ - GDT64 +dw 0 +dw 0 +db 0 +db 10010000b ; access +db 00000000b ; granularity +db 0 +.Pointer: ; GDT pointer +dw $ - GDT64 - 1 ; Limit +dq GDT64 ; Base + +; Start of loader code: +global loader +loader: + +; 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 + +; 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 + +; Load the GDT: +lgdt [GDT64.Pointer] + +; Jump to 64 bits kernel: +jmp GDT64.Code:Realm64 + +bits 64 + +; realm64 +Realm64: + +cli +mov ax, GDT64.Data +mov ds, ax +mov es, ax +mov fs, ax +mov gs, ax + +; 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 +