[org 0x7000]
[bits 16]

; Data at 0x6000

; Layout:
; +0x00: cr3 (only u32)
; +0x08: stack_base
; +0x10: stack_size
; +0x18: entry

__x86_64_ap_bootstrap:
    cli

    ; Reset DS
    mov ax, 0
    mov ds, ax

    ; Disable NMI
    in al, 0x70
    or al, 0x80
    out 0x70, al

    ; Load GDT32 and enable protected mode
    lgdt [gdt32_ptr]
    mov eax, cr0
    or al, 1
    mov cr0, eax

    jmp 0x08:ap_start_32

[bits 32]
ap_start_32:
    cli

    ; Proper DS
    mov ax, 0x10
    mov ds, ax

    ; Enable PSE+PAE
    mov eax, cr4
    or eax, (1 << 5) | (1 << 4)
    mov cr4, eax

    ; Load CR3
    mov eax, dword [0x6000 + 0x00]
    mov cr3, eax

    ; Enable EFER.LME + EFER.NXE
    mov ecx, 0xC0000080
    rdmsr
    or eax, 1 << 8
    or eax, 1 << 11
    wrmsr

    ; Enable paging
    mov eax, cr0
    or eax, 1 << 31
    mov cr0, eax

    ; Load GDT64
    lgdt [gdt64_ptr]

    jmp 0x08:ap_start_64

[bits 64]
ap_start_64:
    mov rax, 0x10
    mov ds, rax
    mov es, rax
    mov ss, rax

    ; Load stack
    mov rsp, qword [0x6000 + 0x08]
    add rsp, qword [0x6000 + 0x10]
    mov rbp, rsp

    ; Push a dummy value onto the stack for align
    push qword 0

    ; Jump to kernel entry
    mov rax, qword [0x6000 + 0x18]

    jmp rax

align 4
gdt32:
    ; NULL
    dq 0
    ; CS32
    dq 0xCF98000000FFFF
    ; DS32
    dq 0xCF92000000FFFF
gdt32_end:

align 4
gdt32_ptr:
    ; limit
    dw gdt32_end - gdt32 - 1
    dd gdt32

align 4
gdt64:
    ; NULL
    dq 0
    ; CS64
    dq 0x00209A0000000000
    ; DS64
    dq 0x0000920000000000
gdt64_end:

align 4
gdt64_ptr:
    dw gdt64_end - gdt64 - 1
    dd gdt64
