]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/arch/x86/entry.S
Return to the int98 vsyscall code when returning from int99.
[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 #define ROSHARED_PTR(x) (x - x86_syscall_ptr + 0x7fff0000)
18
19         .org 0
20         .code32
21         .global _start
22 .align  4
23 multiboot_hdr:
24         .long   0x1badb002              // Multi-boot magic
25         
26         // Multi-boot flags:
27         //  bit 0: 4KiB-align all boot modules
28         //  bit 1: must include memory size and map
29         //  bit 2: must include video mode table
30         //  bit 16: load addresses in this header are valid
31         //          and should be used instead of the ELF header
32
33         .long   0x00010003
34
35         // checksum: -(magic + flags), update if flags change
36         .long   0xe4514ffb
37
38         .long   multiboot_hdr - KERNEL_START    // header_addr
39         .long   0x00200000                      // load_addr
40         .long   0                               // load_end_addr: load whole file
41         .long   bss_end - KERNEL_START          // bss_end_addr
42         .long   _start - KERNEL_START           // entry_addr
43
44 _start:
45         cld
46         lgdt    x86_gdtr_phys + 6 - KERNEL_START
47         ljmp    $0x10, $using_our_gdt - KERNEL_START
48
49 using_our_gdt:
50         movw    $0x08, %ax
51         movw    %ax, %ds
52         movw    %ax, %es
53         movw    %ax, %fs
54         movw    %ax, %gs
55         movw    %ax, %ss
56         
57         movl    %ebx, %esi              // Save the multiboot pointer somewhere
58                                         // it won't be clobbered by CPUID
59         
60         // This gives 512 bytes to Threads::Thread; if it gets larger
61         // this needs to be updated (as well as the code at high_vaddr).
62
63         movl    $x86_init_stack + 3584 - KERNEL_START, %esp
64
65         // Test for CPUID
66         pushfl
67         popl    %eax
68         movl    %eax, %ebx
69         xorl    $0x00200000, %eax
70         pushl   %eax
71         popfl
72         pushfl
73         popl    %eax
74         cmpl    %eax, %ebx
75         je      no_pentium
76
77         // Test for Page Size Extensions
78         xorl    %eax, %eax
79         cpuid
80         cmpl    $1, %eax
81         jb      no_pentium
82         
83         movl    $1, %eax
84         cpuid
85         btl     $3, %edx
86         jnc     no_pentium
87         
88         // enable PSE
89         movl    %cr4, %eax
90         btsl    $4, %eax
91         movl    %eax, %cr4
92         
93         // Load the initial page table
94         movl    $x86_init_ptbl_l2 - KERNEL_START, %eax
95         movl    %eax, %cr3
96         
97         // enable paging, kernel write-protect, 
98         // and internal floating point error handling
99         movl    %cr0, %eax
100         orl     $0x80010020, %eax
101         movl    %eax, %cr0
102
103         // Set up high page tables for 0x80000000 mapping,
104         
105         movl    $0x87, x86_init_ptbl_l2 + 0x800 - KERNEL_START
106         ljmp    $0x10, $paging_on - KERNEL_START
107
108 paging_on:      
109         lgdt    x86_gdtr + 6
110         movl    %esi, x86_boot_info_phys
111         
112         movl    $high_vaddr, %eax
113         jmp     *%eax
114
115 high_vaddr:
116         movl    $x86_init_stack + 3584, %esp
117         jmp     start_kernel
118
119 no_multiboot:
120         movl    $no_multiboot_str - KERNEL_START, %esi
121         jmp     do_print
122 no_pentium:
123         movl    $no_pentium_str - KERNEL_START, %esi
124 do_print:
125         movl    $0xb8000, %edi
126         
127         movb    (%esi), %al
128         xorl    %ecx, %ecx
129 1:      movb    %al, (%edi, %ecx, 2)
130         movb    $14, 1(%edi, %ecx, 2)   // It's not at the cursor, so use
131                                         // yellow to make it stand out.
132         incl    %ecx
133         movb    (%esi, %ecx), %al
134         testb   %al, %al
135         jnz     1b
136
137 2:      jmp     2b
138         
139 no_pentium_str:
140         .string "This kernel requires a Pentium-compatible CPU.  Either CPUID or PSE is missing."
141
142 no_multiboot_str:
143         .string "Unrecognized bootloader; a multiboot-compliant loader is required."
144
145         .macro  enterkernel, reg
146         pushl   %es
147         pushl   %ds
148         movl    $8, \reg
149         cld
150         movl    \reg, %ds
151         movl    \reg, %es
152         .endm
153         
154         .macro  exitkernel
155         popl    %ds
156         popl    %es
157         .endm
158         
159         .macro  pushvolatilesnoeax
160         pushl   %ecx
161         pushl   %edx
162         enterkernel %ecx
163         .endm
164         
165         .macro  pushvolatiles
166         pushl   %eax
167         pushvolatilesnoeax
168         .endm
169
170         .macro  popvolatiles
171         exitkernel
172         popl    %edx
173         popl    %ecx
174         popl    %eax
175         .endm
176
177         // Non-volatile registers must be pushed if the handler will
178         // need to access all of the interrupted code's registers,
179         // such as when producing an error dump.  Does not include
180         // edi, as that is usually swapped with the error code.
181         
182         .macro  pushall
183         pushl   %esi
184         pushl   %ebp
185         pushl   %ebx
186         pushl   %edx
187         pushl   %ecx
188         pushl   %eax
189         enterkernel %esi
190         .endm
191         
192         .macro  pushallnoerr
193         pushl   %edi
194         pushall
195         .endm
196
197         .macro  popall
198         exitkernel
199         popl    %eax
200         popl    %ecx
201         popl    %edx
202         popl    %ebx
203         popl    %ebp
204         popl    %esi
205         popl    %edi
206         .endm
207         
208         .global x86_diverr
209 x86_diverr:
210         pushallnoerr
211
212         pushl   %esp
213         call    x86_do_diverr
214         addl    $4, %esp
215
216         popall
217         iret
218
219         .global x86_debug
220 x86_debug:
221         pushallnoerr
222
223         pushl   %esp
224         call    x86_do_debug
225         addl    $4, %esp
226
227         popall
228         iret
229         
230         .global x86_breakpoint
231 x86_breakpoint:
232         pushallnoerr
233
234         pushl   %esp
235         call    x86_do_breakpoint
236         addl    $4, %esp
237
238         popall
239         iret
240
241         .global x86_invalid_insn
242 x86_invalid_insn:
243         pushallnoerr
244
245         pushl   %esp
246         call    x86_do_invalid_insn
247         addl    $4, %esp
248
249         popall
250         iret
251
252         .global x86_gpf
253 x86_gpf:
254         xchgl   %edi, (%esp)    // get error code
255         pushall
256         
257         movl    %esp, %eax
258         pushl   %edi
259         pushl   %eax
260         call    x86_do_gpf
261         addl    $8, %esp
262         
263         popall
264         iret
265
266         .global x86_page_fault
267 x86_page_fault:
268         xchgl   %edi, (%esp)    // get error code
269         pushall
270         
271         movl    %esp, %ecx
272         movl    %cr2, %eax
273         pushl   %edi
274         pushl   %eax
275         pushl   %ecx
276         call    x86_do_page_fault
277         addl    $12, %esp
278         
279         popall
280         iret
281
282         .global x86_int98_entry
283 x86_int98_entry:
284         pushl   $0
285         pushl   %eax
286         enterkernel %ecx
287
288         pushl   %esp
289         call    x86_invoke_method
290         addl    $4, %esp
291
292         exitkernel
293         popl    %eax
294         xorl    %ecx, %ecx
295         popl    %edx
296         xorl    %ebx, %ebx
297         xorl    %ebp, %ebp
298         xorl    %esi, %esi
299         xorl    %edi, %edi
300         iret
301
302         .global x86_int99_entry
303 x86_int99_entry:
304         pushl   %ecx
305         pushl   %eax
306         enterkernel %edx
307
308         pushl   %esp
309         call    x86_return_from_method
310         addl    $4, %esp
311         
312         exitkernel
313         popl    %eax
314         popl    %ecx
315         xorl    %edx, %edx
316         xorl    %ebx, %ebx
317         xorl    %ebp, %ebp
318         xorl    %esi, %esi
319         xorl    %edi, %edi
320         movl    $ROSHARED_PTR(x86_shared_int98_ret), (%esp)
321         iret
322
323         .global x86_irq
324 x86_irq:
325         pushvolatilesnoeax
326
327         pushl   %eax
328         call    x86_do_irq
329         addl    $4, %esp
330
331         movl    need_resched, %eax
332         testl   %eax, %eax
333         jnz     x86_reschedule
334
335 x86_ret_irq:
336         popvolatiles
337         iret
338
339 x86_reschedule:
340         // The cli is to make sure interrupts don't get re-enabled in
341         // this thread context between the schedule and the ret from
342         // IRQ.
343         
344         cli     
345         call    schedule
346         jmp     x86_ret_irq
347         
348         .section ".irqs","x"
349         .global x86_irqs
350 x86_irqs:
351         .text
352
353         .macro  irq from,to
354 1:      pushl   %eax
355         movl    $\from, %eax
356         jmp     x86_irq
357         .section ".irqs","x"
358         .long   1b
359         .text
360         .if     \to-\from
361         irq     (\from+1),\to
362         .endif
363         .endm
364         
365         .macro  irq16 from,to
366         irq     \from,(\from+15)
367         .if     \to-\from
368         irq16   (\from+16),\to
369         .endif
370         .endm
371
372         irq16   0,240
373
374         .global x86_new_thread
375 x86_new_thread:
376         xorl    %ebx, %ebx
377         xorl    %ecx, %ecx
378         xorl    %edx, %edx
379         xorl    %ebp, %ebp
380         xorl    %esi, %esi
381         xorl    %edi, %edi
382         
383         call    sched_new_thread
384         pop     %eax
385         call    *%eax
386         call    exit_thread
387         ud2a
388
389         .section ".roshared","x"
390         
391         // The vsyscall table must be the first thing in roshared 
392         // (at vaddr 0x7fff0000).
393         
394         .global x86_syscall_ptr
395 x86_syscall_ptr:
396         .long   ROSHARED_PTR(x86_shared_int98)
397
398         .global x86_sysret_ptr
399 x86_sysret_ptr:
400         .long   ROSHARED_PTR(x86_shared_int99)
401
402 x86_shared_int98:
403         // FIXME: This must be unpreemptible by traps
404         pushl   %gs
405         pushl   %fs
406         pushl   %ebp
407         pushl   %edi
408         pushl   %esi
409         pushl   %ebx
410         int     $0x98
411 x86_shared_int98_ret:
412         popl    %ebx
413         popl    %esi
414         popl    %edi
415         popl    %ebp
416         popl    %fs
417         popl    %gs
418         ret
419
420 x86_shared_int99:
421         int     $0x99
422         ret
423
424         .section ".rwshared",""
425
426         // Userspace must set this to an appropriate entry point
427         // prior to registering objects with the kernel.  It should
428         // not be modified while an object is registered (the kernel
429         // won't mind, but there's no mechanism to wait until no more
430         // upcalls to the old entry point are in progress).
431         .global x86_upcall_entry
432 x86_upcall_entry:
433         .long   0