linux/arch/i386/kernel/entry.S
<<
>>
Prefs
   1/*
   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 'syscall_exit':
  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) - %fs
  34 *      28(%esp) - orig_eax
  35 *      2C(%esp) - %eip
  36 *      30(%esp) - %cs
  37 *      34(%esp) - %eflags
  38 *      38(%esp) - %oldesp
  39 *      3C(%esp) - %oldss
  40 *
  41 * "current" is in register %ebx during any slow entries.
  42 */
  43
  44#include <linux/linkage.h>
  45#include <asm/thread_info.h>
  46#include <asm/irqflags.h>
  47#include <asm/errno.h>
  48#include <asm/segment.h>
  49#include <asm/smp.h>
  50#include <asm/page.h>
  51#include <asm/desc.h>
  52#include <asm/percpu.h>
  53#include <asm/dwarf2.h>
  54#include "irq_vectors.h"
  55
  56/*
  57 * We use macros for low-level operations which need to be overridden
  58 * for paravirtualization.  The following will never clobber any registers:
  59 *   INTERRUPT_RETURN (aka. "iret")
  60 *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
  61 *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
  62 *
  63 * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
  64 * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
  65 * Allowing a register to be clobbered can shrink the paravirt replacement
  66 * enough to patch inline, increasing performance.
  67 */
  68
  69#define nr_syscalls ((syscall_table_size)/4)
  70
  71CF_MASK         = 0x00000001
  72TF_MASK         = 0x00000100
  73IF_MASK         = 0x00000200
  74DF_MASK         = 0x00000400 
  75NT_MASK         = 0x00004000
  76VM_MASK         = 0x00020000
  77
  78#ifdef CONFIG_PREEMPT
  79#define preempt_stop(clobbers)  DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
  80#else
  81#define preempt_stop(clobbers)
  82#define resume_kernel           restore_nocheck
  83#endif
  84
  85.macro TRACE_IRQS_IRET
  86#ifdef CONFIG_TRACE_IRQFLAGS
  87        testl $IF_MASK,PT_EFLAGS(%esp)     # interrupts off?
  88        jz 1f
  89        TRACE_IRQS_ON
  901:
  91#endif
  92.endm
  93
  94#ifdef CONFIG_VM86
  95#define resume_userspace_sig    check_userspace
  96#else
  97#define resume_userspace_sig    resume_userspace
  98#endif
  99
 100#define SAVE_ALL \
 101        cld; \
 102        pushl %fs; \
 103        CFI_ADJUST_CFA_OFFSET 4;\
 104        /*CFI_REL_OFFSET fs, 0;*/\
 105        pushl %es; \
 106        CFI_ADJUST_CFA_OFFSET 4;\
 107        /*CFI_REL_OFFSET es, 0;*/\
 108        pushl %ds; \
 109        CFI_ADJUST_CFA_OFFSET 4;\
 110        /*CFI_REL_OFFSET ds, 0;*/\
 111        pushl %eax; \
 112        CFI_ADJUST_CFA_OFFSET 4;\
 113        CFI_REL_OFFSET eax, 0;\
 114        pushl %ebp; \
 115        CFI_ADJUST_CFA_OFFSET 4;\
 116        CFI_REL_OFFSET ebp, 0;\
 117        pushl %edi; \
 118        CFI_ADJUST_CFA_OFFSET 4;\
 119        CFI_REL_OFFSET edi, 0;\
 120        pushl %esi; \
 121        CFI_ADJUST_CFA_OFFSET 4;\
 122        CFI_REL_OFFSET esi, 0;\
 123        pushl %edx; \
 124        CFI_ADJUST_CFA_OFFSET 4;\
 125        CFI_REL_OFFSET edx, 0;\
 126        pushl %ecx; \
 127        CFI_ADJUST_CFA_OFFSET 4;\
 128        CFI_REL_OFFSET ecx, 0;\
 129        pushl %ebx; \
 130        CFI_ADJUST_CFA_OFFSET 4;\
 131        CFI_REL_OFFSET ebx, 0;\
 132        movl $(__USER_DS), %edx; \
 133        movl %edx, %ds; \
 134        movl %edx, %es; \
 135        movl $(__KERNEL_PERCPU), %edx; \
 136        movl %edx, %fs
 137
 138#define RESTORE_INT_REGS \
 139        popl %ebx;      \
 140        CFI_ADJUST_CFA_OFFSET -4;\
 141        CFI_RESTORE ebx;\
 142        popl %ecx;      \
 143        CFI_ADJUST_CFA_OFFSET -4;\
 144        CFI_RESTORE ecx;\
 145        popl %edx;      \
 146        CFI_ADJUST_CFA_OFFSET -4;\
 147        CFI_RESTORE edx;\
 148        popl %esi;      \
 149        CFI_ADJUST_CFA_OFFSET -4;\
 150        CFI_RESTORE esi;\
 151        popl %edi;      \
 152        CFI_ADJUST_CFA_OFFSET -4;\
 153        CFI_RESTORE edi;\
 154        popl %ebp;      \
 155        CFI_ADJUST_CFA_OFFSET -4;\
 156        CFI_RESTORE ebp;\
 157        popl %eax;      \
 158        CFI_ADJUST_CFA_OFFSET -4;\
 159        CFI_RESTORE eax
 160
 161#define RESTORE_REGS    \
 162        RESTORE_INT_REGS; \
 1631:      popl %ds;       \
 164        CFI_ADJUST_CFA_OFFSET -4;\
 165        /*CFI_RESTORE ds;*/\
 1662:      popl %es;       \
 167        CFI_ADJUST_CFA_OFFSET -4;\
 168        /*CFI_RESTORE es;*/\
 1693:      popl %fs;       \
 170        CFI_ADJUST_CFA_OFFSET -4;\
 171        /*CFI_RESTORE fs;*/\
 172.pushsection .fixup,"ax";       \
 1734:      movl $0,(%esp); \
 174        jmp 1b;         \
 1755:      movl $0,(%esp); \
 176        jmp 2b;         \
 1776:      movl $0,(%esp); \
 178        jmp 3b;         \
 179.section __ex_table,"a";\
 180        .align 4;       \
 181        .long 1b,4b;    \
 182        .long 2b,5b;    \
 183        .long 3b,6b;    \
 184.popsection
 185
 186#define RING0_INT_FRAME \
 187        CFI_STARTPROC simple;\
 188        CFI_SIGNAL_FRAME;\
 189        CFI_DEF_CFA esp, 3*4;\
 190        /*CFI_OFFSET cs, -2*4;*/\
 191        CFI_OFFSET eip, -3*4
 192
 193#define RING0_EC_FRAME \
 194        CFI_STARTPROC simple;\
 195        CFI_SIGNAL_FRAME;\
 196        CFI_DEF_CFA esp, 4*4;\
 197        /*CFI_OFFSET cs, -2*4;*/\
 198        CFI_OFFSET eip, -3*4
 199
 200#define RING0_PTREGS_FRAME \
 201        CFI_STARTPROC simple;\
 202        CFI_SIGNAL_FRAME;\
 203        CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\
 204        /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\
 205        CFI_OFFSET eip, PT_EIP-PT_OLDESP;\
 206        /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\
 207        /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\
 208        CFI_OFFSET eax, PT_EAX-PT_OLDESP;\
 209        CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\
 210        CFI_OFFSET edi, PT_EDI-PT_OLDESP;\
 211        CFI_OFFSET esi, PT_ESI-PT_OLDESP;\
 212        CFI_OFFSET edx, PT_EDX-PT_OLDESP;\
 213        CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\
 214        CFI_OFFSET ebx, PT_EBX-PT_OLDESP
 215
 216ENTRY(ret_from_fork)
 217        CFI_STARTPROC
 218        pushl %eax
 219        CFI_ADJUST_CFA_OFFSET 4
 220        call schedule_tail
 221        GET_THREAD_INFO(%ebp)
 222        popl %eax
 223        CFI_ADJUST_CFA_OFFSET -4
 224        pushl $0x0202                   # Reset kernel eflags
 225        CFI_ADJUST_CFA_OFFSET 4
 226        popfl
 227        CFI_ADJUST_CFA_OFFSET -4
 228        jmp syscall_exit
 229        CFI_ENDPROC
 230END(ret_from_fork)
 231
 232/*
 233 * Return to user mode is not as complex as all this looks,
 234 * but we want the default path for a system call return to
 235 * go as quickly as possible which is why some of this is
 236 * less clear than it otherwise should be.
 237 */
 238
 239        # userspace resumption stub bypassing syscall exit tracing
 240        ALIGN
 241        RING0_PTREGS_FRAME
 242ret_from_exception:
 243        preempt_stop(CLBR_ANY)
 244ret_from_intr:
 245        GET_THREAD_INFO(%ebp)
 246check_userspace:
 247        movl PT_EFLAGS(%esp), %eax      # mix EFLAGS and CS
 248        movb PT_CS(%esp), %al
 249        andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
 250        cmpl $USER_RPL, %eax
 251        jb resume_kernel                # not returning to v8086 or userspace
 252
 253ENTRY(resume_userspace)
 254        DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
 255                                        # setting need_resched or sigpending
 256                                        # between sampling and the iret
 257        movl TI_flags(%ebp), %ecx
 258        andl $_TIF_WORK_MASK, %ecx      # is there any work to be done on
 259                                        # int/exception return?
 260        jne work_pending
 261        jmp restore_all
 262END(ret_from_exception)
 263
 264#ifdef CONFIG_PREEMPT
 265ENTRY(resume_kernel)
 266        DISABLE_INTERRUPTS(CLBR_ANY)
 267        cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?
 268        jnz restore_nocheck
 269need_resched:
 270        movl TI_flags(%ebp), %ecx       # need_resched set ?
 271        testb $_TIF_NEED_RESCHED, %cl
 272        jz restore_all
 273        testl $IF_MASK,PT_EFLAGS(%esp)  # interrupts off (exception path) ?
 274        jz restore_all
 275        call preempt_schedule_irq
 276        jmp need_resched
 277END(resume_kernel)
 278#endif
 279        CFI_ENDPROC
 280
 281/* SYSENTER_RETURN points to after the "sysenter" instruction in
 282   the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
 283
 284        # sysenter call handler stub
 285ENTRY(sysenter_entry)
 286        CFI_STARTPROC simple
 287        CFI_SIGNAL_FRAME
 288        CFI_DEF_CFA esp, 0
 289        CFI_REGISTER esp, ebp
 290        movl TSS_sysenter_esp0(%esp),%esp
 291sysenter_past_esp:
 292        /*
 293         * No need to follow this irqs on/off section: the syscall
 294         * disabled irqs and here we enable it straight after entry:
 295         */
 296        ENABLE_INTERRUPTS(CLBR_NONE)
 297        pushl $(__USER_DS)
 298        CFI_ADJUST_CFA_OFFSET 4
 299        /*CFI_REL_OFFSET ss, 0*/
 300        pushl %ebp
 301        CFI_ADJUST_CFA_OFFSET 4
 302        CFI_REL_OFFSET esp, 0
 303        pushfl
 304        CFI_ADJUST_CFA_OFFSET 4
 305        pushl $(__USER_CS)
 306        CFI_ADJUST_CFA_OFFSET 4
 307        /*CFI_REL_OFFSET cs, 0*/
 308        /*
 309         * Push current_thread_info()->sysenter_return to the stack.
 310         * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
 311         * pushed above; +8 corresponds to copy_thread's esp0 setting.
 312         */
 313        pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
 314        CFI_ADJUST_CFA_OFFSET 4
 315        CFI_REL_OFFSET eip, 0
 316
 317/*
 318 * Load the potential sixth argument from user stack.
 319 * Careful about security.
 320 */
 321        cmpl $__PAGE_OFFSET-3,%ebp
 322        jae syscall_fault
 3231:      movl (%ebp),%ebp
 324.section __ex_table,"a"
 325        .align 4
 326        .long 1b,syscall_fault
 327.previous
 328
 329        pushl %eax
 330        CFI_ADJUST_CFA_OFFSET 4
 331        SAVE_ALL
 332        GET_THREAD_INFO(%ebp)
 333
 334        /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 335        testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 336        jnz syscall_trace_entry
 337        cmpl $(nr_syscalls), %eax
 338        jae syscall_badsys
 339        call *sys_call_table(,%eax,4)
 340        movl %eax,PT_EAX(%esp)
 341        DISABLE_INTERRUPTS(CLBR_ANY)
 342        TRACE_IRQS_OFF
 343        movl TI_flags(%ebp), %ecx
 344        testw $_TIF_ALLWORK_MASK, %cx
 345        jne syscall_exit_work
 346/* if something modifies registers it must also disable sysexit */
 347        movl PT_EIP(%esp), %edx
 348        movl PT_OLDESP(%esp), %ecx
 349        xorl %ebp,%ebp
 350        TRACE_IRQS_ON
 3511:      mov  PT_FS(%esp), %fs
 352        ENABLE_INTERRUPTS_SYSEXIT
 353        CFI_ENDPROC
 354.pushsection .fixup,"ax"
 3552:      movl $0,PT_FS(%esp)
 356        jmp 1b
 357.section __ex_table,"a"
 358        .align 4
 359        .long 1b,2b
 360.popsection
 361ENDPROC(sysenter_entry)
 362
 363        # system call handler stub
 364ENTRY(system_call)
 365        RING0_INT_FRAME                 # can't unwind into user space anyway
 366        pushl %eax                      # save orig_eax
 367        CFI_ADJUST_CFA_OFFSET 4
 368        SAVE_ALL
 369        GET_THREAD_INFO(%ebp)
 370                                        # system call tracing in operation / emulation
 371        /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 372        testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 373        jnz syscall_trace_entry
 374        cmpl $(nr_syscalls), %eax
 375        jae syscall_badsys
 376syscall_call:
 377        call *sys_call_table(,%eax,4)
 378        movl %eax,PT_EAX(%esp)          # store the return value
 379syscall_exit:
 380        DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
 381                                        # setting need_resched or sigpending
 382                                        # between sampling and the iret
 383        TRACE_IRQS_OFF
 384        testl $TF_MASK,PT_EFLAGS(%esp)  # If tracing set singlestep flag on exit
 385        jz no_singlestep
 386        orl $_TIF_SINGLESTEP,TI_flags(%ebp)
 387no_singlestep:
 388        movl TI_flags(%ebp), %ecx
 389        testw $_TIF_ALLWORK_MASK, %cx   # current->work
 390        jne syscall_exit_work
 391
 392restore_all:
 393        movl PT_EFLAGS(%esp), %eax      # mix EFLAGS, SS and CS
 394        # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
 395        # are returning to the kernel.
 396        # See comments in process.c:copy_thread() for details.
 397        movb PT_OLDSS(%esp), %ah
 398        movb PT_CS(%esp), %al
 399        andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
 400        cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
 401        CFI_REMEMBER_STATE
 402        je ldt_ss                       # returning to user-space with LDT SS
 403restore_nocheck:
 404        TRACE_IRQS_IRET
 405restore_nocheck_notrace:
 406        RESTORE_REGS
 407        addl $4, %esp                   # skip orig_eax/error_code
 408        CFI_ADJUST_CFA_OFFSET -4
 4091:      INTERRUPT_RETURN
 410.section .fixup,"ax"
 411iret_exc:
 412        TRACE_IRQS_ON
 413        ENABLE_INTERRUPTS(CLBR_NONE)
 414        pushl $0                        # no error code
 415        pushl $do_iret_error
 416        jmp error_code
 417.previous
 418.section __ex_table,"a"
 419        .align 4
 420        .long 1b,iret_exc
 421.previous
 422
 423        CFI_RESTORE_STATE
 424ldt_ss:
 425        larl PT_OLDSS(%esp), %eax
 426        jnz restore_nocheck
 427        testl $0x00400000, %eax         # returning to 32bit stack?
 428        jnz restore_nocheck             # allright, normal return
 429
 430#ifdef CONFIG_PARAVIRT
 431        /*
 432         * The kernel can't run on a non-flat stack if paravirt mode
 433         * is active.  Rather than try to fixup the high bits of
 434         * ESP, bypass this code entirely.  This may break DOSemu
 435         * and/or Wine support in a paravirt VM, although the option
 436         * is still available to implement the setting of the high
 437         * 16-bits in the INTERRUPT_RETURN paravirt-op.
 438         */
 439        cmpl $0, paravirt_ops+PARAVIRT_enabled
 440        jne restore_nocheck
 441#endif
 442
 443        /* If returning to userspace with 16bit stack,
 444         * try to fix the higher word of ESP, as the CPU
 445         * won't restore it.
 446         * This is an "official" bug of all the x86-compatible
 447         * CPUs, which we can try to work around to make
 448         * dosemu and wine happy. */
 449        movl PT_OLDESP(%esp), %eax
 450        movl %esp, %edx
 451        call patch_espfix_desc
 452        pushl $__ESPFIX_SS
 453        CFI_ADJUST_CFA_OFFSET 4
 454        pushl %eax
 455        CFI_ADJUST_CFA_OFFSET 4
 456        DISABLE_INTERRUPTS(CLBR_EAX)
 457        TRACE_IRQS_OFF
 458        lss (%esp), %esp
 459        CFI_ADJUST_CFA_OFFSET -8
 460        jmp restore_nocheck
 461        CFI_ENDPROC
 462ENDPROC(system_call)
 463
 464        # perform work that needs to be done immediately before resumption
 465        ALIGN
 466        RING0_PTREGS_FRAME              # can't unwind into user space anyway
 467work_pending:
 468        testb $_TIF_NEED_RESCHED, %cl
 469        jz work_notifysig
 470work_resched:
 471        call schedule
 472        DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
 473                                        # setting need_resched or sigpending
 474                                        # between sampling and the iret
 475        TRACE_IRQS_OFF
 476        movl TI_flags(%ebp), %ecx
 477        andl $_TIF_WORK_MASK, %ecx      # is there any work to be done other
 478                                        # than syscall tracing?
 479        jz restore_all
 480        testb $_TIF_NEED_RESCHED, %cl
 481        jnz work_resched
 482
 483work_notifysig:                         # deal with pending signals and
 484                                        # notify-resume requests
 485#ifdef CONFIG_VM86
 486        testl $VM_MASK, PT_EFLAGS(%esp)
 487        movl %esp, %eax
 488        jne work_notifysig_v86          # returning to kernel-space or
 489                                        # vm86-space
 490        xorl %edx, %edx
 491        call do_notify_resume
 492        jmp resume_userspace_sig
 493
 494        ALIGN
 495work_notifysig_v86:
 496        pushl %ecx                      # save ti_flags for do_notify_resume
 497        CFI_ADJUST_CFA_OFFSET 4
 498        call save_v86_state             # %eax contains pt_regs pointer
 499        popl %ecx
 500        CFI_ADJUST_CFA_OFFSET -4
 501        movl %eax, %esp
 502#else
 503        movl %esp, %eax
 504#endif
 505        xorl %edx, %edx
 506        call do_notify_resume
 507        jmp resume_userspace_sig
 508END(work_pending)
 509
 510        # perform syscall exit tracing
 511        ALIGN
 512syscall_trace_entry:
 513        movl $-ENOSYS,PT_EAX(%esp)
 514        movl %esp, %eax
 515        xorl %edx,%edx
 516        call do_syscall_trace
 517        cmpl $0, %eax
 518        jne resume_userspace            # ret != 0 -> running under PTRACE_SYSEMU,
 519                                        # so must skip actual syscall
 520        movl PT_ORIG_EAX(%esp), %eax
 521        cmpl $(nr_syscalls), %eax
 522        jnae syscall_call
 523        jmp syscall_exit
 524END(syscall_trace_entry)
 525
 526        # perform syscall exit tracing
 527        ALIGN
 528syscall_exit_work:
 529        testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
 530        jz work_pending
 531        TRACE_IRQS_ON
 532        ENABLE_INTERRUPTS(CLBR_ANY)     # could let do_syscall_trace() call
 533                                        # schedule() instead
 534        movl %esp, %eax
 535        movl $1, %edx
 536        call do_syscall_trace
 537        jmp resume_userspace
 538END(syscall_exit_work)
 539        CFI_ENDPROC
 540
 541        RING0_INT_FRAME                 # can't unwind into user space anyway
 542syscall_fault:
 543        pushl %eax                      # save orig_eax
 544        CFI_ADJUST_CFA_OFFSET 4
 545        SAVE_ALL
 546        GET_THREAD_INFO(%ebp)
 547        movl $-EFAULT,PT_EAX(%esp)
 548        jmp resume_userspace
 549END(syscall_fault)
 550
 551syscall_badsys:
 552        movl $-ENOSYS,PT_EAX(%esp)
 553        jmp resume_userspace
 554END(syscall_badsys)
 555        CFI_ENDPROC
 556
 557#define FIXUP_ESPFIX_STACK \
 558        /* since we are on a wrong stack, we cant make it a C code :( */ \
 559        PER_CPU(gdt_page, %ebx); \
 560        GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
 561        addl %esp, %eax; \
 562        pushl $__KERNEL_DS; \
 563        CFI_ADJUST_CFA_OFFSET 4; \
 564        pushl %eax; \
 565        CFI_ADJUST_CFA_OFFSET 4; \
 566        lss (%esp), %esp; \
 567        CFI_ADJUST_CFA_OFFSET -8;
 568#define UNWIND_ESPFIX_STACK \
 569        movl %ss, %eax; \
 570        /* see if on espfix stack */ \
 571        cmpw $__ESPFIX_SS, %ax; \
 572        jne 27f; \
 573        movl $__KERNEL_DS, %eax; \
 574        movl %eax, %ds; \
 575        movl %eax, %es; \
 576        /* switch to normal stack */ \
 577        FIXUP_ESPFIX_STACK; \
 57827:;
 579
 580/*
 581 * Build the entry stubs and pointer table with
 582 * some assembler magic.
 583 */
 584.data
 585ENTRY(interrupt)
 586.text
 587
 588ENTRY(irq_entries_start)
 589        RING0_INT_FRAME
 590vector=0
 591.rept NR_IRQS
 592        ALIGN
 593 .if vector
 594        CFI_ADJUST_CFA_OFFSET -4
 595 .endif
 5961:      pushl $~(vector)
 597        CFI_ADJUST_CFA_OFFSET 4
 598        jmp common_interrupt
 599 .previous
 600        .long 1b
 601 .text
 602vector=vector+1
 603.endr
 604END(irq_entries_start)
 605
 606.previous
 607END(interrupt)
 608.previous
 609
 610/*
 611 * the CPU automatically disables interrupts when executing an IRQ vector,
 612 * so IRQ-flags tracing has to follow that:
 613 */
 614        ALIGN
 615common_interrupt:
 616        SAVE_ALL
 617        TRACE_IRQS_OFF
 618        movl %esp,%eax
 619        call do_IRQ
 620        jmp ret_from_intr
 621ENDPROC(common_interrupt)
 622        CFI_ENDPROC
 623
 624#define BUILD_INTERRUPT(name, nr)       \
 625ENTRY(name)                             \
 626        RING0_INT_FRAME;                \
 627        pushl $~(nr);                   \
 628        CFI_ADJUST_CFA_OFFSET 4;        \
 629        SAVE_ALL;                       \
 630        TRACE_IRQS_OFF                  \
 631        movl %esp,%eax;                 \
 632        call smp_##name;                \
 633        jmp ret_from_intr;              \
 634        CFI_ENDPROC;                    \
 635ENDPROC(name)
 636
 637/* The include is where all of the SMP etc. interrupts come from */
 638#include "entry_arch.h"
 639
 640KPROBE_ENTRY(page_fault)
 641        RING0_EC_FRAME
 642        pushl $do_page_fault
 643        CFI_ADJUST_CFA_OFFSET 4
 644        ALIGN
 645error_code:
 646        /* the function address is in %fs's slot on the stack */
 647        pushl %es
 648        CFI_ADJUST_CFA_OFFSET 4
 649        /*CFI_REL_OFFSET es, 0*/
 650        pushl %ds
 651        CFI_ADJUST_CFA_OFFSET 4
 652        /*CFI_REL_OFFSET ds, 0*/
 653        pushl %eax
 654        CFI_ADJUST_CFA_OFFSET 4
 655        CFI_REL_OFFSET eax, 0
 656        pushl %ebp
 657        CFI_ADJUST_CFA_OFFSET 4
 658        CFI_REL_OFFSET ebp, 0
 659        pushl %edi
 660        CFI_ADJUST_CFA_OFFSET 4
 661        CFI_REL_OFFSET edi, 0
 662        pushl %esi
 663        CFI_ADJUST_CFA_OFFSET 4
 664        CFI_REL_OFFSET esi, 0
 665        pushl %edx
 666        CFI_ADJUST_CFA_OFFSET 4
 667        CFI_REL_OFFSET edx, 0
 668        pushl %ecx
 669        CFI_ADJUST_CFA_OFFSET 4
 670        CFI_REL_OFFSET ecx, 0
 671        pushl %ebx
 672        CFI_ADJUST_CFA_OFFSET 4
 673        CFI_REL_OFFSET ebx, 0
 674        cld
 675        pushl %fs
 676        CFI_ADJUST_CFA_OFFSET 4
 677        /*CFI_REL_OFFSET fs, 0*/
 678        movl $(__KERNEL_PERCPU), %ecx
 679        movl %ecx, %fs
 680        UNWIND_ESPFIX_STACK
 681        popl %ecx
 682        CFI_ADJUST_CFA_OFFSET -4
 683        /*CFI_REGISTER es, ecx*/
 684        movl PT_FS(%esp), %edi          # get the function address
 685        movl PT_ORIG_EAX(%esp), %edx    # get the error code
 686        movl $-1, PT_ORIG_EAX(%esp)     # no syscall to restart
 687        mov  %ecx, PT_FS(%esp)
 688        /*CFI_REL_OFFSET fs, ES*/
 689        movl $(__USER_DS), %ecx
 690        movl %ecx, %ds
 691        movl %ecx, %es
 692        movl %esp,%eax                  # pt_regs pointer
 693        call *%edi
 694        jmp ret_from_exception
 695        CFI_ENDPROC
 696KPROBE_END(page_fault)
 697
 698ENTRY(coprocessor_error)
 699        RING0_INT_FRAME
 700        pushl $0
 701        CFI_ADJUST_CFA_OFFSET 4
 702        pushl $do_coprocessor_error
 703        CFI_ADJUST_CFA_OFFSET 4
 704        jmp error_code
 705        CFI_ENDPROC
 706END(coprocessor_error)
 707
 708ENTRY(simd_coprocessor_error)
 709        RING0_INT_FRAME
 710        pushl $0
 711        CFI_ADJUST_CFA_OFFSET 4
 712        pushl $do_simd_coprocessor_error
 713        CFI_ADJUST_CFA_OFFSET 4
 714        jmp error_code
 715        CFI_ENDPROC
 716END(simd_coprocessor_error)
 717
 718ENTRY(device_not_available)
 719        RING0_INT_FRAME
 720        pushl $-1                       # mark this as an int
 721        CFI_ADJUST_CFA_OFFSET 4
 722        SAVE_ALL
 723        GET_CR0_INTO_EAX
 724        testl $0x4, %eax                # EM (math emulation bit)
 725        jne device_not_available_emulate
 726        preempt_stop(CLBR_ANY)
 727        call math_state_restore
 728        jmp ret_from_exception
 729device_not_available_emulate:
 730        pushl $0                        # temporary storage for ORIG_EIP
 731        CFI_ADJUST_CFA_OFFSET 4
 732        call math_emulate
 733        addl $4, %esp
 734        CFI_ADJUST_CFA_OFFSET -4
 735        jmp ret_from_exception
 736        CFI_ENDPROC
 737END(device_not_available)
 738
 739/*
 740 * Debug traps and NMI can happen at the one SYSENTER instruction
 741 * that sets up the real kernel stack. Check here, since we can't
 742 * allow the wrong stack to be used.
 743 *
 744 * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
 745 * already pushed 3 words if it hits on the sysenter instruction:
 746 * eflags, cs and eip.
 747 *
 748 * We just load the right stack, and push the three (known) values
 749 * by hand onto the new stack - while updating the return eip past
 750 * the instruction that would have done it for sysenter.
 751 */
 752#define FIX_STACK(offset, ok, label)            \
 753        cmpw $__KERNEL_CS,4(%esp);              \
 754        jne ok;                                 \
 755label:                                          \
 756        movl TSS_sysenter_esp0+offset(%esp),%esp;       \
 757        CFI_DEF_CFA esp, 0;                     \
 758        CFI_UNDEFINED eip;                      \
 759        pushfl;                                 \
 760        CFI_ADJUST_CFA_OFFSET 4;                \
 761        pushl $__KERNEL_CS;                     \
 762        CFI_ADJUST_CFA_OFFSET 4;                \
 763        pushl $sysenter_past_esp;               \
 764        CFI_ADJUST_CFA_OFFSET 4;                \
 765        CFI_REL_OFFSET eip, 0
 766
 767KPROBE_ENTRY(debug)
 768        RING0_INT_FRAME
 769        cmpl $sysenter_entry,(%esp)
 770        jne debug_stack_correct
 771        FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
 772debug_stack_correct:
 773        pushl $-1                       # mark this as an int
 774        CFI_ADJUST_CFA_OFFSET 4
 775        SAVE_ALL
 776        xorl %edx,%edx                  # error code 0
 777        movl %esp,%eax                  # pt_regs pointer
 778        call do_debug
 779        jmp ret_from_exception
 780        CFI_ENDPROC
 781KPROBE_END(debug)
 782
 783/*
 784 * NMI is doubly nasty. It can happen _while_ we're handling
 785 * a debug fault, and the debug fault hasn't yet been able to
 786 * clear up the stack. So we first check whether we got  an
 787 * NMI on the sysenter entry path, but after that we need to
 788 * check whether we got an NMI on the debug path where the debug
 789 * fault happened on the sysenter path.
 790 */
 791KPROBE_ENTRY(nmi)
 792        RING0_INT_FRAME
 793        pushl %eax
 794        CFI_ADJUST_CFA_OFFSET 4
 795        movl %ss, %eax
 796        cmpw $__ESPFIX_SS, %ax
 797        popl %eax
 798        CFI_ADJUST_CFA_OFFSET -4
 799        je nmi_espfix_stack
 800        cmpl $sysenter_entry,(%esp)
 801        je nmi_stack_fixup
 802        pushl %eax
 803        CFI_ADJUST_CFA_OFFSET 4
 804        movl %esp,%eax
 805        /* Do not access memory above the end of our stack page,
 806         * it might not exist.
 807         */
 808        andl $(THREAD_SIZE-1),%eax
 809        cmpl $(THREAD_SIZE-20),%eax
 810        popl %eax
 811        CFI_ADJUST_CFA_OFFSET -4
 812        jae nmi_stack_correct
 813        cmpl $sysenter_entry,12(%esp)
 814        je nmi_debug_stack_check
 815nmi_stack_correct:
 816        /* We have a RING0_INT_FRAME here */
 817        pushl %eax
 818        CFI_ADJUST_CFA_OFFSET 4
 819        SAVE_ALL
 820        xorl %edx,%edx          # zero error code
 821        movl %esp,%eax          # pt_regs pointer
 822        call do_nmi
 823        jmp restore_nocheck_notrace
 824        CFI_ENDPROC
 825
 826nmi_stack_fixup:
 827        RING0_INT_FRAME
 828        FIX_STACK(12,nmi_stack_correct, 1)
 829        jmp nmi_stack_correct
 830
 831nmi_debug_stack_check:
 832        /* We have a RING0_INT_FRAME here */
 833        cmpw $__KERNEL_CS,16(%esp)
 834        jne nmi_stack_correct
 835        cmpl $debug,(%esp)
 836        jb nmi_stack_correct
 837        cmpl $debug_esp_fix_insn,(%esp)
 838        ja nmi_stack_correct
 839        FIX_STACK(24,nmi_stack_correct, 1)
 840        jmp nmi_stack_correct
 841
 842nmi_espfix_stack:
 843        /* We have a RING0_INT_FRAME here.
 844         *
 845         * create the pointer to lss back
 846         */
 847        pushl %ss
 848        CFI_ADJUST_CFA_OFFSET 4
 849        pushl %esp
 850        CFI_ADJUST_CFA_OFFSET 4
 851        addw $4, (%esp)
 852        /* copy the iret frame of 12 bytes */
 853        .rept 3
 854        pushl 16(%esp)
 855        CFI_ADJUST_CFA_OFFSET 4
 856        .endr
 857        pushl %eax
 858        CFI_ADJUST_CFA_OFFSET 4
 859        SAVE_ALL
 860        FIXUP_ESPFIX_STACK              # %eax == %esp
 861        xorl %edx,%edx                  # zero error code
 862        call do_nmi
 863        RESTORE_REGS
 864        lss 12+4(%esp), %esp            # back to espfix stack
 865        CFI_ADJUST_CFA_OFFSET -24
 8661:      INTERRUPT_RETURN
 867        CFI_ENDPROC
 868.section __ex_table,"a"
 869        .align 4
 870        .long 1b,iret_exc
 871.previous
 872KPROBE_END(nmi)
 873
 874#ifdef CONFIG_PARAVIRT
 875ENTRY(native_iret)
 8761:      iret
 877.section __ex_table,"a"
 878        .align 4
 879        .long 1b,iret_exc
 880.previous
 881END(native_iret)
 882
 883ENTRY(native_irq_enable_sysexit)
 884        sti
 885        sysexit
 886END(native_irq_enable_sysexit)
 887#endif
 888
 889KPROBE_ENTRY(int3)
 890        RING0_INT_FRAME
 891        pushl $-1                       # mark this as an int
 892        CFI_ADJUST_CFA_OFFSET 4
 893        SAVE_ALL
 894        xorl %edx,%edx          # zero error code
 895        movl %esp,%eax          # pt_regs pointer
 896        call do_int3
 897        jmp ret_from_exception
 898        CFI_ENDPROC
 899KPROBE_END(int3)
 900
 901ENTRY(overflow)
 902        RING0_INT_FRAME
 903        pushl $0
 904        CFI_ADJUST_CFA_OFFSET 4
 905        pushl $do_overflow
 906        CFI_ADJUST_CFA_OFFSET 4
 907        jmp error_code
 908        CFI_ENDPROC
 909END(overflow)
 910
 911ENTRY(bounds)
 912        RING0_INT_FRAME
 913        pushl $0
 914        CFI_ADJUST_CFA_OFFSET 4
 915        pushl $do_bounds
 916        CFI_ADJUST_CFA_OFFSET 4
 917        jmp error_code
 918        CFI_ENDPROC
 919END(bounds)
 920
 921ENTRY(invalid_op)
 922        RING0_INT_FRAME
 923        pushl $0
 924        CFI_ADJUST_CFA_OFFSET 4
 925        pushl $do_invalid_op
 926        CFI_ADJUST_CFA_OFFSET 4
 927        jmp error_code
 928        CFI_ENDPROC
 929END(invalid_op)
 930
 931ENTRY(coprocessor_segment_overrun)
 932        RING0_INT_FRAME
 933        pushl $0
 934        CFI_ADJUST_CFA_OFFSET 4
 935        pushl $do_coprocessor_segment_overrun
 936        CFI_ADJUST_CFA_OFFSET 4
 937        jmp error_code
 938        CFI_ENDPROC
 939END(coprocessor_segment_overrun)
 940
 941ENTRY(invalid_TSS)
 942        RING0_EC_FRAME
 943        pushl $do_invalid_TSS
 944        CFI_ADJUST_CFA_OFFSET 4
 945        jmp error_code
 946        CFI_ENDPROC
 947END(invalid_TSS)
 948
 949ENTRY(segment_not_present)
 950        RING0_EC_FRAME
 951        pushl $do_segment_not_present
 952        CFI_ADJUST_CFA_OFFSET 4
 953        jmp error_code
 954        CFI_ENDPROC
 955END(segment_not_present)
 956
 957ENTRY(stack_segment)
 958        RING0_EC_FRAME
 959        pushl $do_stack_segment
 960        CFI_ADJUST_CFA_OFFSET 4
 961        jmp error_code
 962        CFI_ENDPROC
 963END(stack_segment)
 964
 965KPROBE_ENTRY(general_protection)
 966        RING0_EC_FRAME
 967        pushl $do_general_protection
 968        CFI_ADJUST_CFA_OFFSET 4
 969        jmp error_code
 970        CFI_ENDPROC
 971KPROBE_END(general_protection)
 972
 973ENTRY(alignment_check)
 974        RING0_EC_FRAME
 975        pushl $do_alignment_check
 976        CFI_ADJUST_CFA_OFFSET 4
 977        jmp error_code
 978        CFI_ENDPROC
 979END(alignment_check)
 980
 981ENTRY(divide_error)
 982        RING0_INT_FRAME
 983        pushl $0                        # no error code
 984        CFI_ADJUST_CFA_OFFSET 4
 985        pushl $do_divide_error
 986        CFI_ADJUST_CFA_OFFSET 4
 987        jmp error_code
 988        CFI_ENDPROC
 989END(divide_error)
 990
 991#ifdef CONFIG_X86_MCE
 992ENTRY(machine_check)
 993        RING0_INT_FRAME
 994        pushl $0
 995        CFI_ADJUST_CFA_OFFSET 4
 996        pushl machine_check_vector
 997        CFI_ADJUST_CFA_OFFSET 4
 998        jmp error_code
 999        CFI_ENDPROC
1000END(machine_check)
1001#endif
1002
1003ENTRY(spurious_interrupt_bug)
1004        RING0_INT_FRAME
1005        pushl $0
1006        CFI_ADJUST_CFA_OFFSET 4
1007        pushl $do_spurious_interrupt_bug
1008        CFI_ADJUST_CFA_OFFSET 4
1009        jmp error_code
1010        CFI_ENDPROC
1011END(spurious_interrupt_bug)
1012
1013ENTRY(kernel_thread_helper)
1014        pushl $0                # fake return address for unwinder
1015        CFI_STARTPROC
1016        movl %edx,%eax
1017        push %edx
1018        CFI_ADJUST_CFA_OFFSET 4
1019        call *%ebx
1020        push %eax
1021        CFI_ADJUST_CFA_OFFSET 4
1022        call do_exit
1023        CFI_ENDPROC
1024ENDPROC(kernel_thread_helper)
1025
1026.section .rodata,"a"
1027#include "syscall_table.S"
1028
1029syscall_table_size=(.-sys_call_table)
1030
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.