; https://wiki.osdev.org/Creating_a_64-bit_kernel ; https://wiki.osdev.org/Entering_Long_Mode_Directly KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB KERNEL_LMA equ 0x1000000 ; 16MB KERNEL_STACK_SIZE equ 0x4000 ; 16KB extern Multiboot2Entry extern BootPageTable extern UpdatePageTable extern UpdatePageTable64 extern DetectCPUID extern Detect64Bit extern LoadGDT32 global MB2_start extern MB2_start_c [bits 32] section .bootstrap.data global MB2_HeaderMagic MB2_HeaderMagic: times (0x64) dq 0 global MB2_HeaderInfo MB2_HeaderInfo: times (0x64) dq 0 section .bootstrap.text MB2_start: cli ; mov word [0xb8F00], 0x072E ; . mov [MB2_HeaderMagic], eax mov [MB2_HeaderInfo], ebx ; We need to check if the CPU supports 64-bit mode call DetectCPUID call Detect64Bit ; mov word [0xb8F02], 0x072E ; . mov ecx, cr0 and ecx, 0x7fffffff ; Clear PG mov cr0, ecx mov ecx, cr4 or ecx, 0x10 ; Set PSE or ecx, 0x20 ; Set PAE mov cr4, ecx ; Load the GDT and update the page table call LoadGDT32 call UpdatePageTable ; Load the new page table mov edi, BootPageTable mov cr3, edi ; mov word [0xb8F04], 0x072E ; . ; Enable long mode mov ecx, 0xC0000080 ; EFER rdmsr or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE wrmsr mov ecx, cr0 or ecx, (0x80000000 | 0x1) ; Set PG and PE mov cr0, ecx lgdt [GDT64.Ptr] ; xor eax, eax ; sgdt [eax] ; test eax, eax ; jz .InvalidGDT ; .InvalidGDT: ; mov word [0xb8F07], 0x4 ; Red ; hlt jmp GDT64.code:HigherHalfStart [bits 64] HigherHalfStart: cli ; mov word [0xb8F06], 0x072E ; . call UpdatePageTable64 ; Load the new page table mov rdi, BootPageTable mov cr3, rdi mov ax, GDT64.data mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ; mov word [0xb8F08], 0x072E ; . mov rsp, (KernelStack + KERNEL_STACK_SIZE) mov rbp, (KernelStack + KERNEL_STACK_SIZE) cld cli call Multiboot2Entry .Loop: hlt jmp .Loop section .bootstrap.bss align 16 KernelStack: resb KERNEL_STACK_SIZE ; Access bits PRESENT equ 1 << 7 NOT_SYS equ 1 << 4 EXEC equ 1 << 3 DC equ 1 << 2 RW equ 1 << 1 ACCESSED equ 1 << 0 ; Flags bits GRAN_4K equ 1 << 7 SZ_32 equ 1 << 6 LONG_MODE equ 1 << 5 section .bootstrap.data GDT64: .null: equ $ - GDT64 dq 0 .code: equ $ - GDT64 dd 0xFFFF db 0 db PRESENT | NOT_SYS | EXEC | RW db GRAN_4K | LONG_MODE | 0xF db 0 .data: equ $ - GDT64 dd 0xFFFF db 0 db PRESENT | NOT_SYS | RW db GRAN_4K | SZ_32 | 0xF db 0 .tss: equ $ - GDT64 dd 0x00000068 dd 0x00CF8900 .Ptr: dw $ - GDT64 - 1 dq GDT64