/ src / impl / x86_64 / boot / main.asm
main.asm
  1  global start
  2  extern long_mode_start
  3  
  4  section .text
  5  bits 32
  6  start:
  7    mov esp, stack_top
  8  
  9    call check_multiboot
 10    call check_cpuid
 11    call check_long_mode
 12  
 13    call setup_page_tables
 14    call enable_paging
 15  
 16    lgdt [gdt64.pointer]
 17    jmp gdt64.code_segment:long_mode_start
 18  
 19  check_multiboot:
 20    cmp eax, 0x36d76289
 21    jne .no_multiboot
 22    ret
 23  .no_multiboot:
 24    mov al, "M"
 25    jmp error
 26  
 27  check_cpuid:
 28    pushfd
 29    pop eax
 30    mov ecx, eax
 31    xor eax, 1 << 21
 32    push eax
 33    popfd
 34    pushfd
 35    pop eax
 36    push ecx
 37    popfd
 38    cmp eax, ecx
 39    je .no_cpuid
 40    ret
 41  .no_cpuid:
 42    mov al, "C"
 43    jmp error
 44  
 45  check_long_mode:
 46    mov eax, 0x80000000
 47    cpuid
 48    cmp eax, 0x80000001
 49    jb .no_long_mode
 50  
 51    mov eax, 0x80000001
 52    cpuid
 53    test edx, 1 << 29
 54    jz .no_long_mode
 55    ret
 56  .no_long_mode:
 57    mov al, "L"
 58    jmp error
 59  
 60  setup_page_tables:
 61    mov eax, page_table_l3
 62    or eax, 0b11 ; present, writable
 63    mov [page_table_l4], eax
 64  
 65    mov eax, page_table_l2
 66    or eax, 0b11 ; present, writable
 67    mov [page_table_l3], eax
 68  
 69    mov ecx, 0 ; counter
 70  .loop:
 71    mov eax, 0x200000 ; 2MiB
 72    mul ecx
 73    or eax, 0b10000011 ; present, writeable, huge page
 74    mov [page_table_l2 + ecx * 8], eax
 75  
 76    inc ecx ; increment counter
 77    cmp cx, 512 ; checks if the whole table is mapped
 78    jne .loop ; if not, continue
 79  
 80    ret
 81  
 82  enable_paging:
 83    ; pass page table location to cpu
 84    mov eax, page_table_l4
 85    mov cr3, eax
 86  
 87    ; enable PAE
 88    mov eax, cr4
 89    or eax, 1 << 5
 90    mov cr4, eax
 91  
 92    ; enable long mode
 93    mov ecx, 0xC0000080
 94    rdmsr
 95    or eax, 1 << 8
 96    wrmsr
 97  
 98    ; enable paging
 99    mov eax, cr0
100    or eax, 1 << 31
101    mov cr0, eax
102  
103    ret
104  
105  error:
106    ; print "ERR: X" where X is the error code
107    mov dword [0xb8000], 0x4f524f45
108    mov dword [0xb8004], 0x4f3a4f52
109    mov dword [0xb8008], 0x4f204f20
110    mov byte [0xb800a], al
111    hlt
112  
113  section .bss
114  align 4096
115  page_table_l4:
116    resb 4096
117  page_table_l3:
118    resb 4096
119  page_table_l2:
120    resb 4096
121  stack_bottom:
122    resb 4096 * 4
123  stack_top:
124  
125  section .rodata
126  gdt64:
127    dq 0 ; zero entry
128  .code_segment: equ $ - gdt64
129    dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment
130  .pointer:
131    dw $ - gdt64 - 1
132    dq gdt64