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
+