1 // arch/x86/entry.S - x64 entry points (booting and traps)
3 // This software is copyright (c) 2006 Scott Wood.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
15 #include <arch/addrs.h>
22 .long 0x1badb002 // Multi-boot magic
25 // bit 0: 4KiB-align all boot modules
26 // bit 1: must include memory size and map
27 // bit 2: must include video mode table
28 // bit 16: load addresses in this header are valid
29 // and should be used instead of the ELF header
33 // checksum: -(magic + flags), update if flags change
36 .long multiboot_hdr - KERNEL_START // header_addr
37 .long 0x00200000 // load_addr
38 .long 0 // load_end_addr: load whole file
39 .long bss_end - KERNEL_START // bss_end_addr
40 .long _start - KERNEL_START // entry_addr
44 cmpl $0x2badb002, %eax
47 lgdt x64_gdtr_phys + 6 - KERNEL_START
48 ljmp $0x10, $using_our_gdt - KERNEL_START
58 movl %ebx, %esi // Save the multiboot pointer somewhere
59 // it won't be clobbered by CPUID
61 // This gives 256 bytes to Threads::Thread; if it gets larger
62 // this needs to be updated (as well as the code at high_vaddr).
64 movl $x64_init_stack + 3840 - KERNEL_START, %esp
70 xorl $0x00200000, %eax
79 movl $0x80000000, %eax
81 cmpl $0x80000000, %eax
83 movl $0x80000001, %eax
88 movl $0xc0000080, %ecx // Extended Feature Enable Register (EFER)
90 movl $0x100, %eax // Enable long mode
98 // Set page table attributes
99 orl $7, x64_init_ptbl_l4 - KERNEL_START
100 orl $7, x64_init_ptbl_l3 - KERNEL_START
101 // orl $7, x64_init_ptbl_l2 - KERNEL_START
103 // Load the initial page table
104 movl $x64_init_ptbl_l4 - KERNEL_START, %eax
107 // enable paging, kernel write-protect,
108 // and internal floating point error handling
110 orl $0x80010020, %eax
112 ljmp $0x18, $in_code64 - KERNEL_START
116 // Set up high page tables for 0xffffffff80000000 mapping,
117 // reusing the tables previously used for the low identity
120 movq x64_init_ptbl_l4 - KERNEL_START, %rax
121 movq %rax, x64_init_ptbl_l4 - KERNEL_START + 0xff8
123 movq x64_init_ptbl_l3 - KERNEL_START, %rax
124 movq %rax, x64_init_ptbl_l3 - KERNEL_START + 0xff0
127 movl %esi, x64_boot_info_phys
129 movq $high_vaddr, %rax
133 movq $x64_init_stack + 3840, %rsp
138 movl $no_multiboot_str - KERNEL_START, %esi
141 movl $no_long_mode_str - KERNEL_START, %esi
147 1: movb %al, (%edi, %ecx, 2)
148 movb $14, 1(%edi, %ecx, 2) // It's not at the cursor, so use
149 // yellow to make it stand out.
151 movb (%esi, %ecx), %al
158 .string "This CPU does not support long (64-bit) mode. Use a 32-bit kernel."
161 .string "Unrecognized bootloader; a multiboot-compliant loader is required."
165 .macro pushvolatilesnordi
193 // Non-volatile registers must be pushed if the handler will
194 // need to access all of the interrupted code's registers,
195 // such as when producing an error dump. Does not include
196 // r15, as that is usually swapped with the error code.
250 .global x64_invalid_insn
255 call x64_do_invalid_insn
262 xchgq %r15, (%rsp) // get error code
272 .global x64_page_fault
274 xchgq %r15, (%rsp) // get error code
280 call x64_do_page_fault
288 subq $8, %rsp // Keep the stack frame 16-byte aligned
291 movl need_resched, %eax
301 // The cli is to make sure interrupts don't get re-enabled in
302 // this thread context between the schedule and the ret from
335 .global x64_new_thread
351 call sched_new_thread