<commit_before>; entrypoint from bootloader into kernel

global start

section .text
bits 32

; fn start()
;   setup stack, check system, setup paging, call into rust
start:
   mov esp, stack_top
   call clear

   call check_multiboot
   call check_cpuid
   call check_long_mode

   call mezzo
   hlt

; fn clear()
;   clear text from the first line
clear:
   mov dword [0xb8000], 0x00000000
   mov dword [0xb8004], 0x00000000
   mov dword [0xb8008], 0x00000000
   mov dword [0xb800c], 0x00000000
   mov dword [0xb8010], 0x00000000
   mov dword [0xb8014], 0x00000000
   mov dword [0xb8018], 0x00000000
   mov dword [0xb801c], 0x00000000
   mov dword [0xb8020], 0x00000000
   ret

; fn mezzo()
;   print '(mezzo)' and halt
mezzo:
   mov dword [0xb80a4], 0x096d0728
   mov dword [0xb80a8], 0x097a0965
   mov dword [0xb80ac], 0x096f097a
   mov dword [0xb80b0], 0x00000729
   ret

; fn error(err)
;   print 'ERROR:' with ascii code from ax and halt
error:
   mov dword [0xb80a4], 0x0c520c45
   mov dword [0xb80a8], 0x0c4f0c52
   mov dword [0xb80ac], 0x073a0c52
   mov dword [0xb80b0], 0x07200720
   mov dword [0xb80b4], 0x07200720
   or  byte  [0xb80b2], al
   or  byte  [0xb80b4], ah
   hlt

; fn check_multiboot()
;   verify that we were entered from a multiboot compliant loader
check_multiboot:
   cmp eax, 0x36d76289
   jne .no_multiboot
   ret

   .no_multiboot:
      mov ax, '01'
      jmp error

; fn check_cpuid()
;   verify that cpuid is supported (that we can flip flags bit 21)
check_cpuid:
   pushfd              ; copy flags to eax via stack
   pop eax             ;
   mov ecx, eax        ;   ...and also to ecx

   xor eax, 1 << 21    ; flip cpuid bit

   push eax            ; copy modified eax into flags
   popfd
   pushfd              ;   ...and back out again
   pop eax

   push ecx            ; restore original flags
   popfd

   cmp eax, ecx        ; compare original and modified flags
   je .no_cpuid
   ret

   .no_cpuid:
      mov ax, '02'
      jmp error

; fn check_long_mode()
;   verify that processor supports long mode
check_long_mode:
   mov eax, 0x80000000 ; cpuid: return highest function supported
   cpuid
   cmp eax, 0x80000001
   jb .no_long_mode

   mov eax, 0x80000001 ; cpuid: return extended processor features
   cpuid
   test edx, 1 << 29
   jz .no_long_mode
   ret

   .no_long_mode:
      mov ax, '03'
      jmp error

section .bss
stack_bottom:
   resb 64
stack_top:<commit_msg>setup identity mapped paging tables<commit_after>; entrypoint from bootloader into kernel

global start

section .text
bits 32

; fn start()
;   setup stack, check system, setup paging, call into rust
start:
   mov esp, stack_top
   call clear

   call check_multiboot
   call check_cpuid
   call check_long_mode

   call setup_paging_tables
   call enable_paging

   call mezzo
   hlt

; fn clear()
;   clear text from the first line
clear:
   mov dword [0xb8000], 0x00000000
   mov dword [0xb8004], 0x00000000
   mov dword [0xb8008], 0x00000000
   mov dword [0xb800c], 0x00000000
   mov dword [0xb8010], 0x00000000
   mov dword [0xb8014], 0x00000000
   mov dword [0xb8018], 0x00000000
   mov dword [0xb801c], 0x00000000
   mov dword [0xb8020], 0x00000000
   ret

; fn mezzo()
;   print '(mezzo)' and halt
mezzo:
   mov dword [0xb80a4], 0x096d0728
   mov dword [0xb80a8], 0x097a0965
   mov dword [0xb80ac], 0x096f097a
   mov dword [0xb80b0], 0x00000729
   ret

; fn error(err)
;   print 'ERROR:' with ascii code from ax and halt
error:
   mov dword [0xb80a4], 0x0c520c45
   mov dword [0xb80a8], 0x0c4f0c52
   mov dword [0xb80ac], 0x073a0c52
   mov dword [0xb80b0], 0x07200720
   mov dword [0xb80b4], 0x07200720
   or  byte  [0xb80b2], al
   or  byte  [0xb80b4], ah
   hlt

; fn check_multiboot()
;   verify that we were entered from a multiboot compliant loader
check_multiboot:
   cmp eax, 0x36d76289
   jne .no_multiboot
   ret

   .no_multiboot:
      mov ax, '01'
      jmp error

; fn check_cpuid()
;   verify that cpuid is supported (that we can flip flags bit 21)
check_cpuid:
   pushfd              ; copy flags to eax via stack
   pop eax             ;
   mov ecx, eax        ;   ...and also to ecx

   xor eax, 1 << 21    ; flip cpuid bit

   push eax            ; copy modified eax into flags
   popfd
   pushfd              ;   ...and back out again
   pop eax

   push ecx            ; restore original flags
   popfd

   cmp eax, ecx        ; compare original and modified flags
   je .no_cpuid
   ret

   .no_cpuid:
      mov ax, '02'
      jmp error

; fn check_long_mode()
;   verify that processor supports long mode
check_long_mode:
   mov eax, 0x80000000 ; cpuid: return highest function supported
   cpuid
   cmp eax, 0x80000001
   jb .no_long_mode

   mov eax, 0x80000001 ; cpuid: return extended processor features
   cpuid
   test edx, 1 << 29
   jz .no_long_mode
   ret

   .no_long_mode:
      mov ax, '03'
      jmp error

; fn setup_paging_tables()
;   map p4 -> p3 -> p2 -> physical
setup_paging_tables:
   mov eax, p3_table   ; mark p3 as writable and present, and
   or  eax, 0b11       ; add it as the first entry in p4
   mov [p4_table], eax ;

   mov eax, p2_table   ; the same for p2 in p3
   or  eax, 0b11       ;
   mov [p3_table], eax ;

   ; identity map each p2 entry as a 2mib frame (512 * 2mib = 1gib)
   mov ecx, 0x0
   .map_p2_entries:
      mov eax, 0x200000
      mul ecx
      or  eax, 0x83    ; huge + writable + present
      mov [p2_table + (ecx * 8)], eax

      inc ecx
      cmp ecx, 512
      jb  .map_p2_entries

   ret

; fn enable_paging()
;   set various bits to enter long mode and enable paging
enable_paging:
   ; map cr3 to p4 paging table
   mov eax, p4_table
   mov cr3, eax

   ; set "physical address extended" bit of cr4
   mov eax, cr4
   or  eax, 1 << 5
   mov cr4, eax

   ; set "long mode" bit of "extended feature enable register"
   mov ecx, 0xC0000080
   rdmsr
   or eax, 1 << 8
   wrmsr

   ; set "paging" bit in the cr0 register
   mov eax, cr0
   or eax, 1 << 31
   mov cr0, eax

   ret

section .bss
align 4096

p4_table:
   resb 4096
p3_table:
   resb 4096
p2_table:
   resb 4096

stack_bottom:
   resb 64
stack_top:
{'fraction_non_alphanumeric': 0.0679516497876511, 'fraction_numerical': 0.10862463247304803, 'mean_word_length': 2.512908777969019, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 20, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7215231', 'n_tokens_mistral': 2775, 'n_tokens_neox': 2299, 'n_words': 785}