]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/arch/x64/entry.S
License change.
[polintos/scott/priv.git] / kernel / arch / x64 / entry.S
1 // arch/x86/entry.S - x64 entry points (booting and traps)
2 //
3 // This software is copyright (c) 2006 Scott Wood.
4 // 
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.
8 // 
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.
14
15 #include <arch/addrs.h>
16
17         .org 0
18         .code32
19         .global _start
20 .align  4
21 multiboot_hdr:
22         .long   0x1badb002              // Multi-boot magic
23         
24         // Multi-boot flags:
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
30
31         .long   0x00010003
32
33         // checksum: -(magic + flags), update if flags change
34         .long   0xe4514ffb
35
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
41
42 _start:
43         cld
44         cmpl    $0x2badb002, %eax
45         bne     no_multiboot
46         
47         lgdt    x64_gdtr_phys + 6 - KERNEL_START
48         ljmp    $0x10, $using_our_gdt - KERNEL_START
49
50 using_our_gdt:
51         movw    $0x08, %ax
52         movw    %ax, %ds
53         movw    %ax, %es
54         movw    %ax, %fs
55         movw    %ax, %gs
56         movw    %ax, %ss
57         
58         movl    %ebx, %esi              // Save the multiboot pointer somewhere
59                                         // it won't be clobbered by CPUID
60
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).
63
64         movl    $x64_init_stack + 3840 - KERNEL_START, %esp
65         
66         // Test for CPUID
67         pushfl
68         popl    %eax
69         movl    %eax, %ebx
70         xorl    $0x00200000, %eax
71         pushl   %eax
72         popfl
73         pushfl
74         popl    %eax
75         cmpl    %eax, %ebx
76         je      no_long_mode
77
78         // Test for long mode
79         movl    $0x80000000, %eax
80         cpuid
81         cmpl    $0x80000000, %eax
82         jbe     no_long_mode
83         movl    $0x80000001, %eax
84         cpuid
85         btl     $29, %edx
86         jnc     no_long_mode
87
88         movl    $0xc0000080, %ecx       // Extended Feature Enable Register (EFER)
89         xorl    %edx, %edx
90         movl    $0x100, %eax            // Enable long mode
91         wrmsr
92         
93         // enable PAE
94         movl    %cr4, %eax
95         btsl    $5, %eax
96         movl    %eax, %cr4
97
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
102         
103         // Load the initial page table
104         movl    $x64_init_ptbl_l4 - KERNEL_START, %eax
105         movl    %eax, %cr3
106         
107         // enable paging, kernel write-protect, 
108         // and internal floating point error handling
109         movl    %cr0, %eax
110         orl     $0x80010020, %eax
111         movl    %eax, %cr0
112         ljmp    $0x18, $in_code64 - KERNEL_START
113
114         .code64
115 in_code64:
116         // Set up high page tables for 0xffffffff80000000 mapping,
117         // reusing the tables previously used for the low identity
118         // mapping.
119         
120         movq    x64_init_ptbl_l4 - KERNEL_START, %rax
121         movq    %rax, x64_init_ptbl_l4 - KERNEL_START + 0xff8
122         
123         movq    x64_init_ptbl_l3 - KERNEL_START, %rax
124         movq    %rax, x64_init_ptbl_l3 - KERNEL_START + 0xff0
125         
126         lgdt    x64_gdtr + 6
127         movl    %esi, x64_boot_info_phys
128         
129         movq    $high_vaddr, %rax
130         jmp     *%rax
131
132 high_vaddr:
133         movq    $x64_init_stack + 3840, %rsp
134         jmp     start_kernel
135
136         .code32
137 no_multiboot:
138         movl    $no_multiboot_str - KERNEL_START, %esi
139         jmp     do_print
140 no_long_mode:
141         movl    $no_long_mode_str - KERNEL_START, %esi
142 do_print:
143         movl    $0xb8000, %edi
144         
145         movb    (%esi), %al
146         xorl    %ecx, %ecx
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.
150         incl    %ecx
151         movb    (%esi, %ecx), %al
152         testb   %al, %al
153         jnz     1b
154
155 2:      jmp     2b
156         
157 no_long_mode_str:
158         .string "This CPU does not support long (64-bit) mode.  Use a 32-bit kernel."
159
160 no_multiboot_str:
161         .string "Unrecognized bootloader; a multiboot-compliant loader is required."
162
163         .code64
164         
165         .macro  pushvolatilesnordi
166         push    %rax
167         push    %rcx
168         push    %rdx
169         push    %rsi
170         push    %r8
171         push    %r9
172         push    %r10
173         push    %r11
174         .endm
175
176         .macro  pushvolatiles
177         push    %rax
178         pushvolatilesnordi
179         .endm
180         
181         .macro  popvolatiles
182         pop     %r11
183         pop     %r10
184         pop     %r9
185         pop     %r8
186         pop     %rsi
187         pop     %rdx
188         pop     %rcx
189         pop     %rax
190         pop     %rdi
191         .endm
192
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.
197         
198         .macro  pushall
199         push    %r14
200         push    %r13
201         push    %r12
202         push    %r11
203         push    %r10
204         push    %r9
205         push    %r8
206         push    %rdi
207         push    %rsi
208         push    %rbp
209         push    %rsp
210         push    %rbx
211         push    %rdx
212         push    %rcx
213         push    %rax
214         .endm
215
216         .macro  pushallnoerr
217         push    %r15
218         pushall
219         .endm
220         
221         .macro  popall
222         pop     %rax
223         pop     %rcx
224         pop     %rdx
225         pop     %rbx
226         addq    $8, %rsp
227         pop     %rbp
228         pop     %rsi
229         pop     %rdi
230         pop     %r8
231         pop     %r9
232         pop     %r10
233         pop     %r11
234         pop     %r12
235         pop     %r13
236         pop     %r14
237         pop     %r15
238         .endm
239         
240         .global x64_diverr
241 x64_diverr:
242         pushallnoerr
243
244         movq    %rsp, %rdi
245         call    x64_do_diverr
246
247         popall
248         iretq
249
250         .global x64_invalid_insn
251 x64_invalid_insn:
252         pushallnoerr
253
254         movq    %rsp, %rdi
255         call    x64_do_invalid_insn
256
257         popall
258         iretq
259
260         .global x64_gpf
261 x64_gpf:
262         xchgq   %r15, (%rsp)    // get error code
263         pushall
264         
265         movq    %rsp, %rdi
266         movq    %r15, %rsi
267         call    x64_do_gpf
268         
269         popall
270         iretq
271
272         .global x64_page_fault
273 x64_page_fault:
274         xchgq   %r15, (%rsp)    // get error code
275         pushall
276         
277         movq    %rsp, %rdi
278         movq    %cr2, %rsi
279         movq    %r15, %rdx
280         call    x64_do_page_fault
281         
282         popall
283         iretq
284
285         .global x64_irq
286 x64_irq:
287         pushvolatilesnordi
288         subq    $8, %rsp        // Keep the stack frame 16-byte aligned
289         
290         call    x64_do_irq
291         movl    need_resched, %eax
292         testl   %eax, %eax
293         jnz     x64_reschedule
294
295 x64_ret_irq:
296         addq    $8, %rsp
297         popvolatiles
298         iretq
299
300 x64_reschedule:
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
303         // IRQ.
304         
305         cli     
306         call    schedule
307         jmp     x64_ret_irq
308         
309         .section ".irqs","x"
310         .global x64_irqs
311 x64_irqs:
312         .text
313
314         .macro  irq from,to
315 1:      push    %rdi
316         movq    $\from, %rdi
317         jmp     x64_irq
318         .section ".irqs","x"
319         .quad   1b
320         .text
321         .if     \to-\from
322         irq     (\from+1),\to
323         .endif
324         .endm
325         
326         .macro  irq16 from,to
327         irq     \from,(\from+15)
328         .if     \to-\from
329         irq16   (\from+16),\to
330         .endif
331         .endm
332
333         irq16   0,240
334
335         .global x64_new_thread
336 x64_new_thread:
337         xorq    %rax, %rax
338         xorq    %rbx, %rbx
339         xorq    %rcx, %rcx
340         xorq    %rdx, %rdx
341         xorq    %rbp, %rbp
342         xorq    %r8, %r8
343         xorq    %r9, %r9
344         xorq    %r10, %r10
345         xorq    %r11, %r11
346         xorq    %r12, %r12
347         xorq    %r13, %r13
348         xorq    %r14, %r14
349         xorq    %r15, %r15
350         
351         call    sched_new_thread
352         pop     %rsi
353         pop     %rdi
354         call    *%rsi
355         call    exit_thread
356         ud2a