blob: 87f9f60b803be12deb178df607c169a6cb333afb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/i386/entry.S
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
7/*
8 * entry.S contains the system-call and fault low-level handling routines.
9 * This also contains the timer-interrupt handler, as well as all interrupts
10 * and faults that can result in a task-switch.
11 *
12 * NOTE: This code handles signal-recognition, which happens every time
13 * after a timer-interrupt and after each system call.
14 *
15 * I changed all the .align's to 4 (16 byte alignment), as that's faster
16 * on a 486.
17 *
18 * Stack layout in 'ret_from_system_call':
19 * ptrace needs to have all regs on the stack.
20 * if the order here is changed, it needs to be
21 * updated in fork.c:copy_process, signal.c:do_signal,
22 * ptrace.c and ptrace.h
23 *
24 * 0(%esp) - %ebx
25 * 4(%esp) - %ecx
26 * 8(%esp) - %edx
27 * C(%esp) - %esi
28 * 10(%esp) - %edi
29 * 14(%esp) - %ebp
30 * 18(%esp) - %eax
31 * 1C(%esp) - %ds
32 * 20(%esp) - %es
33 * 24(%esp) - orig_eax
34 * 28(%esp) - %eip
35 * 2C(%esp) - %cs
36 * 30(%esp) - %eflags
37 * 34(%esp) - %oldesp
38 * 38(%esp) - %oldss
39 *
40 * "current" is in register %ebx during any slow entries.
41 */
42
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/linkage.h>
44#include <asm/thread_info.h>
Ingo Molnar55f327f2006-07-03 00:24:43 -070045#include <asm/irqflags.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <asm/errno.h>
47#include <asm/segment.h>
48#include <asm/smp.h>
49#include <asm/page.h>
50#include <asm/desc.h>
Jan Beulichfe7cacc2006-06-26 13:57:44 +020051#include <asm/dwarf2.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include "irq_vectors.h"
53
54#define nr_syscalls ((syscall_table_size)/4)
55
56EBX = 0x00
57ECX = 0x04
58EDX = 0x08
59ESI = 0x0C
60EDI = 0x10
61EBP = 0x14
62EAX = 0x18
63DS = 0x1C
64ES = 0x20
65ORIG_EAX = 0x24
66EIP = 0x28
67CS = 0x2C
68EFLAGS = 0x30
69OLDESP = 0x34
70OLDSS = 0x38
71
72CF_MASK = 0x00000001
73TF_MASK = 0x00000100
74IF_MASK = 0x00000200
75DF_MASK = 0x00000400
76NT_MASK = 0x00004000
77VM_MASK = 0x00020000
78
79#ifdef CONFIG_PREEMPT
Ingo Molnar55f327f2006-07-03 00:24:43 -070080#define preempt_stop cli; TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#else
82#define preempt_stop
83#define resume_kernel restore_nocheck
84#endif
85
Ingo Molnar55f327f2006-07-03 00:24:43 -070086.macro TRACE_IRQS_IRET
87#ifdef CONFIG_TRACE_IRQFLAGS
88 testl $IF_MASK,EFLAGS(%esp) # interrupts off?
89 jz 1f
90 TRACE_IRQS_ON
911:
92#endif
93.endm
94
Aleksey Gorelov4031ff32006-06-27 02:53:48 -070095#ifdef CONFIG_VM86
96#define resume_userspace_sig check_userspace
97#else
98#define resume_userspace_sig resume_userspace
99#endif
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#define SAVE_ALL \
102 cld; \
103 pushl %es; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200104 CFI_ADJUST_CFA_OFFSET 4;\
105 /*CFI_REL_OFFSET es, 0;*/\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 pushl %ds; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200107 CFI_ADJUST_CFA_OFFSET 4;\
108 /*CFI_REL_OFFSET ds, 0;*/\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 pushl %eax; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200110 CFI_ADJUST_CFA_OFFSET 4;\
111 CFI_REL_OFFSET eax, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 pushl %ebp; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200113 CFI_ADJUST_CFA_OFFSET 4;\
114 CFI_REL_OFFSET ebp, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 pushl %edi; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200116 CFI_ADJUST_CFA_OFFSET 4;\
117 CFI_REL_OFFSET edi, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 pushl %esi; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200119 CFI_ADJUST_CFA_OFFSET 4;\
120 CFI_REL_OFFSET esi, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 pushl %edx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200122 CFI_ADJUST_CFA_OFFSET 4;\
123 CFI_REL_OFFSET edx, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 pushl %ecx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200125 CFI_ADJUST_CFA_OFFSET 4;\
126 CFI_REL_OFFSET ecx, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 pushl %ebx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200128 CFI_ADJUST_CFA_OFFSET 4;\
129 CFI_REL_OFFSET ebx, 0;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 movl $(__USER_DS), %edx; \
131 movl %edx, %ds; \
132 movl %edx, %es;
133
134#define RESTORE_INT_REGS \
135 popl %ebx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200136 CFI_ADJUST_CFA_OFFSET -4;\
137 CFI_RESTORE ebx;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 popl %ecx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200139 CFI_ADJUST_CFA_OFFSET -4;\
140 CFI_RESTORE ecx;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 popl %edx; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200142 CFI_ADJUST_CFA_OFFSET -4;\
143 CFI_RESTORE edx;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 popl %esi; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200145 CFI_ADJUST_CFA_OFFSET -4;\
146 CFI_RESTORE esi;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 popl %edi; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200148 CFI_ADJUST_CFA_OFFSET -4;\
149 CFI_RESTORE edi;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 popl %ebp; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200151 CFI_ADJUST_CFA_OFFSET -4;\
152 CFI_RESTORE ebp;\
153 popl %eax; \
154 CFI_ADJUST_CFA_OFFSET -4;\
155 CFI_RESTORE eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157#define RESTORE_REGS \
158 RESTORE_INT_REGS; \
1591: popl %ds; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200160 CFI_ADJUST_CFA_OFFSET -4;\
161 /*CFI_RESTORE ds;*/\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622: popl %es; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200163 CFI_ADJUST_CFA_OFFSET -4;\
164 /*CFI_RESTORE es;*/\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165.section .fixup,"ax"; \
1663: movl $0,(%esp); \
167 jmp 1b; \
1684: movl $0,(%esp); \
169 jmp 2b; \
170.previous; \
171.section __ex_table,"a";\
172 .align 4; \
173 .long 1b,3b; \
174 .long 2b,4b; \
175.previous
176
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200177#define RING0_INT_FRAME \
178 CFI_STARTPROC simple;\
179 CFI_DEF_CFA esp, 3*4;\
180 /*CFI_OFFSET cs, -2*4;*/\
181 CFI_OFFSET eip, -3*4
182
183#define RING0_EC_FRAME \
184 CFI_STARTPROC simple;\
185 CFI_DEF_CFA esp, 4*4;\
186 /*CFI_OFFSET cs, -2*4;*/\
187 CFI_OFFSET eip, -3*4
188
189#define RING0_PTREGS_FRAME \
190 CFI_STARTPROC simple;\
191 CFI_DEF_CFA esp, OLDESP-EBX;\
192 /*CFI_OFFSET cs, CS-OLDESP;*/\
193 CFI_OFFSET eip, EIP-OLDESP;\
194 /*CFI_OFFSET es, ES-OLDESP;*/\
195 /*CFI_OFFSET ds, DS-OLDESP;*/\
196 CFI_OFFSET eax, EAX-OLDESP;\
197 CFI_OFFSET ebp, EBP-OLDESP;\
198 CFI_OFFSET edi, EDI-OLDESP;\
199 CFI_OFFSET esi, ESI-OLDESP;\
200 CFI_OFFSET edx, EDX-OLDESP;\
201 CFI_OFFSET ecx, ECX-OLDESP;\
202 CFI_OFFSET ebx, EBX-OLDESP
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204ENTRY(ret_from_fork)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200205 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 pushl %eax
Markus Armbruster25d7dfd2006-07-30 03:04:08 -0700207 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 call schedule_tail
209 GET_THREAD_INFO(%ebp)
210 popl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200211 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds47a5c6f2006-09-18 16:20:40 -0700212 pushl $0x0202 # Reset kernel eflags
213 CFI_ADJUST_CFA_OFFSET 4
214 popfl
215 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 jmp syscall_exit
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200217 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219/*
220 * Return to user mode is not as complex as all this looks,
221 * but we want the default path for a system call return to
222 * go as quickly as possible which is why some of this is
223 * less clear than it otherwise should be.
224 */
225
226 # userspace resumption stub bypassing syscall exit tracing
227 ALIGN
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200228 RING0_PTREGS_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229ret_from_exception:
230 preempt_stop
231ret_from_intr:
232 GET_THREAD_INFO(%ebp)
Aleksey Gorelov4031ff32006-06-27 02:53:48 -0700233check_userspace:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
235 movb CS(%esp), %al
236 testl $(VM_MASK | 3), %eax
237 jz resume_kernel
238ENTRY(resume_userspace)
239 cli # make sure we don't miss an interrupt
240 # setting need_resched or sigpending
241 # between sampling and the iret
242 movl TI_flags(%ebp), %ecx
243 andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
244 # int/exception return?
245 jne work_pending
246 jmp restore_all
247
248#ifdef CONFIG_PREEMPT
249ENTRY(resume_kernel)
250 cli
251 cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
252 jnz restore_nocheck
253need_resched:
254 movl TI_flags(%ebp), %ecx # need_resched set ?
255 testb $_TIF_NEED_RESCHED, %cl
256 jz restore_all
257 testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
258 jz restore_all
259 call preempt_schedule_irq
260 jmp need_resched
261#endif
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200262 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264/* SYSENTER_RETURN points to after the "sysenter" instruction in
265 the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
266
267 # sysenter call handler stub
268ENTRY(sysenter_entry)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200269 CFI_STARTPROC simple
270 CFI_DEF_CFA esp, 0
271 CFI_REGISTER esp, ebp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 movl TSS_sysenter_esp0(%esp),%esp
273sysenter_past_esp:
Ingo Molnar55f327f2006-07-03 00:24:43 -0700274 /*
275 * No need to follow this irqs on/off section: the syscall
276 * disabled irqs and here we enable it straight after entry:
277 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 sti
279 pushl $(__USER_DS)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200280 CFI_ADJUST_CFA_OFFSET 4
281 /*CFI_REL_OFFSET ss, 0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 pushl %ebp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200283 CFI_ADJUST_CFA_OFFSET 4
284 CFI_REL_OFFSET esp, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 pushfl
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200286 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 pushl $(__USER_CS)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200288 CFI_ADJUST_CFA_OFFSET 4
289 /*CFI_REL_OFFSET cs, 0*/
Ingo Molnare6e54942006-06-27 02:53:50 -0700290 /*
291 * Push current_thread_info()->sysenter_return to the stack.
292 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
293 * pushed above; +8 corresponds to copy_thread's esp0 setting.
294 */
295 pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200296 CFI_ADJUST_CFA_OFFSET 4
297 CFI_REL_OFFSET eip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299/*
300 * Load the potential sixth argument from user stack.
301 * Careful about security.
302 */
303 cmpl $__PAGE_OFFSET-3,%ebp
304 jae syscall_fault
3051: movl (%ebp),%ebp
306.section __ex_table,"a"
307 .align 4
308 .long 1b,syscall_fault
309.previous
310
311 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200312 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 SAVE_ALL
314 GET_THREAD_INFO(%ebp)
315
316 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
Laurent Viviered75e8d2005-09-03 15:57:18 -0700317 testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 jnz syscall_trace_entry
319 cmpl $(nr_syscalls), %eax
320 jae syscall_badsys
321 call *sys_call_table(,%eax,4)
322 movl %eax,EAX(%esp)
323 cli
Ingo Molnar55f327f2006-07-03 00:24:43 -0700324 TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 movl TI_flags(%ebp), %ecx
326 testw $_TIF_ALLWORK_MASK, %cx
327 jne syscall_exit_work
328/* if something modifies registers it must also disable sysexit */
329 movl EIP(%esp), %edx
330 movl OLDESP(%esp), %ecx
331 xorl %ebp,%ebp
Ingo Molnar55f327f2006-07-03 00:24:43 -0700332 TRACE_IRQS_ON
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 sti
334 sysexit
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200335 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337
338 # system call handler stub
339ENTRY(system_call)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200340 RING0_INT_FRAME # can't unwind into user space anyway
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 pushl %eax # save orig_eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200342 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 SAVE_ALL
344 GET_THREAD_INFO(%ebp)
Chuck Ebbert635cf992006-03-23 02:59:48 -0800345 testl $TF_MASK,EFLAGS(%esp)
346 jz no_singlestep
347 orl $_TIF_SINGLESTEP,TI_flags(%ebp)
348no_singlestep:
Laurent Viviered75e8d2005-09-03 15:57:18 -0700349 # system call tracing in operation / emulation
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
Laurent Viviered75e8d2005-09-03 15:57:18 -0700351 testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 jnz syscall_trace_entry
353 cmpl $(nr_syscalls), %eax
354 jae syscall_badsys
355syscall_call:
356 call *sys_call_table(,%eax,4)
357 movl %eax,EAX(%esp) # store the return value
358syscall_exit:
359 cli # make sure we don't miss an interrupt
360 # setting need_resched or sigpending
361 # between sampling and the iret
Ingo Molnar55f327f2006-07-03 00:24:43 -0700362 TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 movl TI_flags(%ebp), %ecx
364 testw $_TIF_ALLWORK_MASK, %cx # current->work
365 jne syscall_exit_work
366
367restore_all:
368 movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
Stas Sergeev5df24082005-04-16 15:24:01 -0700369 # Warning: OLDSS(%esp) contains the wrong/random values if we
370 # are returning to the kernel.
371 # See comments in process.c:copy_thread() for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 movb OLDSS(%esp), %ah
373 movb CS(%esp), %al
374 andl $(VM_MASK | (4 << 8) | 3), %eax
375 cmpl $((4 << 8) | 3), %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200376 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 je ldt_ss # returning to user-space with LDT SS
378restore_nocheck:
Ingo Molnar55f327f2006-07-03 00:24:43 -0700379 TRACE_IRQS_IRET
380restore_nocheck_notrace:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 RESTORE_REGS
382 addl $4, %esp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200383 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841: iret
385.section .fixup,"ax"
386iret_exc:
Ingo Molnar55f327f2006-07-03 00:24:43 -0700387 TRACE_IRQS_ON
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 sti
Linus Torvaldsa879cbb2005-04-29 09:38:44 -0700389 pushl $0 # no error code
390 pushl $do_iret_error
391 jmp error_code
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392.previous
393.section __ex_table,"a"
394 .align 4
395 .long 1b,iret_exc
396.previous
397
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200398 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399ldt_ss:
400 larl OLDSS(%esp), %eax
401 jnz restore_nocheck
402 testl $0x00400000, %eax # returning to 32bit stack?
403 jnz restore_nocheck # allright, normal return
404 /* If returning to userspace with 16bit stack,
405 * try to fix the higher word of ESP, as the CPU
406 * won't restore it.
407 * This is an "official" bug of all the x86-compatible
408 * CPUs, which we can try to work around to make
409 * dosemu and wine happy. */
410 subl $8, %esp # reserve space for switch16 pointer
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200411 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 cli
Ingo Molnar55f327f2006-07-03 00:24:43 -0700413 TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 movl %esp, %eax
415 /* Set up the 16bit stack frame with switch32 pointer on top,
416 * and a switch16 pointer on top of the current frame. */
417 call setup_x86_bogus_stack
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200418 CFI_ADJUST_CFA_OFFSET -8 # frame has moved
Ingo Molnar55f327f2006-07-03 00:24:43 -0700419 TRACE_IRQS_IRET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 RESTORE_REGS
421 lss 20+4(%esp), %esp # switch to 16bit stack
4221: iret
423.section __ex_table,"a"
424 .align 4
425 .long 1b,iret_exc
426.previous
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200427 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 # perform work that needs to be done immediately before resumption
430 ALIGN
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200431 RING0_PTREGS_FRAME # can't unwind into user space anyway
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432work_pending:
433 testb $_TIF_NEED_RESCHED, %cl
434 jz work_notifysig
435work_resched:
436 call schedule
437 cli # make sure we don't miss an interrupt
438 # setting need_resched or sigpending
439 # between sampling and the iret
Ingo Molnar55f327f2006-07-03 00:24:43 -0700440 TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 movl TI_flags(%ebp), %ecx
442 andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
443 # than syscall tracing?
444 jz restore_all
445 testb $_TIF_NEED_RESCHED, %cl
446 jnz work_resched
447
448work_notifysig: # deal with pending signals and
449 # notify-resume requests
450 testl $VM_MASK, EFLAGS(%esp)
451 movl %esp, %eax
452 jne work_notifysig_v86 # returning to kernel-space or
453 # vm86-space
454 xorl %edx, %edx
455 call do_notify_resume
Aleksey Gorelov4031ff32006-06-27 02:53:48 -0700456 jmp resume_userspace_sig
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
458 ALIGN
459work_notifysig_v86:
Matt Mackall64ca9002006-01-08 01:05:26 -0800460#ifdef CONFIG_VM86
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 pushl %ecx # save ti_flags for do_notify_resume
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200462 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 call save_v86_state # %eax contains pt_regs pointer
464 popl %ecx
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200465 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 movl %eax, %esp
467 xorl %edx, %edx
468 call do_notify_resume
Aleksey Gorelov4031ff32006-06-27 02:53:48 -0700469 jmp resume_userspace_sig
Matt Mackall64ca9002006-01-08 01:05:26 -0800470#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 # perform syscall exit tracing
473 ALIGN
474syscall_trace_entry:
475 movl $-ENOSYS,EAX(%esp)
476 movl %esp, %eax
477 xorl %edx,%edx
478 call do_syscall_trace
Laurent Viviered75e8d2005-09-03 15:57:18 -0700479 cmpl $0, %eax
Paolo 'Blaisorblade' Giarrusso640aa462005-09-03 15:57:22 -0700480 jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU,
Laurent Viviered75e8d2005-09-03 15:57:18 -0700481 # so must skip actual syscall
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 movl ORIG_EAX(%esp), %eax
483 cmpl $(nr_syscalls), %eax
484 jnae syscall_call
485 jmp syscall_exit
486
487 # perform syscall exit tracing
488 ALIGN
489syscall_exit_work:
490 testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
491 jz work_pending
Ingo Molnar55f327f2006-07-03 00:24:43 -0700492 TRACE_IRQS_ON
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 sti # could let do_syscall_trace() call
494 # schedule() instead
495 movl %esp, %eax
496 movl $1, %edx
497 call do_syscall_trace
498 jmp resume_userspace
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200499 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200501 RING0_INT_FRAME # can't unwind into user space anyway
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502syscall_fault:
503 pushl %eax # save orig_eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200504 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 SAVE_ALL
506 GET_THREAD_INFO(%ebp)
507 movl $-EFAULT,EAX(%esp)
508 jmp resume_userspace
509
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510syscall_badsys:
511 movl $-ENOSYS,EAX(%esp)
512 jmp resume_userspace
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200513 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515#define FIXUP_ESPFIX_STACK \
516 movl %esp, %eax; \
517 /* switch to 32bit stack using the pointer on top of 16bit stack */ \
518 lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
519 /* copy data from 16bit stack to 32bit stack */ \
520 call fixup_x86_bogus_stack; \
521 /* put ESP to the proper location */ \
522 movl %eax, %esp;
523#define UNWIND_ESPFIX_STACK \
524 pushl %eax; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200525 CFI_ADJUST_CFA_OFFSET 4; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 movl %ss, %eax; \
527 /* see if on 16bit stack */ \
528 cmpw $__ESPFIX_SS, %ax; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200529 je 28f; \
53027: popl %eax; \
531 CFI_ADJUST_CFA_OFFSET -4; \
532.section .fixup,"ax"; \
53328: movl $__KERNEL_DS, %eax; \
534 movl %eax, %ds; \
535 movl %eax, %es; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 /* switch to 32bit stack */ \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200537 FIXUP_ESPFIX_STACK; \
538 jmp 27b; \
539.previous
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
541/*
542 * Build the entry stubs and pointer table with
543 * some assembler magic.
544 */
545.data
546ENTRY(interrupt)
547.text
548
549vector=0
550ENTRY(irq_entries_start)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200551 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552.rept NR_IRQS
553 ALIGN
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200554 .if vector
555 CFI_ADJUST_CFA_OFFSET -4
556 .endif
Rusty Russell19eadf92006-06-27 02:53:44 -07005571: pushl $~(vector)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200558 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 jmp common_interrupt
560.data
561 .long 1b
562.text
563vector=vector+1
564.endr
565
Ingo Molnar55f327f2006-07-03 00:24:43 -0700566/*
567 * the CPU automatically disables interrupts when executing an IRQ vector,
568 * so IRQ-flags tracing has to follow that:
569 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 ALIGN
571common_interrupt:
572 SAVE_ALL
Ingo Molnar55f327f2006-07-03 00:24:43 -0700573 TRACE_IRQS_OFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 movl %esp,%eax
575 call do_IRQ
576 jmp ret_from_intr
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200577 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
579#define BUILD_INTERRUPT(name, nr) \
580ENTRY(name) \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200581 RING0_INT_FRAME; \
Rusty Russell19eadf92006-06-27 02:53:44 -0700582 pushl $~(nr); \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200583 CFI_ADJUST_CFA_OFFSET 4; \
584 SAVE_ALL; \
Ingo Molnar55f327f2006-07-03 00:24:43 -0700585 TRACE_IRQS_OFF \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 movl %esp,%eax; \
587 call smp_/**/name; \
Ingo Molnar55f327f2006-07-03 00:24:43 -0700588 jmp ret_from_intr; \
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200589 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591/* The include is where all of the SMP etc. interrupts come from */
592#include "entry_arch.h"
593
594ENTRY(divide_error)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200595 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 pushl $0 # no error code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200597 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 pushl $do_divide_error
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200599 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 ALIGN
601error_code:
602 pushl %ds
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200603 CFI_ADJUST_CFA_OFFSET 4
604 /*CFI_REL_OFFSET ds, 0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200606 CFI_ADJUST_CFA_OFFSET 4
607 CFI_REL_OFFSET eax, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 xorl %eax, %eax
609 pushl %ebp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200610 CFI_ADJUST_CFA_OFFSET 4
611 CFI_REL_OFFSET ebp, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 pushl %edi
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200613 CFI_ADJUST_CFA_OFFSET 4
614 CFI_REL_OFFSET edi, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 pushl %esi
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200616 CFI_ADJUST_CFA_OFFSET 4
617 CFI_REL_OFFSET esi, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 pushl %edx
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200619 CFI_ADJUST_CFA_OFFSET 4
620 CFI_REL_OFFSET edx, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 decl %eax # eax = -1
622 pushl %ecx
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200623 CFI_ADJUST_CFA_OFFSET 4
624 CFI_REL_OFFSET ecx, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 pushl %ebx
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200626 CFI_ADJUST_CFA_OFFSET 4
627 CFI_REL_OFFSET ebx, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 cld
629 pushl %es
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200630 CFI_ADJUST_CFA_OFFSET 4
631 /*CFI_REL_OFFSET es, 0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 UNWIND_ESPFIX_STACK
633 popl %ecx
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200634 CFI_ADJUST_CFA_OFFSET -4
635 /*CFI_REGISTER es, ecx*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 movl ES(%esp), %edi # get the function address
637 movl ORIG_EAX(%esp), %edx # get the error code
638 movl %eax, ORIG_EAX(%esp)
639 movl %ecx, ES(%esp)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200640 /*CFI_REL_OFFSET es, ES*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 movl $(__USER_DS), %ecx
642 movl %ecx, %ds
643 movl %ecx, %es
644 movl %esp,%eax # pt_regs pointer
645 call *%edi
646 jmp ret_from_exception
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200647 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
649ENTRY(coprocessor_error)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200650 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200652 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 pushl $do_coprocessor_error
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200654 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200656 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658ENTRY(simd_coprocessor_error)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200659 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200661 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 pushl $do_simd_coprocessor_error
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200663 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200665 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667ENTRY(device_not_available)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200668 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 pushl $-1 # mark this as an int
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200670 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 SAVE_ALL
672 movl %cr0, %eax
673 testl $0x4, %eax # EM (math emulation bit)
674 jne device_not_available_emulate
675 preempt_stop
676 call math_state_restore
677 jmp ret_from_exception
678device_not_available_emulate:
679 pushl $0 # temporary storage for ORIG_EIP
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200680 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 call math_emulate
682 addl $4, %esp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200683 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 jmp ret_from_exception
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200685 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687/*
688 * Debug traps and NMI can happen at the one SYSENTER instruction
689 * that sets up the real kernel stack. Check here, since we can't
690 * allow the wrong stack to be used.
691 *
692 * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
693 * already pushed 3 words if it hits on the sysenter instruction:
694 * eflags, cs and eip.
695 *
696 * We just load the right stack, and push the three (known) values
697 * by hand onto the new stack - while updating the return eip past
698 * the instruction that would have done it for sysenter.
699 */
700#define FIX_STACK(offset, ok, label) \
701 cmpw $__KERNEL_CS,4(%esp); \
702 jne ok; \
703label: \
704 movl TSS_sysenter_esp0+offset(%esp),%esp; \
705 pushfl; \
706 pushl $__KERNEL_CS; \
707 pushl $sysenter_past_esp
708
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700709KPROBE_ENTRY(debug)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200710 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 cmpl $sysenter_entry,(%esp)
712 jne debug_stack_correct
713 FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
714debug_stack_correct:
715 pushl $-1 # mark this as an int
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200716 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 SAVE_ALL
718 xorl %edx,%edx # error code 0
719 movl %esp,%eax # pt_regs pointer
720 call do_debug
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 jmp ret_from_exception
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200722 CFI_ENDPROC
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700723 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724/*
725 * NMI is doubly nasty. It can happen _while_ we're handling
726 * a debug fault, and the debug fault hasn't yet been able to
727 * clear up the stack. So we first check whether we got an
728 * NMI on the sysenter entry path, but after that we need to
729 * check whether we got an NMI on the debug path where the debug
730 * fault happened on the sysenter path.
731 */
732ENTRY(nmi)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200733 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200735 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 movl %ss, %eax
737 cmpw $__ESPFIX_SS, %ax
738 popl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200739 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 je nmi_16bit_stack
741 cmpl $sysenter_entry,(%esp)
742 je nmi_stack_fixup
743 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200744 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 movl %esp,%eax
746 /* Do not access memory above the end of our stack page,
747 * it might not exist.
748 */
749 andl $(THREAD_SIZE-1),%eax
750 cmpl $(THREAD_SIZE-20),%eax
751 popl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200752 CFI_ADJUST_CFA_OFFSET -4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 jae nmi_stack_correct
754 cmpl $sysenter_entry,12(%esp)
755 je nmi_debug_stack_check
756nmi_stack_correct:
757 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200758 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 SAVE_ALL
760 xorl %edx,%edx # zero error code
761 movl %esp,%eax # pt_regs pointer
762 call do_nmi
Ingo Molnar55f327f2006-07-03 00:24:43 -0700763 jmp restore_nocheck_notrace
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200764 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766nmi_stack_fixup:
767 FIX_STACK(12,nmi_stack_correct, 1)
768 jmp nmi_stack_correct
769nmi_debug_stack_check:
770 cmpw $__KERNEL_CS,16(%esp)
771 jne nmi_stack_correct
Jan Beuliche2718202005-11-13 16:06:52 -0800772 cmpl $debug,(%esp)
773 jb nmi_stack_correct
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 cmpl $debug_esp_fix_insn,(%esp)
Jan Beuliche2718202005-11-13 16:06:52 -0800775 ja nmi_stack_correct
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 FIX_STACK(24,nmi_stack_correct, 1)
777 jmp nmi_stack_correct
778
779nmi_16bit_stack:
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200780 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /* create the pointer to lss back */
782 pushl %ss
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200783 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 pushl %esp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200785 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 movzwl %sp, %esp
787 addw $4, (%esp)
788 /* copy the iret frame of 12 bytes */
789 .rept 3
790 pushl 16(%esp)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200791 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 .endr
793 pushl %eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200794 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 SAVE_ALL
796 FIXUP_ESPFIX_STACK # %eax == %esp
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200797 CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 xorl %edx,%edx # zero error code
799 call do_nmi
800 RESTORE_REGS
801 lss 12+4(%esp), %esp # back to 16bit stack
8021: iret
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200803 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804.section __ex_table,"a"
805 .align 4
806 .long 1b,iret_exc
807.previous
808
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700809KPROBE_ENTRY(int3)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200810 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 pushl $-1 # mark this as an int
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200812 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 SAVE_ALL
814 xorl %edx,%edx # zero error code
815 movl %esp,%eax # pt_regs pointer
816 call do_int3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 jmp ret_from_exception
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200818 CFI_ENDPROC
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700819 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821ENTRY(overflow)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200822 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200824 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 pushl $do_overflow
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200826 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200828 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
830ENTRY(bounds)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200831 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200833 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 pushl $do_bounds
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200835 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200837 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839ENTRY(invalid_op)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200840 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200842 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 pushl $do_invalid_op
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200844 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200846 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
848ENTRY(coprocessor_segment_overrun)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200849 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200851 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 pushl $do_coprocessor_segment_overrun
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200853 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200855 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
857ENTRY(invalid_TSS)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200858 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 pushl $do_invalid_TSS
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200860 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200862 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864ENTRY(segment_not_present)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200865 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 pushl $do_segment_not_present
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200867 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200869 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
871ENTRY(stack_segment)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200872 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 pushl $do_stack_segment
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200874 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200876 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700878KPROBE_ENTRY(general_protection)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200879 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 pushl $do_general_protection
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200881 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200883 CFI_ENDPROC
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700884 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886ENTRY(alignment_check)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200887 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 pushl $do_alignment_check
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200889 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200891 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700893KPROBE_ENTRY(page_fault)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200894 RING0_EC_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 pushl $do_page_fault
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200896 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200898 CFI_ENDPROC
Prasanna S Panchamukhi3d97ae52005-09-06 15:19:27 -0700899 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901#ifdef CONFIG_X86_MCE
902ENTRY(machine_check)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200903 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200905 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 pushl machine_check_vector
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200907 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200909 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910#endif
911
912ENTRY(spurious_interrupt_bug)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200913 RING0_INT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 pushl $0
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200915 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 pushl $do_spurious_interrupt_bug
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200917 CFI_ADJUST_CFA_OFFSET 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 jmp error_code
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200919 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Jan Beulich176a2712006-06-26 13:57:41 +0200921#ifdef CONFIG_STACK_UNWIND
922ENTRY(arch_unwind_init_running)
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200923 CFI_STARTPROC
Jan Beulich176a2712006-06-26 13:57:41 +0200924 movl 4(%esp), %edx
925 movl (%esp), %ecx
926 leal 4(%esp), %eax
927 movl %ebx, EBX(%edx)
928 xorl %ebx, %ebx
929 movl %ebx, ECX(%edx)
930 movl %ebx, EDX(%edx)
931 movl %esi, ESI(%edx)
932 movl %edi, EDI(%edx)
933 movl %ebp, EBP(%edx)
934 movl %ebx, EAX(%edx)
935 movl $__USER_DS, DS(%edx)
936 movl $__USER_DS, ES(%edx)
937 movl %ebx, ORIG_EAX(%edx)
938 movl %ecx, EIP(%edx)
939 movl 12(%esp), %ecx
940 movl $__KERNEL_CS, CS(%edx)
941 movl %ebx, EFLAGS(%edx)
942 movl %eax, OLDESP(%edx)
943 movl 8(%esp), %eax
944 movl %ecx, 8(%esp)
945 movl EBX(%edx), %ebx
946 movl $__KERNEL_DS, OLDSS(%edx)
947 jmpl *%eax
Jan Beulichfe7cacc2006-06-26 13:57:44 +0200948 CFI_ENDPROC
Jan Beulich176a2712006-06-26 13:57:41 +0200949ENDPROC(arch_unwind_init_running)
950#endif
951
Arjan van de Venbb152f52006-01-06 00:12:05 -0800952.section .rodata,"a"
Paolo 'Blaisorblade' Giarrusso5e7b83f2005-05-01 08:58:55 -0700953#include "syscall_table.S"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955syscall_table_size=(.-sys_call_table)