.asm
Assembly
(text/assembly)
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 512 KB
    jmp 0x28:0x00080000