#include <comus/limits.h> .globl _start .globl kernel_pml4 .globl kernel_pdpt_0 .globl kernel_pd_0 .globl kernel_pd_0_ents .globl kernel_pd_1 .globl paging_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: .skip 4096 kernel_pdpt_0: .skip 4096 kernel_pd_0: .skip 4096 kernel_pd_0_ents: .skip (4096*N_IDENT_PTS) kernel_pd_1: .skip 4096 paging_pt: .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 # setup kernel paging structures movl $kernel_pml4, %edi # zero out pml4 movl %edi, %cr3 xorl %eax, %eax movl $0x1000, %ecx rep stosl movl %cr3, %edi movl $kernel_pdpt_0 + 3, (%edi) # map pdpt movl $kernel_pdpt_0, %edi movl $kernel_pd_0 + 3, (%edi) # map pd 0 addl $8, %edi # map pd 1 movl $kernel_pd_1 + 3, (%edi) movl $kernel_pd_0, %edi # map pd 0 ents movl $kernel_pd_0_ents + 3, %ebx movl $N_IDENT_PTS, %ecx _start.map_pd_0: movl %ebx, (%edi) addl $(8 * 512), %ebx addl $8, %edi loop _start.map_pd_0 movl $kernel_pd_0_ents, %edi # identity map kernel movl $0x03, %ebx movl $(512 * N_IDENT_PTS), %ecx _start.map_pd_0_ents: movl %ebx, (%edi) addl $0x1000, %ebx addl $8, %edi loop _start.map_pd_0_ents # 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 _start_efi: # disable interrupts cli # setup stack movq $kern_stack_end, %rsp movq $kern_stack_end, %rbp # save multiboot pushq %rbx pushq %rax # load gdt lgdt GDT.Pointer pushq $GDT.Code pushq $code64 retfq code64: # set segment registers movw $GDT.Data, %dx movw %dx, %ds movw %dx, %es movw %dx, %fs movw %dx, %gs movw %dx, %ss # set ebp to 0 so we know where to end stack traces xorq %rbp, %rbp # pop multiboot header pop %rdi pop %rsi call main halt: cli hlt jmp halt