.set PG_PRESENT, 1<<0 .set PG_READ_WRITE, 1<<1 .set PG_PAGE_SIZE, 1<<7 #define KERNEL_OFFSET 0xFFFFFFFF80000000 #define V2P(vaddr) ((vaddr) - KERNEL_OFFSET) .code32 # multiboot2 header .section .multiboot, "aw" multiboot2_start: .align 8 .long 0xE85250D6 .long 0 .long multiboot2_end - multiboot2_start .long -(0xE85250D6 + (multiboot2_end - multiboot2_start)) # framebuffer tag .align 8 .short 5 .short 0 .long 20 .long 1920 .long 1080 .long 32 # legacy start .align 8 .short 3 .short 0 .long 12 .long V2P(_start) .align 8 .short 0 .short 0 .long 8 multiboot2_end: .section .bss, "aw", @nobits # Create stack .global g_boot_stack_bottom g_boot_stack_bottom: .skip 16384 .global g_boot_stack_top g_boot_stack_top: .global g_kernel_cmdline g_kernel_cmdline: .skip 4096 .global g_multiboot2_info g_multiboot2_info: .skip 8 .global g_multiboot2_magic g_multiboot2_magic: .skip 8 .section .data # Map first GiB to 0x00000000 and 0xFFFFFFFF80000000 .align 4096 boot_pml4: .quad V2P(boot_pdpt_lo) + (PG_READ_WRITE | PG_PRESENT) .rept 510 .quad 0 .endr .quad V2P(boot_pdpt_hi) + (PG_READ_WRITE | PG_PRESENT) boot_pdpt_lo: .quad V2P(boot_pd) + (PG_READ_WRITE | PG_PRESENT) .rept 511 .quad 0 .endr boot_pdpt_hi: .rept 510 .quad 0 .endr .quad V2P(boot_pd) + (PG_READ_WRITE | PG_PRESENT) .quad 0 boot_pd: .set i, 0 .rept 512 .quad i + (PG_PAGE_SIZE | PG_READ_WRITE | PG_PRESENT) .set i, i + 0x200000 .endr boot_gdt: .quad 0x0000000000000000 # null descriptor .quad 0x00AF9A000000FFFF # kernel code .quad 0x00AF92000000FFFF # kernel data boot_gdtr: .short . - boot_gdt - 1 .quad V2P(boot_gdt) .section .text has_cpuid: pushfl pushfl xorl $0x00200000, (%esp) popfl pushfl popl %eax xorl (%esp), %eax popfl testl $0x00200000, %eax ret is_64_bit: movl $0x80000000, %eax cpuid cmpl $0x80000001, %eax jl .no_extension movl $0x80000001, %eax cpuid testl $(1 << 29), %edx ret .no_extension: cmpl %eax, %eax ret check_requirements: call has_cpuid jz .exit call is_64_bit jz .exit ret .exit: jmp system_halt enable_sse: movl %cr0, %eax andw $0xFFFB, %ax orw $0x0002, %ax movl %eax, %cr0 movl %cr4, %eax orw $0x0600, %ax movl %eax, %cr4 ret initialize_paging: # enable PAE movl %cr4, %ecx orl $0x20, %ecx movl %ecx, %cr4 # set long mode enable bit movl $0x100, %eax movl $0x000, %edx movl $0xC0000080, %ecx wrmsr # set address of paging structures movl $V2P(boot_pml4), %ecx movl %ecx, %cr3 # enable paging movl %cr0, %ecx orl $0x80000000, %ecx movl %ecx, %cr0 ret .global _start .type _start, @function _start: # Initialize stack and multiboot info movl $V2P(g_boot_stack_top), %esp movl %eax, V2P(g_multiboot2_magic) movl %ebx, V2P(g_multiboot2_info) call check_requirements call enable_sse call initialize_paging # flush gdt and jump to 64 bit lgdt V2P(boot_gdtr) ljmpl $0x08, $V2P(long_mode) .code64 long_mode: movw $0x10, %ax movw %ax, %ss # clear segment registers (unused in x86_64?) movw $0x00, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs # jump to higher half movq $g_boot_stack_top, %rsp movabsq $higher_half, %rcx jmp *%rcx higher_half: # call global constuctors call _init # call to the kernel itself (clear ebp for stacktrace) xorq %rbp, %rbp call kernel_main # call global destructors call _fini system_halt: xchgw %bx, %bx cli 1: hlt jmp 1b