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