4 mov ecx, 1024 ; 1024 times for 4 byte stosd
12 global multiboot_magic:data
13 global multiboot_infoptr:data
14 global _multiboot_entry:function
19 ; multiboot header needs to be 4 byte aligned.
20 ; it would be anyway I think, but make it explicit
24 dd 0x1BADB002 ; multiboot 1 magic
25 dd 0x00000007 ; flags: 4 KB aligned modules, memory and video informatino
26 dd -(0x1BADB002 + 0x00000007) ; checksum
28 dd 0 ; a place to store the multiboot info pointer until the kernel gets it
32 extern kernel_bootstrap
38 ; boot loader passes multiboot info in ebx and eax
39 mov [multiboot_infoptr], ebx
40 mov [multiboot_magic], eax
42 ; set up initial page tables
43 ; We could also just use 1GB pages for now and let the
44 ; actual memory manager handle it later, we just need
45 ; these tables set up so that we can run the kernel
48 ; free memory at this point is pretty much everything normally free
50 ; 0x1000 - 0x7ffff is all free, plus 0x80000 - bottom of EBDA
52 ; map the first four megabytes of physical memory twice
53 ; once to identity map it, once to map it into the high kernel
54 ; virtual memory area for a higher half kernel
56 ; 0x10000 PML4 (512 GB/entry)
57 ; 0x11000 PDPT identity map (1 GB/entry)
58 ; 0x12000 PDT identity map (2 MB/entry)
59 ; 0x13000 PT identity map 0-2 MB (4 KB/entry)
60 ; 0x14000 PT identity map 2-4 MB
61 ; 0x15000 PDPT kernel map for higher half (1 GB/entry)
62 ; 0x16000 PDT kernel map for higher half (2 MB/entry)
63 ; 0x17000 PT kernel map 0-2 MB
64 ; 0x18000 PT kernel map 2-4 MB
65 ; 0x19000 1GB PDPT physical low 512 GB map
66 ; 0x20000-0x2ffff 64KB initial stack
68 ; zero the initial stack
75 mov esp, 0x30000 ; set to top of stack
77 ; The 3 at the end of these marks the page as present and read/write
81 mov edi, PML4ADDR ; address of initial PML4
82 mov [edi], dword 0x11003 ; first entry, covers virtual 0-512 GB
84 mov [edi + 511 * 8], dword 0x15003 ; last entry, covers upper virtual 512 GB
89 mov [edi], dword 0x12003 ; virtual 0-1 GB
94 ; 0xFFFFFFFF80000000 kernel is at here + 1 MB
95 mov [edi + 510 * 8], dword 0x16003 ; virtual -2 - -1 GB
100 mov [edi], dword 0x13003 ; first 2 MB
101 mov [edi+8], dword 0x14003 ; second 2 MB
106 mov [edi], dword 0x017003
107 mov [edi+8], dword 0x018003
112 ; Don't need to zero-page these, because we're going
113 ; to fill them anyway
117 mov ecx, 1024 ; i.e. two tables worth
127 mov cr3, eax ; paging is off, so this is safe
140 ; enable paging and enter long mode (still 32-bit)
145 ; Load the long mode GDT.
149 ; set the SS register. Probably not needed
150 mov ax, 0x18 ; 0x18 is 64 bit kernel data segment
153 ; jump to the 64 bit code segment
159 ; TODO set up the higher half map here. easier to do in 64 bit code
161 ; from the AMD manual...
162 ; System software must create at least one 64-bit TSS for use after
163 ; activating long mode, and it must execute the LTR instruction, in
164 ; 64-bit mode, to load the TR register with a pointer to the 64-bit TSS
165 ; that serves both 64-bit-mode programs and compatibility-mode
168 ; fill in the TSS selector with the address of the TSS
170 mov rbx, qword TSS_selector
171 ; load up the address fragments
180 ; calculate the TSS segment offset
182 sub rbx, rax ; rbx still holds the TSS_selector address
186 ; and jump to the start code
187 mov rax, qword kernel_bootstrap
202 ; G = -01- ---- so G = 2 always, unless you want to use the avl bit and make it 3
203 ; or G = 4 for a 32 bit segment
204 ; A = 1pl1 1CRA I don't think C matters, and RA should be ignored, so 8?
205 ; but in principle C == 1 for code?
206 ; R == 1 (i.e +2 for read write). Supposedly ignored, but should't hurt
207 ; so, 8 + 0 + 2 + 0 == non conforming read write
208 ; Thus 00 20 9A 00 for code
209 ; 00 20 F2 00 for user code
212 ; L = 2 for 64 bit, 4 for 32 bit
213 ; A = 9 for kernel, F for user
214 ; C = A for code, 2 for data
217 ; 0x00209A00 ; 64 bit kernel code
218 ; 0x00209200 ; 64 bit kernel data
224 dd 0x00000000, 0x00209A00 ; 0x10: 64-bit Kernel Code
225 dd 0x00000000, 0x00209200 ; 0x18: 64-bit Kernel Data
226 dd 0x00000000, 0x0040FA00 ; 0x20: 32-bit User Code, should be unused
227 dd 0x00000000, 0x0040F200 ; 0x28: 32-bit User Data
228 dd 0x00000000, 0x0020FA00 ; 0x30: 64-bit User Code
229 dd 0x00000000, 0x0000F200 ; 0x38: 64-bit User Data
231 times MAX_CPUS dd 0, 0x00008900, 0, 0 ; 0x38+16*n: TSS 0
234 dw GDT_load - GDT64 - 1 ; limit
244 times 2 dd 0 ; ignored
245 times 7 dq 0 ; rsp for ist 1-7
246 times 2 dd 0 ; ignored
248 dd 0 ; base address for io permission bitmap
251 dq TSS_selector - GDT64