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