.globl _start .globl kernel_pml4 .globl kernel_pdpt_0 .globl kernel_pd_0 .globl kernel_pt_0 .globl paging_pt .globl bootstrap_pt .extern main .extern GDT .section .multiboot # multiboot header mb_start: # magic .align 8 .long 0xe85250d6 .long 0 .long mb_end - mb_start .long 0x100000000 - (0xe85250d6 + (mb_end - mb_start)) # info request .align 8 .short 1 .short 1 .long 36 .long 1 # cmdline .long 6 # mmap .long 9 # elf section .long 12 # efi64 .long 14 # rsdp .long 15 # xsdp .long 20 # efi64 IH # bios entry .align 8 .short 3 .short 0 .long 12 .long _start # framebuffer .align 8 .short 5 .short 1 .long 20 .long 720 # width .long 480 # height .long 32 # bpp # efi boot services .align 8 .short 7 .short 0 .long 8 # efi amd64 entry .align 8 .short 9 .short 0 .long 12 .long _start_efi # null .align 8 .short 0 .short 0 .long 8 mb_end: .section .bss # kernel page tables .align 4096 kernel_pml4: # reserve memory for initial 512 pml4 entires .skip 4096 kernel_pdpt_0: # reserve memory for initial 512 pdpt entires .skip 4096 kernel_pd_0: # reserve memory for initial 512 pd entries .skip 4096 kernel_pt_0: # reserve memory for initial 512 pt entries .skip 4096 paging_pt: # reserve pages for pager mappings .skip 4096 bootstrap_pt: # reserve pages to bootstrap pager .skip 4096 # kernel stack .align 16 kern_stack_start: .skip 8192 kern_stack_end: .section .data .align 16 # access bits .set PRESENT, 1 << 7 .set NOT_SYS, 1 << 4 .set EXEC, 1 << 3 .set DC, 1 << 2 .set RW, 1 << 1 .set ACCESSED, 1 << 0 # privlage level (access bit) .set RING0, 0 << 5 .set RING1, 1 << 5 .set RING2, 2 << 5 .set RING3, 3 << 5 # flag bits .set GRAN_4K, 1 << 7 .set SZ_32, 1 << 6 .set LONG_MODE, 1 << 5 # kernel gdt (long mode) GDT: # Null Segment (0x00) .equ GDT.Null, . - GDT .quad 0 # Kernel Code segment (0x08) .equ GDT.Code, . - GDT .long 0xFFFF .byte 0 .byte PRESENT | NOT_SYS | EXEC | RW | RING0 .byte GRAN_4K | LONG_MODE | 0xF .byte 0 # Kernel Data segment (0x10) .equ GDT.Data, . - GDT .long 0xFFFF .byte 0 .byte PRESENT | NOT_SYS | RW | RING0 .byte GRAN_4K | SZ_32 | 0xF .byte 0 # User Code Segment (0x18) .equ GDT.UserCode, . - GDT .long 0xFFFF .byte 0 .byte PRESENT | NOT_SYS | EXEC | RW | RING3 .byte GRAN_4K | LONG_MODE | 0xF .byte 0 # User Data Segment (0x20) .equ GDT.UserData, . - GDT .long 0xFFFF .byte 0 .byte PRESENT | NOT_SYS | RW | RING3 .byte GRAN_4K | SZ_32 | 0xF .byte 0 # TSS segment (0x28) .equ GDT.TSS, . - GDT .quad 0 # to be modified in kernel # GDT Pointer .equ GDT.Pointer, . .word . - GDT - 1 .quad GDT .section .text .code32 _start: # disable interrupts cli # setup stack movl $kern_stack_end, %esp movl $kern_stack_end, %ebp # save multiboot (if using multiboot) pushl $0 push %ebx pushl $0 push %eax # zero out kernel page table movl $kernel_pml4, %edi movl %edi, %cr3 xorl %eax, %eax movl $4096, %ecx # zero 4096 pages rep stosl movl %cr3, %edi # identity map kernel movl $kernel_pdpt_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x2003. movl $kernel_pdpt_0, %edi # Add 0x1000 to the desination index. movl $kernel_pd_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x3003. movl $kernel_pd_0, %edi # Add 0x1000 to the desination index. movl $kernel_pt_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x4003. movl $kernel_pt_0, %edi # Add 0x1000 to the desination index. movl $0x03, %ebx # Entry value to set movl $512, %ecx # Loop count _start.SetEntry: # set entires in mapping movl %ebx, (%edi) # Set the uint32_t at the desination index to the B-register addl $0x1000, %ebx # Add 0x1000 to the B-register addl $8, %edi # Add eight to the desination index loop _start.SetEntry # enable page address extension movl %cr4, %eax orl $(1 << 5), %eax movl %eax, %cr4 # enable long mode movl $0xC0000080, %ecx rdmsr orl $(1 << 8), %eax wrmsr # enable paging movl %cr0, %eax orl $(1 << 31), %eax movl %eax, %cr0 # load gdt lgdt GDT.Pointer ljmp $GDT.Code, $code64 .code64 code64: movw $GDT.Data, %dx # set segment registers movw %dx, %ds movw %dx, %ss xorq %rbp, %rbp # set ebp to 0 so we know where to end stack traces pop %rdi # pop possible multiboot header pop %rsi call main jmp halt _start_efi: # disable interrupts cli # setup stack movq $kern_stack_end, %rsp movq $kern_stack_end, %rbp # load gdt lgdt GDT.Pointer # set segment registers movw $GDT.Code, %dx movw %dx, %cs movw %dx, %es movw $GDT.Data, %dx movw %dx, %ds movw %dx, %ss xorq %rbp, %rbp # set ebp to 0 so we know where to end stack traces movq %rax, %rdi movq %rbx, %rsi call main jmp halt halt: cli hlt jmp halt