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