]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/32/entry.S
update
[l4.git] / kernel / fiasco / src / kern / ia32 / 32 / entry.S
1 /*
2  * This file contains a 'gate_init' initialization table
3  * to initialize the x86 processor trap vectors to default entrypoints.
4  * These entrypoints simply push a standard trap_state frame
5  * and jump to the 'trap_handler' routine.
6  */
7
8 #include "config_tcbsize.h"
9 #include "config_gdt.h"
10 #include "globalconfig.h"
11 #include "idt_init.h"
12 #include <low_level.h>
13 #include "shortcut.h"
14 #include "tcboffset.h"
15 #include "regdefs.h"
16
17 #include "asm.h"
18
19 /* We make the trap handler an interrupt gate, because for debugging
20    purposes, we don't want any interrupts to occur until they're
21    explicitly enabled in the base_trap_handler (usually
22    Thread::handle_slow_trap). */
23
24 /*
25  * No error code.  Clear error code and push trap number.
26  */
27 #define EXCEPTION(n,name)                                       \
28         GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE)     ;\
29         .p2align 3                                              ;\
30 entry_##name:                                                   ;\
31         pushl   $(0)                                            ;\
32         pushl   $(n)                                            ;\
33         pusha                                                   ;\
34         jmp     _slowtraps
35
36 /*
37  * User-accessible exception.  Otherwise, same as above.
38  */
39 #define EXCEP_USR(n,name)                                       \
40         GATE_ENTRY(n,entry_##name,ACC_PL_U | ACC_INTR_GATE)     ;\
41         .p2align 3                                              ;\
42 entry_##name:                                                   ;\
43         pushl   $(0)                                            ;\
44         pushl   $(n)                                            ;\
45         pusha                                                   ;\
46         jmp     _slowtraps
47
48 /*
49  * Error code has been pushed.  Just push trap number.
50  */
51 #define EXCEP_ERR(n,name)                                       \
52         GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE)     ;\
53         .p2align 3                                              ;\
54 entry_##name:                                                   ;\
55         pushl   $(n)                                            ;\
56         pusha                                                   ;\
57         jmp     _slowtraps
58
59 .macro  PRE_ALIEN_IPC
60         btrl    $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */
61         jc      1f
62         RESTORE_STATE
63         sub     $2, 4(%esp)                /* Correct EIP to point to insn */
64         popl    %eax
65         pushl   $(0x30 << 3 | 2)
66         pushl   $(0xd)
67         pusha
68         jmp     _slowtraps
69
70 1:      /* do alien IPC and raise a trap afterwards */  
71         RESET_THREAD_CANCEL_AT %ebx
72 .endm
73
74 .macro  POST_ALIEN_IPC
75         CHECK_SANITY $3                 /* scratches ecx */
76         RESTORE_STATE_AFTER_IPC
77         popl    %eax
78         pushl   $(0x30 << 3 | 6)
79         pushl   $(0xd)
80         pusha
81         jmp     _slowtraps
82 .endm
83
84 GATE_INITTAB_BEGIN(idt_init_table)
85
86 EXCEPTION(0x00,vec00_zero_div)
87 #ifdef CONFIG_PF_UX
88 EXCEPTION(0x01,vec01_debug)
89 #else
90 /* IA32 has to handle breakpoint exceptions if occured exactly at 
91    entry_sys_fast_ipc -- see ia32/entry-ia32.S */
92 GATE_ENTRY(0x01,entry_vec01_debug,ACC_PL_K | ACC_INTR_GATE)
93 #endif
94 /* XXX IA32 has to handle NMI occured exactly at entry_sys_fast_ipc */
95 EXCEP_USR(0x02,vec02_nmi)
96 EXCEP_USR(0x03,vec03_breakpoint)
97 EXCEP_USR(0x04,vec04_into)
98 EXCEP_USR(0x05,vec05_bounds)
99 EXCEPTION(0x06,vec06_invop)
100 /* EXCEPTION(0x07,nofpu) */
101 #ifdef CONFIG_PF_UX
102 EXCEP_ERR(0x08,vec08_dbl_fault)
103 #else
104 GATE_ENTRY(0x08, GDT_TSS_DBF, ACC_PL_K | ACC_TASK_GATE)
105 #endif
106 EXCEPTION(0x09,vec09_fpu_ovfl)
107 /* EXCEP_ERR(0x0a,vec0a_inv_tss) */
108 EXCEP_ERR(0x0b,vec0b_segnp)
109 EXCEP_ERR(0x0c,vec0c_stack_fault)
110 EXCEP_ERR(0x0d,vec0d_gen_prot)
111 /* EXCEP_ERR(0x0e,vec0e_page_fault) */
112 /* EXCEPTION(0x0f,vec0f_trap_0f) */
113 EXCEPTION(0x10,vec10_fpu_err)
114 EXCEP_ERR(0x11,vec11_align)
115 EXCEPTION(0x12,vec12_mcheck)
116 EXCEPTION(0x13,vec13_simd_err)
117
118
119         .p2align 4
120         .type   slowtraps,@function
121         .globl  slowtraps
122         /* We have to introduce the label _slowtraps besides the label
123            slowtraps to achive that jmps from exception entry points
124            are optimized to two-byte jmps. The label slowtraps is visible
125            from outside. */
126 _slowtraps:
127 slowtraps:
128 #ifdef CONFIG_PF_UX
129 # define REG_GS CPU_GS
130 # define REG_FS CPU_FS
131 #else
132 # define REG_GS %gs
133 # define REG_FS %fs
134 #endif
135
136         pushl   REG_FS          /* we save the segment regs in the trap   */
137         pushl   REG_GS          /* state, but we do not restore them.  We */
138         pushl   %ds             /* rather reload them using               */
139         pushl   %es             /* RESET_{KERNEL,USER}_SEGMENTS           */
140
141         cld
142
143         /* Load the kernel's segment registers.  */
144         RESET_KERNEL_SEGMENTS_FORCE_DS_ES /* scratches ecx, edx */
145         
146         /* Note: we do not use RESET_THREAD_CANCEL_* here as that is
147            needed only when an I/O-page-fault IPC is sent and when the
148            thread is killed. Resetting Thread_cancel here could
149            be harmful when using this trap handler in debugging.
150            Instead, we clear this flag in Thread::handle_slow_trap()
151            just before sending the IPC message or before killing the
152            thread.  That's OK, because it is still atomic -- we never
153            enable IRQs (sti) before that point. */
154
155         movl    %esp,%eax               /* ARG1: address of trap_state */
156         xorl    %edx,%edx               /* ARG2: default CPU = 0 */
157 #ifndef CONFIG_NO_FRAME_PTR
158         pushl   56(%esp)                /* create artificial stack frame */
159         pushl   %ebp
160 # ifndef CONFIG_PROFILE
161         leal    (%esp),%ebp
162 # else
163         xorl    %ebp,%ebp
164 # endif
165 #endif
166
167         /* Call the C handler function if one has been installed.  */
168         movl    BASE_TRAP_HANDLER, %ecx
169         orl     %ecx,%ecx
170         jz      unexpected_trap_pop
171         call    *%ecx
172 in_slowtrap:
173
174 #ifndef CONFIG_NO_FRAME_PTR
175         leal    8(%esp),%esp
176 #endif
177
178         /* If the handler function returned zero (success),
179            then resume execution as if the trap never happened.
180            Otherwise, just panic.  */
181         orl     %eax,%eax
182         jnz     unexpected_trap
183
184         CHECK_SANITY 60(%esp)           /* scratches ecx */
185
186         addl    $4*2,%esp               /* Pop ds, es segment registers */
187         popl    REG_GS
188         popl    REG_FS                  /* Restore segment registers */
189         popa
190         addl    $4*2,%esp               /* Pop trap number and error code */
191         iret
192
193 unexpected_trap_pop:
194 #ifndef CONFIG_NO_FRAME_PTR
195         leal    8(%esp), %esp
196 #endif
197
198 unexpected_trap:
199         movw    %ss,%ax
200         movw    %ax,%ds
201         movw    %ax,%es
202         movl    %esp,%eax
203         call    trap_dump_panic
204
205 GATE_ENTRY(0x0e,entry_vec0e_page_fault,ACC_PL_K | ACC_INTR_GATE)
206
207 /* we must save %cr2 before we can be preempted -- therefore we're an
208    interrupt gate (invoked with interrupts turned off).  Also, we
209    don't turn them on again here, but only after checking for
210    page-ins from the global page directory in thread_page_fault().
211    XXX: If you make changes to stack layout here, fix thread_page_fault */
212
213 /* XXX slow version - sets up nice stack frame for debugger */
214
215         .p2align 4
216         .type   entry_vec0e_page_fault,@function
217 entry_vec0e_page_fault:
218         cld
219         SAVE_SCRATCH
220         RESET_KERNEL_SEGMENTS_FORCE_DS_ES
221         movl    12(%esp),%edx           /* save error code in ARG2 ... */
222         movl    PAGE_FAULT_ADDR,%eax    /* save page fault address in ARG1 */
223
224 /* We must reset the cancel flag here atomically 
225    if we are entering fresh from user mode and an IPC might occur. 
226    NOTE: We cannot test the user-mode bit in the error code because
227    it will flag "kernel" in case an I/O-bitmap page is not mapped
228    during an I/O access. */
229
230         movl    20(%esp),%ecx   /* get CS from stack */
231         andb    $3,%cl          /* retrieve current privilege level (CPL) */
232         jz      1f              /* CPL == 0 -> kernel, skip resetting state */
233         ESP_TO_TCB_AT %ecx
234         RESET_THREAD_CANCEL_AT %ecx
235 1:      movl    %ebp,12(%esp)   /* save frame pointer */
236         leal    12(%esp),%ebp   /* load new frame pointer */
237 #ifdef CONFIG_PROFILE
238         call    mcount
239 #endif
240         pushl   %eax            /* save pf address */
241         pushl   %edx            /* save error code */
242         leal    24(%esp),%ecx   /* ARG5: ptr to Return_frame */
243         pushl   %ecx
244         pushl   36(%esp)        /* ARG4: eflags */
245         movl    32(%esp),%ecx   /* ARG3: eip */
246         call    thread_page_fault
247 in_page_fault:
248
249         orl     %eax,%eax
250         jz      bad_page_fault
251         lea     16(%esp),%esp
252         CHECK_SANITY 20(%esp)                   /* scratches ecx */
253         RESTORE_SCRATCH
254         popl    %ebp
255         iret
256
257 /* recover from a bad page fault by invoking the slow_trap handler */
258         .p2align 4
259 bad_page_fault:
260         cli
261         addl    $8,%esp         /* pop ARG4 and ARG5 */
262         movl    (%ebp),%eax     /* old ebp */
263         popl    (%ebp)          /* error code */
264         popl    %edx            /* page fault address */
265         movl    %eax,%ebp
266
267         /* we have on stack: error code, eax, ecx, edx
268            move registers down to make room for trap number */
269         subl    $4,%esp
270         movl    4(%esp),%eax
271         movl    %eax,(%esp)
272         movl    8(%esp),%eax
273         movl    %eax,4(%esp)
274         movl    12(%esp),%eax
275         movl    %eax,8(%esp)
276         movl    $0x0e,12(%esp)  /* error code */
277         pushl   %ebx            /* rest of trap state */
278         pushl   %edx            /* page fault address */
279         pushl   %ebp
280         pushl   %esi
281         pushl   %edi
282         jmp     slowtraps
283
284
285 /* FPU not available in this context. */
286 GATE_ENTRY(0x07,entry_vec07_fpu_unavail, ACC_PL_K | ACC_INTR_GATE)
287
288 /* do all of this with disabled interrupts */
289         .p2align 4
290         .type   entry_vec07_fpu_unavail,@function
291 entry_vec07_fpu_unavail:
292         cld
293         SAVE_SCRATCH
294         call    thread_handle_fputrap
295 in_handle_fputrap:
296         CHECK_SANITY 16(%esp)                   /* scratches ecx */
297         test    %eax, %eax
298         jz      real_fpu_exception
299         RESTORE_SCRATCH
300         iret 
301 real_fpu_exception:
302         RESTORE_SCRATCH
303         pushl   $(0)
304         pushl   $(7)
305         pusha                                                   
306         jmp     _slowtraps
307
308
309 /* timer interrupt */
310 #ifdef CONFIG_SCHED_PIT
311 GATE_ENTRY(0x20,entry_int_timer,ACC_PL_K | ACC_INTR_GATE)
312 #endif
313 #ifdef CONFIG_SCHED_RTC
314 GATE_ENTRY(0x28,entry_int_timer,ACC_PL_K | ACC_INTR_GATE)
315 #endif
316 #ifdef CONFIG_SCHED_APIC
317 GATE_ENTRY(APIC_IRQ_BASE, entry_int_timer,ACC_PL_K | ACC_INTR_GATE)
318 #endif
319 #ifdef CONFIG_SCHED_HPET
320 /* HPET is set at startup */
321 #endif
322
323         .p2align 4
324         .globl  entry_int_timer
325 entry_int_timer:
326 #ifndef CONFIG_NO_FRAME_PTR
327         pushl   %ebp
328 #ifndef CONFIG_PROFILE
329         movl    %esp,%ebp
330 #else
331         xorl    %ebp,%ebp
332 #endif
333 #endif
334         SAVE_SCRATCH
335 do_timer_interrupt:
336         cld
337 #ifdef CONFIG_NO_FRAME_PTR
338         movl    12(%esp), %eax                  /* ARG1: eip for logging */
339 #else
340         movl    16(%esp), %eax                  /* ARG1: eip for logging */
341 #endif
342         call    thread_timer_interrupt          /* enter with disabled irqs */
343 in_timer_interrupt:
344 #ifndef CONFIG_NO_FRAME_PTR
345         CHECK_SANITY 20(%esp)                   /* scratches ecx */
346 #else
347         CHECK_SANITY 16(%esp)                   /* scratches ecx */
348 #endif
349         RESTORE_SCRATCH
350 #ifndef CONFIG_NO_FRAME_PTR
351         popl    %ebp
352 #endif
353         iret
354
355         .p2align 4
356         .globl  entry_int_timer_slow
357 entry_int_timer_slow:
358 #ifndef CONFIG_NO_FRAME_PTR
359         pushl   %ebp
360 #ifndef CONFIG_PROFILE
361         movl    %esp,%ebp
362 #else
363         xorl    %ebp,%ebp
364 #endif
365 #endif
366         SAVE_SCRATCH
367         cld
368
369         call    thread_timer_interrupt_slow     /* enter with disabled irqs */
370 in_timer_interrupt_slow:
371         jmp     do_timer_interrupt
372
373         
374         .p2align 4
375         .globl  entry_int_timer_stop
376 entry_int_timer_stop:
377 #ifndef CONFIG_NO_FRAME_PTR
378         pushl   %ebp
379 #ifndef CONFIG_PROFILE
380         movl    %esp,%ebp
381 #else
382         xorl    %ebp,%ebp
383 #endif
384 #endif
385         SAVE_SCRATCH
386         cld
387         call    thread_timer_interrupt_stop
388 #ifndef CONFIG_NO_FRAME_PTR
389         CHECK_SANITY 20(%esp)                   /* scratches ecx */
390 #else
391         CHECK_SANITY 16(%esp)                   /* scratches ecx */
392 #endif
393         RESTORE_SCRATCH
394 #ifndef CONFIG_NO_FRAME_PTR
395         popl    %ebp
396 #endif
397         iret
398
399
400 /* profiling timer interrupt entry point */
401 #ifdef CONFIG_PROFILE
402
403         .p2align 4
404         .globl profile_interrupt_entry
405         .type   profile_interrupt_entry,@function
406 profile_interrupt_entry:
407         cld
408 #ifndef CONFIG_NO_FRAME_PTR
409         pushl   %ebp
410         movl    %esp,%ebp
411         pushl   %eax
412         movl    8(%esp),%eax                    /* %eax = return address */
413 #else
414         pushl   %eax
415         movl    4(%esp),%eax                    /* %eax = return address */
416 #endif
417         pushl   %edx
418         pushl   %ecx
419         call    profile_interrupt               /* enter with disabled irqs */
420 #ifndef CONFIG_NO_FRAME_PTR
421         CHECK_SANITY 20(%esp)                   /* scratches ecx */
422 #else
423         CHECK_SANITY 16(%esp)                   /* scratches ecx */
424 #endif
425         popl    %ecx
426         popl    %edx
427         popl    %eax
428 #ifndef CONFIG_NO_FRAME_PTR
429         popl    %ebp
430 #endif
431         iret
432
433 #endif /* CONFIG_PROFILE */
434
435 /* other interrupts */
436
437 #define INTERRUPT(int,name)                                     \
438         GATE_ENTRY(int,entry_##name,ACC_PL_K | ACC_INTR_GATE)   ;\
439         .p2align 3                                              ;\
440 entry_##name:                                                   ;\
441         pushl   %eax                                            ;\
442         movl    $ (int - 0x20), %eax    /* ARG1: irqnum */      ;\
443         jmp     all_irqs
444
445 #ifndef CONFIG_SCHED_PIT
446 INTERRUPT(0x20,int0)
447 #endif
448 /* spurious IRQ handlers */
449 GATE_ENTRY(0x27,entry_int_pic_ignore,ACC_PL_K | ACC_INTR_GATE)
450 GATE_ENTRY(0x2f,entry_int_pic_ignore,ACC_PL_K | ACC_INTR_GATE)  
451 #ifndef CONFIG_SCHED_RTC
452 INTERRUPT(0x28,int8)
453 #endif
454
455         .p2align 4
456         .type   all_irqs,@function
457         .type   __generic_irq_entry,@function
458         .global __generic_irq_entry
459 all_irqs:
460 __generic_irq_entry:
461         cld
462         pushl   %edx
463         pushl   %ecx
464         movl    12(%esp), %edx                  /* ARG2: eip */
465         call    irq_interrupt                   /* enter with disabled irqs */
466 in_interrupt:
467         CHECK_SANITY 16(%esp)                   /* scratches ecx */
468         popl    %ecx
469         popl    %edx
470         popl    %eax
471
472 entry_int_pic_ignore:
473         iret
474
475         .global entry_int_pic_ignore
476         .global entry_int7
477         .global entry_intf
478
479 /****************************************************************************/
480 /* system calls                                                             */
481 /****************************************************************************/
482
483 #ifdef CONFIG_ASSEMBLER_IPC_SHORTCUT
484 GATE_ENTRY(0x30,entry_sys_ipc,ACC_PL_U | ACC_INTR_GATE);
485 #else
486 GATE_ENTRY(0x30,entry_sys_ipc_c,ACC_PL_U | ACC_INTR_GATE);
487 #endif
488
489 #if defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)
490         .p2align 4
491         .globl  entry_sys_ipc_c
492 entry_sys_ipc_c:
493         cld
494         pushl   %eax
495         SAVE_STATE
496         ESP_TO_TCB_AT %ebx
497         testl   $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx)
498         jnz     alien_sys_ipc_c
499         RESET_THREAD_CANCEL_AT %ebx
500         call    sys_ipc_wrapper //ipc_short_cut_wrapper
501 in_sc_ipc1:
502         CHECK_SANITY $3                 /* scratches ecx */
503         RESTORE_STATE_AFTER_IPC
504         popl    %eax
505         iret
506
507         .globl  in_sc_ipc1
508 #endif
509
510 #ifdef CONFIG_JDB
511         /* The slow variant of sys_ipc_entry is used when logging IPC */
512         .p2align 4
513         .globl  entry_sys_ipc_log
514 entry_sys_ipc_log:
515         cld
516         pushl   %eax
517         SAVE_STATE
518         ESP_TO_TCB_AT %ebx
519         testl   $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx)
520         jnz     alien_sys_ipc_log
521         RESET_THREAD_CANCEL_AT %ebx
522         call    *syscall_table
523 in_slow_ipc4:
524         CHECK_SANITY $3                 /* scratches ecx */
525         RESTORE_STATE_AFTER_IPC
526         popl    %eax
527         iret
528
529         .globl  in_slow_ipc4
530 #endif // CONFIG_JDB
531
532         // these labels help show_tcb to guess the thread state
533         .globl  in_syscall
534         .globl  in_slowtrap
535         .globl  in_page_fault
536         .globl  in_handle_fputrap
537         .globl  in_interrupt  
538         .globl  in_timer_interrupt
539         .globl  in_timer_interrupt_slow
540
541 #define SYSTEM_CALL(int,name)                                   \
542         GATE_ENTRY(int,entry_##name,ACC_PL_U | ACC_INTR_GATE)   ;\
543         .p2align 3                                              ;\
544 entry_##name:                                                   ;\
545         pushl   %eax                                            ;\
546         movl    $(syscall_table+4*(int-0x30)), %eax             ;\
547         jmp     all_syscalls
548
549         .p2align 4
550         .type   all_syscalls,@function
551 all_syscalls:
552         SAVE_STATE                                              ;\
553         cld
554         ESP_TO_TCB_AT %ebx
555         testl   $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx)
556         jnz     alien_sys_call
557         RESET_THREAD_CANCEL_AT %ebx
558         call    *(%eax)                 /* interrupts enabled in wrappers */
559 in_syscall:
560
561 ret_from_syscall:
562         CHECK_SANITY $3                 /* scratches ecx */
563         RESTORE_STATE
564         popl    %eax
565         iret
566
567
568 SYSTEM_CALL(0x32,sys_invoke_debug)
569
570 #ifndef CONFIG_PF_UX
571 /* these functions are implemented in entry-native.S */
572 GATE_ENTRY(0x0a,entry_vec0a_invalid_tss,ACC_PL_K | ACC_INTR_GATE)
573 GATE_ENTRY(0x0f,entry_vec0f_apic_spurious_interrupt_bug,ACC_PL_K | ACC_INTR_GATE)
574 GATE_ENTRY(APIC_IRQ_BASE + 3,entry_apic_error_interrupt,ACC_PL_K | ACC_INTR_GATE)
575 GATE_ENTRY(APIC_IRQ_BASE + 0xf,entry_apic_spurious_interrupt,ACC_PL_K | ACC_INTR_GATE)
576 #endif
577
578 #ifdef CONFIG_MP
579 GATE_ENTRY(APIC_IRQ_BASE + 2, entry_ipi, ACC_PL_K | ACC_INTR_GATE)
580 GATE_ENTRY(APIC_IRQ_BASE - 2, entry_debug_ipi, ACC_PL_K | ACC_INTR_GATE)
581 GATE_ENTRY(APIC_IRQ_BASE - 1, entry_ipi_remote_request, ACC_PL_K | ACC_INTR_GATE)
582 #endif
583
584 GATE_INITTAB_END
585
586         .globl alien_sys_ipc_c /* Also used in shortcut */
587 alien_sys_ipc_c:
588         cld
589         PRE_ALIEN_IPC
590         call    sys_ipc_wrapper
591         POST_ALIEN_IPC
592
593 #if defined (CONFIG_JDB)
594 alien_sys_ipc_log:
595         cld
596         PRE_ALIEN_IPC
597         call    *syscall_table
598         POST_ALIEN_IPC
599 #endif
600
601 /*
602  * input:  eax: address to syscall function
603  * output: eax: error code
604  */
605 .macro SC_ADDR_TO_ERR val
606         sub     $syscall_table , %eax   /* eax = byte offset to syscall */
607         shr     $2, %eax                /* convert eax to syscall nr */
608         add     $0x30, %eax             /* convert eax to syscall int nr */
609         shl     $3, %eax                /* construct error code */
610         orl     $\val, %eax             /* -"- */
611 .endm
612
613 alien_sys_call:
614         btrl    $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */
615         jc      1f
616         RESTORE_STATE
617         sub     $2, 4(%esp)             /* Correct EIP to point to insn */
618         SC_ADDR_TO_ERR 2
619 2:      pushl   $0xd
620         xchgl   4(%esp), %eax
621         pusha
622         jmp     _slowtraps
623
624 1:      /* do alien syscall and trap afterwards */
625         RESET_THREAD_CANCEL_AT %ebx
626         pushl   %eax
627         call    *(%eax)                 /* call with ENABLED interrupts */
628         cli
629         CHECK_SANITY $3                 /* scratches ecx */
630         popl    %eax
631         RESTORE_STATE
632         SC_ADDR_TO_ERR 6
633         jmp     2b
634
635
636         .p2align
637         .globl  leave_by_trigger_exception
638 leave_by_trigger_exception:
639         cli
640         subl    $12,%esp                /* clean up stack from previous
641                                          * CPL0-CPL0 iret */
642         SAVE_SCRATCH
643         call    thread_restore_exc_state
644         RESTORE_SCRATCH
645         pushl   $0x00
646         pushl   $0xff
647         pusha
648         jmp     _slowtraps
649
650         .p2align
651         .globl  leave_by_vcpu_upcall
652 leave_by_vcpu_upcall:
653         cli
654         subl    $12,%esp                /* clean up stack from previous
655                                          * CPL0-CPL0 iret */
656         SAVE_SCRATCH
657         call    thread_restore_exc_state
658
659         ESP_TO_TCB_AT %ecx
660         mov OFS__THREAD__USER_VCPU(%ecx), %eax /* vcpu state pointer from TCB */
661         mov OFS__THREAD__VCPU_STATE(%ecx), %ecx /* vcpu state pointer from TCB */
662         addl $(VAL__SIZEOF_TRAP_STATE - 20), %ecx /* skip return frame */
663         mov SCRATCH_REGISTER_SIZE(%esp),  %edx
664         mov %edx, (%ecx)                                /* EIP */
665         mov 8 + SCRATCH_REGISTER_SIZE(%esp),  %edx
666         mov %edx, 8(%ecx)                               /* EFLAGS */
667         mov 12 + SCRATCH_REGISTER_SIZE(%esp), %edx
668         mov %edx, 12(%ecx)                              /* ESP */
669         mov 16 + SCRATCH_REGISTER_SIZE(%esp), %edx
670         mov %edx, 16(%ecx)                              /* SS */
671
672         mov 0(%esp), %edx    /* EDX */
673         mov %edx, -20(%ecx)
674         mov 4(%esp), %edx    /* ECX */
675         mov %edx, -16(%ecx)
676         mov 8(%esp), %edx    /* EAX */
677         mov %edx, -12(%ecx)
678
679         lea 12(%esp), %edx
680         lea -20(%ecx), %esp
681
682         push %ebx            /* EBX */
683         sub $4, %esp         /* SKIP PFA */
684         push %ebp            /* EBP */
685         push %esi            /* ESI */
686         push %edi            /* EDI */
687
688         /*add SCRATCH_REGISTER_SIZE, %esp*/
689
690         pushl   REG_FS          /* we save the segment regs in the trap   */
691         pushl   REG_GS          /* state, but we do not restore them.  We */
692         pushl   %ds             /* rather reload them using               */
693         pushl   %es             /* RESET_{KERNEL,USER}_SEGMENTS           */
694
695         mov %edx, %esp
696         mov -VAL__SIZEOF_TRAP_STATE + 20 + OFS__VCPU_STATE__ENTRY_SP(%ecx), %edx
697         mov %edx, 12(%esp)
698         mov -VAL__SIZEOF_TRAP_STATE + 20 + OFS__VCPU_STATE__ENTRY_IP(%ecx), %edx
699         mov %edx, 0(%esp)
700         movl $EFLAGS_IF, 8(%esp)
701         iret
702         
703         .p2align
704         .globl  vcpu_resume
705 vcpu_resume:
706         mov %eax, %esp
707         addl $(2*4), %esp // skip es and ds for now
708         //popl %es
709         //popl %ds
710         popl REG_GS
711         popl REG_FS
712         popa
713         addl $(2*4), %esp
714         iret
715
716
717 .section ".text.debug.stack_profiling"
718
719         .global __cyg_profile_func_enter
720         .global __cyg_profile_func_exit
721
722
723 __ret_from_cyg:
724         ret
725 __cyg_profile_func_enter:
726 __cyg_profile_func_exit:
727         cmp $0xc0000000, %esp
728         jl __ret_from_cyg
729         cmp $0xd0000000,%esp
730         jg __ret_from_cyg
731         mov %esp, %ecx
732 //      and $0x7ff, %ecx /* 2K TCBs */
733         and $0xfff, %ecx /* 4K TCBs */
734         cmp $0x200, %ecx
735         jg __ret_from_cyg
736         int3
737         jmp 1f
738         .ascii "STACK"
739 1:      ret
740
741         // fast return from Dirq::hit
742         .align  16
743         .globl  fast_ret_from_irq
744 fast_ret_from_irq:
745         CHECK_SANITY $3                         // scratches ecx
746         RESTORE_STATE_AFTER_IPC
747         popl    %eax
748         andl    $0x7f, 4(%esp)                  // if entered using sysenter
749         orl     $EFLAGS_IF, 8(%esp)             // if entered using sysenter
750         iret
751
752
753
754
755