view 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 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
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