Mercurial > lcfOS
comparison cos/kernel/goto64.asm @ 20:b1fed2171e1a
Now working with 2 MB pages
author | windel |
---|---|
date | Mon, 28 Nov 2011 20:54:40 +0100 |
parents | 6129643f5c34 |
children | 5dd47d6eebac |
comparison
equal
deleted
inserted
replaced
19:f454e3c592dd | 20:b1fed2171e1a |
---|---|
3 ; | 3 ; |
4 ; See http://wiki.osdev.org/User:Stephanvanschaik/Setting_Up_Long_Mode | 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. | 5 ; Loader assembly to load the 64 bits kernel just after this file. |
6 | 6 |
7 ; Assume that we are loaded at 1M (0x100000) | 7 ; Assume that we are loaded at 1M (0x100000) |
8 ;org 0x100000 ; this only works with flat bin output, not with elf64 output. | 8 |
9 | 9 ; This file sets up long mode and creates paging tables. |
10 bits 32 ; Start in 32 bits mode. | 10 ; Use 2 mbyte pages. Is this more efficient? |
11 | |
12 ; Intended memory map (copied from pure64), at the end of this file: | |
13 ; 0x0 : IDT, 256 entries | |
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) | |
18 ; 0x5000 - 0xA000 : Stack | |
19 | |
20 bits 32 ; Start in 32 bits mode, as loaded by GRUB | |
21 | |
11 ; Multiboot header: | 22 ; Multiboot header: |
12 ; Settings for multiboot header | 23 ; Settings for multiboot header |
13 PAGE_ALIGN equ 1 << 0 | 24 PAGE_ALIGN equ 1 << 0 |
14 MEM_INFO equ 1 << 1 | 25 MEM_INFO equ 1 << 1 |
15 KLUDGE equ 1 << 16 | 26 KLUDGE equ 1 << 16 |
28 dd 0x100000 ; load_addr: load address, the address to start loading | 39 dd 0x100000 ; load_addr: load address, the address to start loading |
29 dd 0x0 ; load_end_addr: zero indicates to load whole file | 40 dd 0x0 ; load_end_addr: zero indicates to load whole file |
30 dd 0x0 ; bss_end_addr: zero indicates no bss segment present | 41 dd 0x0 ; bss_end_addr: zero indicates no bss segment present |
31 dd loader ; entry_addr: jump to here | 42 dd loader ; entry_addr: jump to here |
32 | 43 |
44 ; 32 bits temporary GDT: | |
45 align 16 | |
46 gdt32: | |
47 dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null desciptor | |
48 dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code desciptor | |
49 dw 0xFFFF, 0x0000, 0x9200, 0x008F ; 32-bit data desciptor | |
50 gdt32_end: | |
51 | |
52 ; 32 bits gdt pointer: | |
53 align 16 | |
54 gdt32pointer: ; Global Descriptors Table Register | |
55 dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one) | |
56 dq gdt32 ; linear address of GDT | |
57 | |
33 ; GDT, three entries: one for code, one for data | 58 ; GDT, three entries: one for code, one for data |
34 GDT64: | 59 align 16 |
35 .Null: equ $ - GDT64 | 60 gdt64: |
61 .Null: equ $ - gdt64 | |
36 dq 0 | 62 dq 0 |
37 .Code: equ $ - GDT64 | 63 .Code: equ $ - gdt64 |
38 dw 0 ; Segment limit 15-0 | 64 dw 0 ; Segment limit 15-0 |
39 dw 0 ; Base 15 - 0 | 65 dw 0 ; Base 15 - 0 |
40 db 0 ; Base 23 - 16 | 66 db 0 ; Base 23 - 16 |
41 db 10011000b ; access 0x98 (P=1 => Present) | 67 db 10011000b ; access 0x98 (P=1 => Present) |
42 db 00100000b ; granularity 0x20 (L=1 => long mode) | 68 db 00100000b ; granularity 0x20 (L=1 => long mode) |
43 db 0 | 69 db 0 |
44 .Data: equ $ - GDT64 | 70 .Data: equ $ - gdt64 |
45 dw 0 | 71 dw 0 |
46 dw 0 | 72 dw 0 |
47 db 0 | 73 db 0 |
48 db 10010000b ; access ; 0x90 | 74 db 10010000b ; access ; 0x90 |
49 db 00000000b ; granularity 0x00 | 75 db 00000000b ; granularity 0x00 |
50 db 0 | 76 db 0 |
51 .Pointer: ; GDT pointer | 77 gdt64end: |
52 dw $ - GDT64 - 1 ; Limit | 78 |
53 dq GDT64 ; Base | 79 ;SYS64_NULL_SEL equ $-gdt64 ; Null Segment |
80 ; dq 0x0000000000000000 | |
81 ; SYS64_CODE_SEL equ $-gdt64 ; Code segment, read/execute, nonconforming | |
82 ; dq 0x0020980000000000 ; 0x00209A0000000000 | |
83 ; SYS64_DATA_SEL equ $-gdt64 ; Data segment, read/write, expand down | |
84 ; dq 0x0000900000000000 ; 0x0020920000000000 | |
85 ; gdt64_end: | |
86 | |
87 gdt64pointer: ; GDT pointer | |
88 dw gdt64end - gdt64 - 1 ; Limit (size) | |
89 dq gdt64 ; Base | |
54 | 90 |
55 ; Start of loader code: | 91 ; Start of loader code: |
56 global loader | |
57 loader: | 92 loader: |
58 | 93 |
59 ; Check that the CPU supports long mode: | 94 ; Check that the CPU supports long mode: |
60 mov eax, 80000000h | 95 mov eax, 80000000h |
61 cpuid | 96 cpuid |
63 jbe no_long_mode | 98 jbe no_long_mode |
64 mov eax, 80000001h | 99 mov eax, 80000001h |
65 cpuid | 100 cpuid |
66 bt edx, 29 | 101 bt edx, 29 |
67 jnc no_long_mode | 102 jnc no_long_mode |
68 jmp long_mode | 103 jmp cpu_has_long_mode |
69 | 104 |
70 no_long_mode: | 105 no_long_mode: |
71 hlt | 106 hlt |
72 | 107 |
73 long_mode: | 108 cpu_has_long_mode: |
74 | 109 |
75 ; Prepare paging: | 110 lgdt [gdt32pointer] ; Reload a valid temporary 32 bits GDT, overload GRUB gdt. |
76 ; PML4T - 0x1000 | 111 mov ax, 0x10 |
77 ; PDPT - 0x2000 | 112 mov ds, ax |
78 ; PDT - 0x3000 | 113 mov es, ax |
79 ; PT - 0x4000 | 114 mov fs, ax |
80 | 115 mov gs, ax |
81 ; Clear the tables: | 116 mov ss, ax |
117 jmp 8:start32 ; make sure CS is loaded. | |
118 start32: | |
119 | |
120 cld ; clear direction? | |
121 | |
122 ; Clear the paging tables 0x1000, 0x2000, 0x3000 and 0x4000: | |
82 mov edi, 0x1000 | 123 mov edi, 0x1000 |
83 mov cr3, edi ; CR3 is the page table address! | |
84 xor eax, eax | 124 xor eax, eax |
85 mov ecx, 4096 | 125 mov ecx, 4096 |
86 rep stosd | 126 rep stosd |
87 mov edi, cr3 ; restore edi | 127 |
88 | 128 ; Create PML4 table: |
89 mov DWORD [edi], 0x2003 ; present and readwrite, points to first PDPT | 129 mov edi, 0x1000 |
90 add edi, 0x1000 | 130 mov eax, 0x2003 |
91 mov DWORD [edi], 0x3003 ; present and readwrite, points to first PDT | 131 stosd |
92 add edi, 0x1000 | 132 |
93 mov DWORD [edi], 0x4003 ; present and readwrite, points to first PT | 133 ; Create PDP (page directory pointer) table: |
94 add edi, 0x1000 | 134 mov edi, 0x2000 |
95 | 135 mov eax, 0x3003 ; PDPT entry, present and read/write |
96 ; identity map the first two megabytes: | 136 stosd |
97 mov ebx, 0x00000003 | 137 |
98 mov ecx, 512 | 138 ; Create PD (page directory) table |
99 ; Fill all PT entries at 0x4000 | 139 mov edi, 0x3000 |
100 SetEntry: | 140 ; First entry: |
101 mov DWORD [edi], ebx | 141 mov eax, 0x8F ; PD entry, present (bit 0), read write (bit 1) and bit 7, page size=2MB |
102 add ebx, 0x1000 | 142 stosd |
103 add edi, 8 | 143 xor eax, eax |
104 loop SetEntry | 144 stosd |
105 | 145 |
106 ; Enable paging: | 146 ; Second entry: |
147 mov eax, 0x20008f | |
148 stosd | |
149 xor eax, eax | |
150 stosd | |
151 | |
152 ; Third entry: | |
153 mov eax, 0x40008f | |
154 stosd | |
155 xor eax, eax | |
156 stosd | |
157 ; 6 MB mapped in total now. | |
158 | |
159 mov edi, 0x1000 ; Set load address | |
160 mov cr3, edi ; CR3 is the PML4 base address! | |
161 | |
162 ; Enable address extension: | |
107 mov eax, cr4 | 163 mov eax, cr4 |
108 or eax, 1 << 5 ; PAE-bit is bit 5 | 164 or eax, 1 << 5 ; PAE-bit is bit 5 |
109 mov cr4, eax | 165 mov cr4, eax |
110 | 166 |
111 ; Load the GDT: | 167 ; Load the GDT: |
112 lgdt [GDT64.Pointer] | 168 lgdt [gdt64pointer] |
113 | 169 |
114 ; Set LM-bit (Long Mode bit): | 170 ; Set LM-bit (Long Mode bit): |
115 mov ecx, 0xC0000080 | 171 mov ecx, 0xC0000080 |
116 rdmsr | 172 rdmsr |
117 or eax, 0x100 ; Set bit 8 (LM-bit) | 173 or eax, 0x100 ; Set bit 8 (LM-bit) |
120 ; Enable paging: | 176 ; Enable paging: |
121 mov eax, cr0 | 177 mov eax, cr0 |
122 or eax, 0x80000000 ; Set bit 31 (PG-bit) | 178 or eax, 0x80000000 ; Set bit 31 (PG-bit) |
123 mov cr0, eax | 179 mov cr0, eax |
124 | 180 |
125 | |
126 ; Jump to 64 bits kernel: | 181 ; Jump to 64 bits kernel: |
127 jmp GDT64.Code:Realm64 | 182 jmp gdt64.Code:Realm64 |
128 | 183 |
129 bits 64 | 184 bits 64 |
130 | 185 align 16 |
131 ; realm64 | 186 |
132 Realm64: | 187 Realm64: |
133 | 188 |
134 ; Clear segment registers: | 189 ; Clear segment registers: |
135 xor ax, ax | 190 xor ax, ax |
136 mov ds, ax | 191 mov ds, ax |
137 mov es, ax | 192 mov es, ax |
138 mov ss, ax | 193 mov ss, ax |
139 mov fs, ax | 194 mov fs, ax |
140 mov gs, ax | 195 mov gs, ax |
141 | 196 |
142 ; Reoad the GDT: | 197 lgdt [gdt64pointer] ; Reload GDT in 64 bits mode |
143 lgdt [GDT64.Pointer] | 198 |
144 | 199 mov rsp, 0xA000 ; Setup stack pointer. |
145 ; Done! | 200 |
146 | |
147 ; Setup stack pointer: | |
148 mov rsp, stackEnd | |
149 ; Put a B upper left corner | |
150 mov al, 66 ; 'B' | |
151 mov [0xb8000], al | |
152 | |
153 ; Jump to code that is glued after this file | |
154 jmp einde | |
155 | |
156 align 16 | |
157 dataEnd: | |
158 ; reserve bytes for stack: | |
159 stackBegin: | |
160 resb 1024 | |
161 stackEnd: | |
162 | |
163 einde: | |
164 # XCHG BX, BX ; bochs breakpoint | 201 # XCHG BX, BX ; bochs breakpoint |
165 | 202 |
166 # Call kernel: | |
167 extern kmain | 203 extern kmain |
168 call kmain | 204 call kmain ; Call kernel in C-code |
205 | |
169 # Should we ever return, remain in endless loop: | 206 # Should we ever return, remain in endless loop: |
170 cli | 207 cli |
171 hang: | 208 hang: |
172 hlt | 209 hlt |
173 jmp hang | 210 jmp hang |