]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/arch/x86/entry.S
Initial checkin from Perforce.
[polintos/scott/priv.git] / kernel / arch / x86 / entry.S
1 // arch/x86/entry.S - x86 entry points (booting and traps)
2 //
3 // This software is copyright (c) 2006 Scott Wood.
4 // 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following conditions:
11 // 
12 //     * Redistributions of source code must retain the above copyright notice,
13 //       this list of conditions and the following disclaimers.
14 // 
15 //     * Redistributions in binary form must reproduce the above copyright notice,
16 //       this list of conditions and the following disclaimers in the
17 //       documentation and/or other materials provided with the distribution.
18 // 
19 //     * The names of the Software's authors and/or contributors
20 //       may not be used to endorse or promote products derived from
21 //       this Software without specific prior written permission.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
29 // SOFTWARE.
30
31 #include <arch/addrs.h>
32
33         .org 0
34         .code32
35         .global _start
36 .align  4
37 multiboot_hdr:
38         .long   0x1badb002              // Multi-boot magic
39         
40         // Multi-boot flags:
41         //  bit 0: 4KiB-align all boot modules
42         //  bit 1: must include memory size and map
43         //  bit 2: must include video mode table
44         //  bit 16: load addresses in this header are valid
45         //          and should be used instead of the ELF header
46
47         .long   0x00010003
48
49         // checksum: -(magic + flags), update if flags change
50         .long   0xe4514ffb
51
52         .long   multiboot_hdr - KERNEL_START    // header_addr
53         .long   0x00200000                      // load_addr
54         .long   0                               // load_end_addr: load whole file
55         .long   bss_end - KERNEL_START          // bss_end_addr
56         .long   _start - KERNEL_START           // entry_addr
57
58 _start:
59         cld
60         lgdt    x86_gdtr_phys + 6 - KERNEL_START
61         ljmp    $0x10, $using_our_gdt - KERNEL_START
62
63 using_our_gdt:
64         movw    $0x08, %ax
65         movw    %ax, %ds
66         movw    %ax, %es
67         movw    %ax, %fs
68         movw    %ax, %gs
69         movw    %ax, %ss
70         
71         movl    %ebx, %esi              // Save the multiboot pointer somewhere
72                                         // it won't be clobbered by CPUID
73         
74         // This gives 512 bytes to Threads::Thread; if it gets larger
75         // this needs to be updated (as well as the code at high_vaddr).
76
77         movl    $x86_init_stack + 3584 - KERNEL_START, %esp
78
79         // Test for CPUID
80         pushfl
81         popl    %eax
82         movl    %eax, %ebx
83         xorl    $0x00200000, %eax
84         pushl   %eax
85         popfl
86         pushfl
87         popl    %eax
88         cmpl    %eax, %ebx
89         je      no_pentium
90
91         // Test for Page Size Extensions
92         xorl    %eax, %eax
93         cpuid
94         cmpl    $1, %eax
95         jb      no_pentium
96         
97         movl    $1, %eax
98         cpuid
99         btl     $3, %edx
100         jnc     no_pentium
101         
102         // enable PSE
103         movl    %cr4, %eax
104         btsl    $4, %eax
105         movl    %eax, %cr4
106         
107         // Load the initial page table
108         movl    $x86_init_ptbl_l2 - KERNEL_START, %eax
109         movl    %eax, %cr3
110         
111         // enable paging, kernel write-protect, 
112         // and internal floating point error handling
113         movl    %cr0, %eax
114         orl     $0x80010020, %eax
115         movl    %eax, %cr0
116
117         // Set up high page tables for 0x80000000 mapping,
118         
119         movl    $0x87, x86_init_ptbl_l2 + 0x800 - KERNEL_START
120         ljmp    $0x10, $paging_on - KERNEL_START
121
122 paging_on:      
123         lgdt    x86_gdtr + 6
124         movl    %esi, x86_boot_info_phys
125         
126         movl    $high_vaddr, %eax
127         jmp     *%eax
128
129 high_vaddr:
130         movl    $x86_init_stack + 3584, %esp
131         jmp     start_kernel
132
133 no_multiboot:
134         movl    $no_multiboot_str - KERNEL_START, %esi
135         jmp     do_print
136 no_pentium:
137         movl    $no_pentium_str - KERNEL_START, %esi
138 do_print:
139         movl    $0xb8000, %edi
140         
141         movb    (%esi), %al
142         xorl    %ecx, %ecx
143 1:      movb    %al, (%edi, %ecx, 2)
144         movb    $14, 1(%edi, %ecx, 2)   // It's not at the cursor, so use
145                                         // yellow to make it stand out.
146         incl    %ecx
147         movb    (%esi, %ecx), %al
148         testb   %al, %al
149         jnz     1b
150
151 2:      jmp     2b
152         
153 no_pentium_str:
154         .string "This kernel requires a Pentium-compatible CPU.  Either CPUID or PSE is missing."
155
156 no_multiboot_str:
157         .string "Unrecognized bootloader; a multiboot-compliant loader is required."
158         
159         .macro  pushvolatilesnoeax
160         pushl   %ecx
161         pushl   %edx
162         .endm
163         
164         .macro  pushvolatiles
165         pushl   %eax
166         pushvolatilesnoeax
167         .endm
168
169         .macro  popvolatiles
170         popl    %edx
171         popl    %ecx
172         popl    %eax
173         .endm
174
175         // Non-volatile registers must be pushed if the handler will
176         // need to access all of the interrupted code's registers,
177         // such as when producing an error dump.  Does not include
178         // edi, as that is usually swapped with the error code.
179         
180         .macro  pushall
181         pushl   %esi
182         pushl   %ebp
183         pushl   %esp
184         pushl   %ebx
185         pushl   %edx
186         pushl   %ecx
187         pushl   %eax
188         .endm
189         
190         .macro  pushallnoerr
191         pushl   %edi
192         pushall
193         .endm
194
195         .macro  popall
196         popl    %eax
197         popl    %ecx
198         popl    %edx
199         popl    %ebx
200         addl    $4, %esp
201         popl    %ebp
202         popl    %esi
203         popl    %edi
204         .endm
205         
206         .global x86_diverr
207 x86_diverr:
208         pushallnoerr
209
210         pushl   %esp
211         call    x86_do_diverr
212         addl    $4, %esp
213
214         popall
215         iret
216
217         .global x86_debug
218 x86_debug:
219         pushallnoerr
220
221         pushl   %esp
222         call    x86_do_debug
223         addl    $4, %esp
224
225         popall
226         iret
227         
228         .global x86_breakpoint
229 x86_breakpoint:
230         pushallnoerr
231
232         pushl   %esp
233         call    x86_do_breakpoint
234         addl    $4, %esp
235
236         popall
237         iret
238
239         .global x86_invalid_insn
240 x86_invalid_insn:
241         pushallnoerr
242
243         pushl   %esp
244         call    x86_do_invalid_insn
245         addl    $4, %esp
246
247         popall
248         iret
249
250         .global x86_gpf
251 x86_gpf:
252         xchgl   %edi, (%esp)    // get error code
253         pushall
254         
255         movl    %esp, %eax
256         pushl   %edi
257         pushl   %eax
258         call    x86_do_gpf
259         addl    $8, %esp
260         
261         popall
262         iret
263
264         .global x86_page_fault
265 x86_page_fault:
266         xchgl   %edi, (%esp)    // get error code
267         pushall
268         
269         movl    %esp, %ecx
270         movl    %cr2, %eax
271         pushl   %edi
272         pushl   %eax
273         pushl   %ecx
274         call    x86_do_page_fault
275         addl    $12, %esp
276         
277         popall
278         iret
279
280         .global x86_int99_entry
281 x86_int99_entry:
282         pushl   %edx
283         pushl   4(%esp)
284         pushl   %edx
285         pushl   %ecx
286         pushl   %eax
287         call    invoke_method
288         addl    $16, %esp
289         xorl    %ecx, %ecx
290         popl    %edx
291         iret
292
293         .global x86_irq
294 x86_irq:
295         pushvolatilesnoeax
296
297         pushl   %eax
298         call    x86_do_irq
299         addl    $4, %esp
300
301         movl    need_resched, %eax
302         testl   %eax, %eax
303         jnz     x86_reschedule
304
305 x86_ret_irq:
306         popvolatiles
307         iret
308
309 x86_reschedule:
310         // The cli is to make sure interrupts don't get re-enabled in
311         // this thread context between the schedule and the ret from
312         // IRQ.
313         
314         cli     
315         call    schedule
316         jmp     x86_ret_irq
317         
318         .section ".irqs","x"
319         .global x86_irqs
320 x86_irqs:
321         .text
322
323         .macro  irq from,to
324 1:      pushl   %eax
325         movl    $\from, %eax
326         jmp     x86_irq
327         .section ".irqs","x"
328         .long   1b
329         .text
330         .if     \to-\from
331         irq     (\from+1),\to
332         .endif
333         .endm
334         
335         .macro  irq16 from,to
336         irq     \from,(\from+15)
337         .if     \to-\from
338         irq16   (\from+16),\to
339         .endif
340         .endm
341
342         irq16   0,240
343
344         .global x86_new_thread
345 x86_new_thread:
346         xorl    %ebx, %ebx
347         xorl    %ecx, %ecx
348         xorl    %edx, %edx
349         xorl    %ebp, %ebp
350         xorl    %esi, %esi
351         xorl    %edi, %edi
352         
353         call    sched_new_thread
354         pop     %eax
355         call    *%eax
356         call    exit_thread
357         ud2a
358
359         .section ".roshared","x"
360         
361         // The syscall pointer must be the first thing in roshared
362         // (at vaddr 0x7fff0000), so that user code can make method
363         // invocations to find out where other stuff is.
364         
365         .global x86_syscall_ptr
366 x86_syscall_ptr:
367         .long   x86_shared_int99 - x86_syscall_ptr + 0x7fff0000
368         
369         .global x86_shared_int99
370 x86_shared_int99:
371         int     $0x99
372         // FIXME: search for exception handler
373         ret