Mercurial > lcfOS
annotate cos/kernel/goto64.asm @ 287:1c7c1e619be8
File movage
author | Windel Bouwman |
---|---|
date | Thu, 21 Nov 2013 11:57:27 +0100 |
parents | bcb3b68c8147 |
children |
rev | line source |
---|---|
9 | 1 ;#!/usr/bin/nasm |
2 | |
3 ; | |
4 ; See http://wiki.osdev.org/User:Stephanvanschaik/Setting_Up_Long_Mode | |
5 ; Loader assembly to load the 64 bits kernel just after this file. | |
6 | |
7 ; Assume that we are loaded at 1M (0x100000) | |
20 | 8 |
9 ; This file sets up long mode and creates paging tables. | |
10 ; Use 2 mbyte pages. Is this more efficient? | |
9 | 11 |
20 | 12 ; Intended memory map (copied from pure64), at the end of this file: |
24 | 13 ; MOVED TO 0x5000!! 0x0 : IDT, 256 entries |
20 | 14 ; 0x1000 - 0x2000 : PML4 (Page map level 4) |
15 ; 0x2000 - 0x3000 : PDPT (page directory pointer table) | |
16 ; 0x3000 - 0x4000 : PDT (page directory table) | |
17 ; 0x4000 - 0x5000 : PT (page table) | |
24 | 18 ; 0x5000 - 0x6000 : IDT entries |
19 ; 0x6000 - 0xA000 : Stack | |
20 | |
20 | 21 bits 32 ; Start in 32 bits mode, as loaded by GRUB |
22 | |
9 | 23 ; Multiboot header: |
24 ; Settings for multiboot header | |
25 PAGE_ALIGN equ 1 << 0 | |
26 MEM_INFO equ 1 << 1 | |
27 KLUDGE equ 1 << 16 | |
28 MAGIC equ 0x1BADB002 | |
29 FLAGS equ PAGE_ALIGN | MEM_INFO | KLUDGE ; align and provide memory map | |
30 CHECKSUM equ -(MAGIC+FLAGS) | |
31 | |
32 ; actual multiboot header: | |
33 align 4 | |
34 MultiBootHeader: | |
35 dd MAGIC | |
36 dd FLAGS | |
37 dd CHECKSUM | |
38 ; item below are present if bit 16 is set in flags | |
35
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
39 extern load_end_address ; Import load end address from linker script |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
40 extern bss_end_address ; Import bss end address to make sure data is zero initialized. |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
41 dd MultiBootHeader ; physical address in file of header (will be 0x100000 if put at start) |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
42 dd 0x100000 ; load_addr: load address, the address to start loading |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
43 dd load_end_address ; load_end_addr: zero indicates to load whole file |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
44 dd bss_end_address ; bss_end_addr: zero indicates no bss segment present |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
45 dd loader ; entry_addr: jump to here |
9 | 46 |
20 | 47 ; 32 bits temporary GDT: |
48 align 16 | |
49 gdt32: | |
50 dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null desciptor | |
51 dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code desciptor | |
52 dw 0xFFFF, 0x0000, 0x9200, 0x008F ; 32-bit data desciptor | |
53 gdt32_end: | |
54 | |
55 ; 32 bits gdt pointer: | |
56 align 16 | |
57 gdt32pointer: ; Global Descriptors Table Register | |
58 dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one) | |
59 dq gdt32 ; linear address of GDT | |
60 | |
9 | 61 ; GDT, three entries: one for code, one for data |
20 | 62 align 16 |
63 gdt64: | |
64 .Null: equ $ - gdt64 | |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
65 dq 0 |
20 | 66 .Code: equ $ - gdt64 |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
67 dw 0 ; Segment limit 15-0 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
68 dw 0 ; Base 15 - 0 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
69 db 0 ; Base 23 - 16 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
70 db 10011000b ; access 0x98 (P=1 => Present) |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
71 db 00100000b ; granularity 0x20 (L=1 => long mode) |
9 | 72 db 0 |
20 | 73 .Data: equ $ - gdt64 |
9 | 74 dw 0 |
75 dw 0 | |
76 db 0 | |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
77 db 10010000b ; access ; 0x90 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
78 db 00000000b ; granularity 0x00 |
9 | 79 db 0 |
20 | 80 gdt64end: |
81 | |
82 ;SYS64_NULL_SEL equ $-gdt64 ; Null Segment | |
83 ; dq 0x0000000000000000 | |
84 ; SYS64_CODE_SEL equ $-gdt64 ; Code segment, read/execute, nonconforming | |
85 ; dq 0x0020980000000000 ; 0x00209A0000000000 | |
86 ; SYS64_DATA_SEL equ $-gdt64 ; Data segment, read/write, expand down | |
87 ; dq 0x0000900000000000 ; 0x0020920000000000 | |
88 ; gdt64_end: | |
89 | |
90 gdt64pointer: ; GDT pointer | |
91 dw gdt64end - gdt64 - 1 ; Limit (size) | |
92 dq gdt64 ; Base | |
9 | 93 |
23 | 94 hltmessage: |
95 db "Long mode not supported", 0x0 | |
96 | |
9 | 97 ; Start of loader code: |
98 loader: | |
32
3a6a9b929db0
Added initial ramdisk and some virtual file system functions
windel
parents:
24
diff
changeset
|
99 ; here ebx contains the pointer to the multiboot header, store is for later use. |
35
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
100 ; Make sure that multiboot_info is located in the BSS section and that this section |
bcb3b68c8147
Added bss end address and load end address to multiboot header
windel
parents:
34
diff
changeset
|
101 ; is proper zeroed. |
32
3a6a9b929db0
Added initial ramdisk and some virtual file system functions
windel
parents:
24
diff
changeset
|
102 extern multiboot_info |
3a6a9b929db0
Added initial ramdisk and some virtual file system functions
windel
parents:
24
diff
changeset
|
103 mov [multiboot_info], ebx |
9 | 104 |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
105 ; Check that the CPU supports long mode: |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
106 mov eax, 80000000h |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
107 cpuid |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
108 cmp eax, 80000000h |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
109 jbe no_long_mode |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
110 mov eax, 80000001h |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
111 cpuid |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
112 bt edx, 29 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
113 jnc no_long_mode |
20 | 114 jmp cpu_has_long_mode |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
115 |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
116 no_long_mode: |
23 | 117 ; Print long mode not supported |
118 mov edi, 0xb8000 | |
119 mov esi, hltmessage | |
24 | 120 xor eax, eax |
23 | 121 loop1: |
122 lodsb | |
123 mov dl, al | |
124 stosb | |
125 mov al, 0x1f | |
126 stosb | |
127 cmp dl, 0 | |
128 jne loop1 | |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
129 hlt |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
130 |
20 | 131 cpu_has_long_mode: |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
132 |
20 | 133 lgdt [gdt32pointer] ; Reload a valid temporary 32 bits GDT, overload GRUB gdt. |
134 mov ax, 0x10 | |
135 mov ds, ax | |
136 mov es, ax | |
137 mov fs, ax | |
138 mov gs, ax | |
139 mov ss, ax | |
140 jmp 8:start32 ; make sure CS is loaded. | |
141 start32: | |
9 | 142 |
20 | 143 cld ; clear direction? |
144 | |
145 ; Clear the paging tables 0x1000, 0x2000, 0x3000 and 0x4000: | |
9 | 146 mov edi, 0x1000 |
147 xor eax, eax | |
24 | 148 mov ecx, 0x1000 |
9 | 149 rep stosd |
150 | |
20 | 151 ; Create PML4 table: |
152 mov edi, 0x1000 | |
153 mov eax, 0x2003 | |
154 stosd | |
155 | |
156 ; Create PDP (page directory pointer) table: | |
157 mov edi, 0x2000 | |
158 mov eax, 0x3003 ; PDPT entry, present and read/write | |
159 stosd | |
9 | 160 |
20 | 161 ; Create PD (page directory) table |
162 mov edi, 0x3000 | |
163 ; First entry: | |
164 mov eax, 0x8F ; PD entry, present (bit 0), read write (bit 1) and bit 7, page size=2MB | |
165 stosd | |
166 xor eax, eax | |
167 stosd | |
9 | 168 |
20 | 169 ; Second entry: |
170 mov eax, 0x20008f | |
171 stosd | |
172 xor eax, eax | |
173 stosd | |
174 | |
175 ; Third entry: | |
176 mov eax, 0x40008f | |
177 stosd | |
178 xor eax, eax | |
179 stosd | |
180 ; 6 MB mapped in total now. | |
181 | |
182 mov edi, 0x1000 ; Set load address | |
183 mov cr3, edi ; CR3 is the PML4 base address! | |
184 | |
185 ; Enable address extension: | |
9 | 186 mov eax, cr4 |
187 or eax, 1 << 5 ; PAE-bit is bit 5 | |
188 mov cr4, eax | |
189 | |
24 | 190 lgdt [gdt64pointer] ; Load the GDT |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
191 |
9 | 192 ; Set LM-bit (Long Mode bit): |
193 mov ecx, 0xC0000080 | |
194 rdmsr | |
195 or eax, 0x100 ; Set bit 8 (LM-bit) | |
196 wrmsr | |
197 | |
198 ; Enable paging: | |
199 mov eax, cr0 | |
200 or eax, 0x80000000 ; Set bit 31 (PG-bit) | |
201 mov cr0, eax | |
202 | |
203 ; Jump to 64 bits kernel: | |
20 | 204 jmp gdt64.Code:Realm64 |
9 | 205 |
206 bits 64 | |
20 | 207 align 16 |
9 | 208 |
209 Realm64: | |
210 | |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
211 ; Clear segment registers: |
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
212 xor ax, ax |
9 | 213 mov ds, ax |
214 mov es, ax | |
18
6129643f5c34
Fixed interrupt issue, ds, es, ss, fs and gs were not initialized to 0
windel
parents:
12
diff
changeset
|
215 mov ss, ax |
9 | 216 mov fs, ax |
217 mov gs, ax | |
218 | |
20 | 219 lgdt [gdt64pointer] ; Reload GDT in 64 bits mode |
9 | 220 |
33 | 221 ; Test: |
222 mov ax, 0x10 | |
223 mov ds, ax | |
224 ; End of test | |
225 | |
32
3a6a9b929db0
Added initial ramdisk and some virtual file system functions
windel
parents:
24
diff
changeset
|
226 ; TODO: determine a good place for the kernel stack. |
20 | 227 mov rsp, 0xA000 ; Setup stack pointer. |
9 | 228 |
229 extern kmain | |
20 | 230 call kmain ; Call kernel in C-code |
231 |