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