2 #include "config_tcbsize.h"
3 #include "config_gdt.h"
4 #include "globalconfig.h"
11 .macro PRE_FAST_ALIEN_IPC
12 btrl $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */
17 orl $EFLAGS_IF,8(%esp)
18 pushl $(0x30 << 3 | 2)
21 /* emulate entry code in KIP */
22 mov 40(%esp), %ebp /* offset 40: eip */
23 mov %ebp, 16(%esp) /* offset 16: ebx */
24 movl $(VAL__MEM_LAYOUT__SYSCALLS + 4f - 3f), 40(%esp)
25 mov 52(%esp), %ebp /* offset 52: sp */
26 mov %ebp, 8(%esp) /* offset 8: ebp */
28 3: /* must be the same code as code before sysenter in syscall-page.... */
31 4: /* the code between 3 and 4 shall never be executed, it is just to calculate
32 * the offset for the sysenter insn in the KIP / syscall page
34 1: /* do alien IPC and raise a trap afterwards */
35 RESET_THREAD_CANCEL_AT %ebx
38 .macro POST_FAST_ALIEN_IPC
39 RESTORE_STATE_AFTER_IPC
42 orl $EFLAGS_IF, 8(%esp)
43 pushl $(0x30 << 3 | 6)
50 .globl entry_vec01_debug
52 #if 0 // FIXME: figure out stuff differently
53 cmpl $VAL__MEM_LAYOUT__TCBS, %esp
55 cmpl $VAL__MEM_LAYOUT__TCBS_END, %esp
63 2: /* We came from an address equal to one of the sysenter entry
64 * points. Did we also come from kernel? */
68 /* copy last three dwords to the current kernel stack */
71 movl 20(%esp),%ecx // x86_tss.esp0
72 movl 8(%esp),%eax // 3rd dword == EIP
73 incl %eax // skip ``pop %esp''
75 movl 12(%esp),%eax // 2nd dword == CS
77 movl 16(%esp),%eax // 1st dword == EFLAGS
81 movl 12(%esp),%esp // x86_tss.esp0
82 subl $12, %esp // skip entry frame
89 .globl entry_vec0a_invalid_tss
90 entry_vec0a_invalid_tss:
91 andl $0xffffbfff, 12(%esp)
92 addl $4, %esp /* skip error code */
96 .globl entry_vec08_dbf
98 #if 0 /* XXX: disable debug feature reset on double fault */
99 testl $0xffffffff,CPU_DEBUGCTL_BUSY
100 jnz thread_handle_double_fault
102 movl CPU_DEBUGCTL_RESET, %eax
108 jmp thread_handle_double_fault
111 /* PPro spurious interrupt bug:
112 * See "Pentium Pro Processor Specification Update / January 1999"
113 * Erratum "Virtual Wire mode through local APIC may cause int 15"
114 * This exception can be silently ignored */
116 .globl entry_vec0f_apic_spurious_interrupt_bug
117 entry_vec0f_apic_spurious_interrupt_bug:
120 incl apic_spurious_interrupt_bug_cnt
125 /* APIC error interrupt */
127 .globl entry_apic_error_interrupt
128 entry_apic_error_interrupt:
131 leal SCRATCH_REGISTER_SIZE(%esp), %eax /* &Return_frame */
132 call apic_error_interrupt
136 /* Intel Architecture Software Developer's Manual Volume 3,
137 * Advanced Programmable Interrupt Controller (APIC):
138 * Spurious Interrupt: "If at the time the INTA cycle is issued, the
139 * interupt that was to be dispensed has become masked (programmed by
140 * software), the local APIC will deliver a spurious-interrupt vector." */
142 .globl entry_apic_spurious_interrupt
143 entry_apic_spurious_interrupt:
146 incl apic_spurious_interrupt_cnt
152 .global entry_int_apic_ignore
153 entry_int_apic_ignore:
156 mov apic_io_base, %ecx
163 #if defined(CONFIG_JDB)
166 .global entry_sys_fast_ipc_log
167 entry_sys_fast_ipc_log:
169 pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */
170 pushl %ebp // user esp
171 #ifdef CONFIG_IO_PROT
172 // We must not fake the interrupt flags since we must not
173 // loose the current IOPL of the user task
176 // Fake user eflags, set IOPL to 3
180 // Fake user cs. This cs value is never used with exception
181 // that the thread is ex_regs'd before we leave with sysexit.
182 // lthread_ex_regs has to check user cs for that value. If
183 // it is faked, the thread would leave the kernel by sysexit
184 // and the thread is in the slow ipc path. Sysexit would
185 // adapt the user eip (by subtracting 2) to ensure the user
186 // executes the "mov %ebp,%edx" sequence. This is wrong if
187 // the thread is ex_regs'd. In that case, we modify the return
188 // value from "call dispatch_syscall" to an alternate exit
189 // path using "iret".
190 pushl $(GDT_CODE_USER|SEL_PL_U|0x80) /* user cs */
191 pushl %ebx /* user eip */
202 testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx)
203 jnz alien_sys_fast_ipc_log
204 RESET_THREAD_CANCEL_AT %ebx
209 alien_sys_fast_ipc_log:
211 push $ret_from_fast_alien_ipc
219 #if (defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT))
221 .global entry_sys_fast_ipc_c
222 entry_sys_fast_ipc_c:
224 pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */
225 pushl %ebp // push user SP (get in ebp)
226 #ifdef CONFIG_IO_PROT
227 // We must not fake the interrupt flags since we must not
228 // loose the current IOPL of the user task
231 // Fake user eflags, set IOPL to 3
235 // Fake user cs. This cs value is never used with exception
236 // that the thread is ex_regs'd before we leave with sysexit.
237 // lthread_ex_regs has to check user cs for that value. If
238 // it is faked, the thread would leave the kernel by sysexit
239 // and the thread is in the slow ipc path. Sysexit would
240 // adapt the user eip (by subtracting 2) to ensure the user
241 // executes the "mov %ebp,%edx" sequence. This is wrong if
242 // the thread is ex_regs'd. In that case, we modify the return
243 // value from "call dispatch_syscall" to an alternate exit
244 // path using "iret".
245 pushl $(GDT_CODE_USER|SEL_PL_U|0x80) /* user cs */
246 pushl %ebx // push user return address
254 pushl %ecx /* save ecx */
256 testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx)
257 jnz alien_sys_fast_ipc_c
258 RESET_THREAD_CANCEL_AT %ebx
264 .globl alien_sys_fast_ipc_c /* Also used in shortcut */
265 .global ret_from_fast_alien_ipc /* used in ex-regs */
266 /* ex-regs patches the return address of the call to the 'sys_ipc' function
267 * in the case of sysenter, because we need to leave the kernel by iret
268 * to prevent the need of user-level trampoline code.
269 * In the case of alien ipc there must be a special case because otherwise the
270 * second alien exception is not generated. Therefore ex-regs uses
271 * 'ret_from_fast_alien_ipc' to determine this case and patches the return
272 * address with 'leave_alien_from_sysenter_by_iret' instead of
273 * 'leave_from_sysenter_by_iret'. (see Thread::user_ip in thread-ia32-ux.cpp)
277 alien_sys_fast_ipc_c:
281 ret_from_fast_alien_ipc:
286 .macro LEAVE_SE_BY_IRET
288 RESET_THREAD_IPC_MASK_AT %ebx
289 RESTORE_STATE_AFTER_IPC
291 orl $EFLAGS_IF, 8(%esp)
295 .globl leave_from_sysenter_by_iret
296 leave_from_sysenter_by_iret:
300 .globl leave_alien_from_sysenter_by_iret
301 leave_alien_from_sysenter_by_iret:
303 pushl $(0x30 << 3 | 6)
310 .global dbf_stack_top