aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/core/loader.s
blob: 6f14be62c9d8933b0298ee1e1b29aed5d0005787 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
[EXTERN kmain]            ; kmain is defined in kmain.c
[GLOBAL loader]           ; making entry point visible to linker
[GLOBAL kernel_pd]   	  ; make kernel page directory visible
[GLOBAL kernel_stack_protector] 		; used to detect kernel stack overflow
[GLOBAL kernel_stack_bottom] 			; usefull for debugging
[GLOBAL kernel_stack_top] 				; stack re-used by scheduler

; higher-half kernel setup
K_HIGHHALF_ADDR     equ 0xC0000000
K_PAGE_NUMBER       equ (K_HIGHHALF_ADDR >> 22)

; loader stack size
LOADER_STACK_SIZE   equ 0x8000		; 8Kb

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN         equ 1<<0                   ; align loaded modules on page boundaries
MEMINFO             equ 1<<1                   ; provide memory map
FLAGS               equ MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC               equ 0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM            equ -(MAGIC + FLAGS)        ; checksum required

[section .setup]
align 4
multiboot_header:
	dd MAGIC
	dd FLAGS
	dd CHECKSUM

loader:	
	; setup the boot page directory used for higher-half
	mov ecx, kernel_pd
	sub ecx, K_HIGHHALF_ADDR	; access its lower-half address
	mov cr3, ecx

	; Set PSE bit in CR4 to enable 4MB pages.
	mov ecx, cr4
	or ecx, 0x00000010
	mov cr4, ecx

	; Set PG bit in CR0 to enable paging.
	mov ecx, cr0
	or ecx, 0x80000000
	mov cr0, ecx

	; long jump required
	lea ecx, [higherhalf]
	jmp ecx

[section .data]
align 0x1000
kernel_pd:
	; uses 4MB pages
	; identity-maps the first 4Mb of RAM, and also maps them with offset += k_highhalf_addr
	dd 0x00000083
	times (K_PAGE_NUMBER - 1) dd 0
	dd 0x00000083
	times (1024 - K_PAGE_NUMBER - 1) dd 0

[section .text]
higherhalf:		; now we're running in higher half
	; unmap first 4Mb
	mov dword [kernel_pd], 0
	invlpg [0]

	mov esp, kernel_stack_top   ; set up the stack

	push eax                    ; pass Multiboot magic number
	add ebx, K_HIGHHALF_ADDR    ; update the MB info structure so that it is in higher half
	push ebx                    ; pass Multiboot info structure

	call  kmain                 ; call kernel proper

hang:
	; halt machine should kernel return
	cli
	hlt
	jmp   hang

[section .bss]
align 0x1000
kernel_stack_protector:
	resb 0x1000			; as soon as we have efficient paging, we WON'T map this page
kernel_stack_bottom:
	resb LOADER_STACK_SIZE
kernel_stack_top:

; vim: set ts=4 sw=4 tw=0 noet :