loader.s (2377B)
1 /* 32-bit loader stub that GRUB can load */ 2 /* This sets up 64-bit mode and jumps to the 64-bit kernel */ 3 4 /* Multiboot1 header */ 5 .section .multiboot 6 .align 4 7 .long 0x1BADB002 /* magic */ 8 .long 0x00000000 /* flags */ 9 .long -(0x1BADB002 + 0x00000000) /* checksum */ 10 11 .section .bss 12 .align 4096 13 pml4: 14 .skip 4096 15 pdpt: 16 .skip 4096 17 pd: 18 .skip 4096 19 .align 16 20 stack_bottom: 21 .skip 16384 22 stack_top: 23 24 .section .text 25 .code32 26 .global _start 27 _start: 28 /* Set up stack */ 29 mov $stack_top, %esp 30 31 /* Disable interrupts */ 32 cli 33 34 /* Check for long mode support */ 35 mov $0x80000000, %eax 36 cpuid 37 cmp $0x80000001, %eax 38 jb no_long_mode 39 40 mov $0x80000001, %eax 41 cpuid 42 test $(1 << 29), %edx 43 jz no_long_mode 44 45 /* Set up identity paging for first 2MB */ 46 /* PML4[0] -> PDPT */ 47 mov $pdpt, %eax 48 or $0x3, %eax 49 mov %eax, pml4 50 51 /* PDPT[0] -> PD */ 52 mov $pd, %eax 53 or $0x3, %eax 54 mov %eax, pdpt 55 56 /* PD[0] -> 2MB huge page at 0x0 */ 57 mov $0x83, %eax 58 mov %eax, pd 59 60 /* Also map higher half for kernel (identity map first 2GB) */ 61 mov $pd, %edi 62 mov $0x83, %eax 63 mov $512, %ecx 64 1: 65 mov %eax, (%edi) 66 add $0x200000, %eax /* 2MB */ 67 add $8, %edi 68 loop 1b 69 70 /* Load CR3 with PML4 */ 71 mov $pml4, %eax 72 mov %eax, %cr3 73 74 /* Enable PAE */ 75 mov %cr4, %eax 76 or $(1 << 5), %eax 77 mov %eax, %cr4 78 79 /* Enable long mode in EFER MSR */ 80 mov $0xC0000080, %ecx 81 rdmsr 82 or $(1 << 8), %eax 83 wrmsr 84 85 /* Enable paging */ 86 mov %cr0, %eax 87 or $(1 << 31), %eax 88 mov %eax, %cr0 89 90 /* Load GDT */ 91 lgdt gdt64_pointer 92 93 /* Far jump to 64-bit code */ 94 ljmp $0x08, $long_mode_start 95 96 no_long_mode: 97 /* Hang */ 98 cli 99 1: hlt 100 jmp 1b 101 102 .code64 103 long_mode_start: 104 /* Set up segments */ 105 mov $0x10, %ax 106 mov %ax, %ds 107 mov %ax, %es 108 mov %ax, %fs 109 mov %ax, %gs 110 mov %ax, %ss 111 112 /* Set up stack */ 113 mov $stack_top, %rsp 114 115 /* Call the external kernel_main */ 116 call kernel_main 117 118 /* Hang */ 119 cli 120 1: hlt 121 jmp 1b 122 123 /* GDT for 64-bit mode */ 124 .align 16 125 gdt64: 126 .quad 0x0000000000000000 /* Null */ 127 .quad 0x00AF9A000000FFFF /* Code segment (64-bit) */ 128 .quad 0x00CF92000000FFFF /* Data segment */ 129 gdt64_pointer: 130 .word gdt64_pointer - gdt64 - 1 131 .quad gdt64