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