bits 32
PML4_ADDR: equ 0x7200
PDPT_ADDR: equ 0x7300
PD_ADDR: equ 0x7400
; void setup_page_tables()
setup_page_tables:
; Zero PML4 table (4096 bytes)
mov edi, PML4_ADDR
xor eax, eax
mov ecx, 1024
rep stosd
; Zero PDPT table (4096 bytes)
mov edi, PDPT_ADDR
xor eax, eax
mov ecx, 1024
rep stosd
; Zero PD table (4096 bytes)
mov edi, PD_ADDR
xor eax, eax
mov ecx, 1024
rep stosd
; PML4[0] -> PDPT
mov eax, PDPT_ADDR
or eax, 0x03
mov [PML4_ADDR], eax
mov dword [PML4_ADDR + 4], 0
; PDPT[0] -> PD
mov eax, PD_ADDR
or eax, 0x03
mov [PDPT_ADDR], eax
mov dword [PDPT_ADDR + 4], 0
; PD[0] -> 2MiB identity mapped page
mov dword [PD_ADDR], 0x00000083
mov dword [PD_ADDR + 4], 0
ret
; Enters long mode and jumps to the 64-bit kernel entry point.
enter_long_mode:
; enable protected mode first
enable_protected_mode
call setup_page_tables
; Enable PAE
mov eax, cr4
or eax, 0x20
mov cr4, eax
; Enable long mode in EFER
mov ecx, 0xC0000080
rdmsr
or eax, 0x100
wrmsr
; Load page tables
mov eax, PML4_ADDR
mov cr3, eax
; Enable paging
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
; Jump into the 64-bit kernel entry at 1MB
jmp 0x28:0x00100000