The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/exception.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1989, 1990 William F. Jolitz.
    3  * Copyright (c) 1990 The Regents of the University of California.
    4  * Copyright (c) 2007, 2018 The FreeBSD Foundation
    5  * All rights reserved.
    6  *
    7  * Portions of this software were developed by A. Joseph Koshy under
    8  * sponsorship from the FreeBSD Foundation and Google, Inc.
    9  * Portions of this software were developed by Konstantin Belousov
   10  * <kib@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * $FreeBSD$
   37  */
   38 
   39 #include "opt_apic.h"
   40 #include "opt_atpic.h"
   41 #include "opt_hwpmc_hooks.h"
   42 #include "opt_hyperv.h"
   43 
   44 #include "assym.inc"
   45 
   46 #include <machine/psl.h>
   47 #include <machine/asmacros.h>
   48 #include <machine/trap.h>
   49 
   50 #ifdef KDTRACE_HOOKS
   51         .bss
   52         .globl  dtrace_invop_jump_addr
   53         .align  4
   54         .type   dtrace_invop_jump_addr, @object
   55         .size   dtrace_invop_jump_addr, 4
   56 dtrace_invop_jump_addr:
   57         .zero   4
   58         .globl  dtrace_invop_calltrap_addr
   59         .align  4
   60         .type   dtrace_invop_calltrap_addr, @object
   61         .size   dtrace_invop_calltrap_addr, 4
   62 dtrace_invop_calltrap_addr:
   63         .zero   8
   64 #endif
   65         .text
   66 ENTRY(start_exceptions)
   67         .globl  tramp_idleptd
   68 tramp_idleptd:  .long   0
   69 
   70 /*****************************************************************************/
   71 /* Trap handling                                                             */
   72 /*****************************************************************************/
   73 /*
   74  * Trap and fault vector routines.
   75  *
   76  * All traps are 'interrupt gates', SDT_SYS386IGT.  Interrupts are disabled
   77  * by hardware to not allow interrupts until code switched to the kernel
   78  * address space and the kernel thread stack.
   79  *
   80  * The cpu will push a certain amount of state onto the kernel stack for
   81  * the current process.  The amount of state depends on the type of trap
   82  * and whether the trap crossed rings or not.  See i386/include/frame.h.
   83  * At the very least the current EFLAGS (status register, which includes
   84  * the interrupt disable state prior to the trap), the code segment register,
   85  * and the return instruction pointer are pushed by the cpu.  The cpu
   86  * will also push an 'error' code for certain traps.  We push a dummy
   87  * error code for those traps where the cpu doesn't in order to maintain
   88  * a consistent frame.  We also push a contrived 'trap number'.
   89  *
   90  * The cpu does not push the general registers, we must do that, and we
   91  * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
   92  * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
   93  * must load them with appropriate values for supervisor mode operation.
   94  *
   95  * This code is not executed at the linked address, it is copied to the
   96  * trampoline area.  As the consequence, all code there and in included files
   97  * must be PIC.
   98  */
   99 
  100 MCOUNT_LABEL(user)
  101 MCOUNT_LABEL(btrap)
  102 
  103 #define TRAP(a)         pushl $(a) ; jmp alltraps
  104 
  105 IDTVEC(div)
  106         pushl $0; TRAP(T_DIVIDE)
  107 IDTVEC(bpt)
  108         pushl $0; TRAP(T_BPTFLT)
  109 IDTVEC(dtrace_ret)
  110         pushl $0; TRAP(T_DTRACE_RET)
  111 IDTVEC(ofl)
  112         pushl $0; TRAP(T_OFLOW)
  113 IDTVEC(bnd)
  114         pushl $0; TRAP(T_BOUND)
  115 #ifndef KDTRACE_HOOKS
  116 IDTVEC(ill)
  117         pushl $0; TRAP(T_PRIVINFLT)
  118 #endif
  119 IDTVEC(dna)
  120         pushl $0; TRAP(T_DNA)
  121 IDTVEC(fpusegm)
  122         pushl $0; TRAP(T_FPOPFLT)
  123 IDTVEC(tss)
  124         TRAP(T_TSSFLT)
  125 IDTVEC(missing)
  126         pushl   $T_SEGNPFLT
  127         jmp     irettraps
  128 IDTVEC(stk)
  129         pushl   $T_STKFLT
  130         jmp     irettraps
  131 IDTVEC(prot)
  132         pushl   $T_PROTFLT
  133         jmp     irettraps
  134 IDTVEC(page)
  135         testl   $PSL_VM, TF_EFLAGS-TF_ERR(%esp)
  136         jnz     1f
  137         testb   $SEL_RPL_MASK, TF_CS-TF_ERR(%esp)
  138         jnz     1f
  139         cmpl    $PMAP_TRM_MIN_ADDRESS, TF_EIP-TF_ERR(%esp)
  140         jb      1f
  141         movl    %ebx, %cr3
  142         movl    %edx, TF_EIP-TF_ERR(%esp)
  143         addl    $4, %esp
  144         iret
  145 1:      pushl   $T_PAGEFLT
  146         jmp     alltraps
  147 IDTVEC(rsvd_pti)
  148 IDTVEC(rsvd)
  149         pushl $0; TRAP(T_RESERVED)
  150 IDTVEC(fpu)
  151         pushl $0; TRAP(T_ARITHTRAP)
  152 IDTVEC(align)
  153         TRAP(T_ALIGNFLT)
  154 IDTVEC(xmm)
  155         pushl $0; TRAP(T_XMMFLT)
  156 
  157         /*
  158          * All traps except ones for syscalls or invalid segment,
  159          * jump to alltraps.  If
  160          * interrupts were enabled when the trap occurred, then interrupts
  161          * are enabled now if the trap was through a trap gate, else
  162          * disabled if the trap was through an interrupt gate.  Note that
  163          * int0x80_syscall is a trap gate.   Interrupt gates are used by
  164          * page faults, non-maskable interrupts, debug and breakpoint
  165          * exceptions.
  166          */
  167         SUPERALIGN_TEXT
  168         .globl  alltraps
  169         .type   alltraps,@function
  170 alltraps:
  171         PUSH_FRAME2
  172 alltraps_with_regs_pushed:
  173         SET_KERNEL_SREGS
  174         cld
  175         KENTER
  176         FAKE_MCOUNT(TF_EIP(%esp))
  177 calltrap:
  178         pushl   %esp
  179         movl    $trap,%eax
  180         call    *%eax
  181         add     $4, %esp
  182 
  183         /*
  184          * Return via doreti to handle ASTs.
  185          */
  186         MEXITCOUNT
  187         jmp     doreti
  188 
  189         .globl  irettraps
  190         .type   irettraps,@function
  191 irettraps:
  192         testl   $PSL_VM, TF_EFLAGS-TF_TRAPNO(%esp)
  193         jnz     alltraps
  194         testb   $SEL_RPL_MASK, TF_CS-TF_TRAPNO(%esp)
  195         jnz     alltraps
  196 
  197         /*
  198          * Kernel mode.
  199          * The special case there is the kernel mode with user %cr3 and
  200          * trampoline stack. We need to copy both current frame and the
  201          * hardware portion of the frame we tried to return to, to the
  202          * normal stack.  This logic must follow the stack unwind order
  203          * in doreti.
  204          */
  205         PUSH_FRAME2
  206         SET_KERNEL_SREGS
  207         cld
  208         call    1f
  209 1:      popl    %ebx
  210         leal    (doreti_iret - 1b)(%ebx), %edx
  211         cmpl    %edx, TF_EIP(%esp)
  212         jne     2f
  213         movl    $(2 * TF_SZ - TF_EIP), %ecx
  214         jmp     6f
  215 2:      leal    (doreti_popl_ds - 1b)(%ebx), %edx
  216         cmpl    %edx, TF_EIP(%esp)
  217         jne     3f
  218         movl    $(2 * TF_SZ - TF_DS), %ecx
  219         jmp     6f
  220 3:      leal    (doreti_popl_es - 1b)(%ebx), %edx
  221         cmpl    %edx, TF_EIP(%esp)
  222         jne     4f
  223         movl    $(2 * TF_SZ - TF_ES), %ecx
  224         jmp     6f
  225 4:      leal    (doreti_popl_fs - 1b)(%ebx), %edx
  226         cmpl    %edx, TF_EIP(%esp)
  227         jne     5f
  228         movl    $(2 * TF_SZ - TF_FS), %ecx
  229         jmp     6f
  230         /* kernel mode, normal */
  231 5:      FAKE_MCOUNT(TF_EIP(%esp))
  232         jmp     calltrap
  233 6:      cmpl    $PMAP_TRM_MIN_ADDRESS, %esp     /* trampoline stack ? */
  234         jb      5b      /* if not, no need to change stacks */
  235         movl    (tramp_idleptd - 1b)(%ebx), %eax
  236         movl    %eax, %cr3
  237         movl    PCPU(KESP0), %edx
  238         subl    %ecx, %edx
  239         movl    %edx, %edi
  240         movl    %esp, %esi
  241         rep; movsb
  242         movl    %edx, %esp
  243         FAKE_MCOUNT(TF_EIP(%esp))
  244         jmp     calltrap
  245 
  246 /*
  247  * Privileged instruction fault.
  248  */
  249 #ifdef KDTRACE_HOOKS
  250         SUPERALIGN_TEXT
  251 IDTVEC(ill)
  252         /*
  253          * Check if this is a user fault.  If so, just handle it as a normal
  254          * trap.
  255          */
  256         testl   $PSL_VM, 8(%esp)        /* and vm86 mode. */
  257         jnz     norm_ill
  258         cmpl    $GSEL_KPL, 4(%esp)      /* Check the code segment */
  259         jne     norm_ill
  260 
  261         /*
  262          * Check if a DTrace hook is registered.  The trampoline cannot
  263          * be instrumented.
  264          */
  265         cmpl    $0, dtrace_invop_jump_addr
  266         je      norm_ill
  267 
  268         /*
  269          * This is a kernel instruction fault that might have been caused
  270          * by a DTrace provider.
  271          */
  272         pushal
  273         cld
  274 
  275         /*
  276          * Set our jump address for the jump back in the event that
  277          * the exception wasn't caused by DTrace at all.
  278          */
  279         movl    $norm_ill, dtrace_invop_calltrap_addr
  280 
  281         /* Jump to the code hooked in by DTrace. */
  282         jmpl    *dtrace_invop_jump_addr
  283 
  284         /*
  285          * Process the instruction fault in the normal way.
  286          */
  287 norm_ill:
  288         pushl   $0
  289         pushl   $T_PRIVINFLT
  290         jmp     alltraps
  291 #endif
  292 
  293 /*
  294  * See comment in the handler for the kernel case T_TRCTRAP in trap.c.
  295  * The exception handler must be ready to execute with wrong %cr3.
  296  * We save original %cr3 in frame->tf_err, similarly to NMI and MCE
  297  * handlers.
  298  */
  299 IDTVEC(dbg)
  300         pushl   $0
  301         pushl   $T_TRCTRAP
  302         PUSH_FRAME2
  303         SET_KERNEL_SREGS
  304         cld
  305         movl    %cr3, %eax
  306         movl    %eax, TF_ERR(%esp)
  307         call    1f
  308 1:      popl    %eax
  309         movl    (tramp_idleptd - 1b)(%eax), %eax
  310         movl    %eax, %cr3
  311         FAKE_MCOUNT(TF_EIP(%esp))
  312         testl   $PSL_VM, TF_EFLAGS(%esp)
  313         jnz     dbg_user
  314         testb   $SEL_RPL_MASK,TF_CS(%esp)
  315         jz      calltrap
  316 dbg_user:
  317         NMOVE_STACKS
  318         movl    $handle_ibrs_entry,%eax
  319         call    *%eax
  320         pushl   %esp
  321         movl    $trap,%eax
  322         call    *%eax
  323         add     $4, %esp
  324         movl    $T_RESERVED, TF_TRAPNO(%esp)
  325         MEXITCOUNT
  326         jmp     doreti
  327 
  328 IDTVEC(mchk)
  329         pushl   $0
  330         pushl   $T_MCHK
  331         jmp     nmi_mchk_common
  332 
  333 IDTVEC(nmi)
  334         pushl   $0
  335         pushl   $T_NMI
  336 nmi_mchk_common:
  337         PUSH_FRAME2
  338         SET_KERNEL_SREGS
  339         cld
  340         /*
  341          * Save %cr3 into tf_err.  There is no good place to put it.
  342          * Always reload %cr3, since we might have interrupted the
  343          * kernel entry or exit.
  344          * Do not switch to the thread kernel stack, otherwise we might
  345          * obliterate the previous context partially copied from the
  346          * trampoline stack.
  347          * Do not re-enable IBRS, there is no good place to store
  348          * previous state if we come from the kernel.
  349          */
  350         movl    %cr3, %eax
  351         movl    %eax, TF_ERR(%esp)
  352         call    1f
  353 1:      popl    %eax
  354         movl    (tramp_idleptd - 1b)(%eax), %eax
  355         movl    %eax, %cr3
  356         FAKE_MCOUNT(TF_EIP(%esp))
  357         jmp     calltrap
  358 
  359 /*
  360  * Trap gate entry for syscalls (int 0x80).
  361  * This is used by FreeBSD ELF executables, "new" a.out executables, and all
  362  * Linux executables.
  363  *
  364  * Even though the name says 'int0x80', this is actually a trap gate, not an
  365  * interrupt gate.  Thus interrupts are enabled on entry just as they are for
  366  * a normal syscall.
  367  */
  368         SUPERALIGN_TEXT
  369 IDTVEC(int0x80_syscall)
  370         pushl   $2                      /* sizeof "int 0x80" */
  371         pushl   $0                      /* tf_trapno */
  372         PUSH_FRAME2
  373         SET_KERNEL_SREGS
  374         cld
  375         MOVE_STACKS
  376         movl    $handle_ibrs_entry,%eax
  377         call    *%eax
  378         sti
  379         FAKE_MCOUNT(TF_EIP(%esp))
  380         pushl   %esp
  381         movl    $syscall, %eax
  382         call    *%eax
  383         add     $4, %esp
  384         MEXITCOUNT
  385         jmp     doreti
  386 
  387 ENTRY(fork_trampoline)
  388         pushl   %esp                    /* trapframe pointer */
  389         pushl   %ebx                    /* arg1 */
  390         pushl   %esi                    /* function */
  391         movl    $fork_exit, %eax
  392         call    *%eax
  393         addl    $12,%esp
  394         /* cut from syscall */
  395 
  396         /*
  397          * Return via doreti to handle ASTs.
  398          */
  399         MEXITCOUNT
  400         jmp     doreti
  401 
  402 
  403 /*
  404  * To efficiently implement classification of trap and interrupt handlers
  405  * for profiling, there must be only trap handlers between the labels btrap
  406  * and bintr, and only interrupt handlers between the labels bintr and
  407  * eintr.  This is implemented (partly) by including files that contain
  408  * some of the handlers.  Before including the files, set up a normal asm
  409  * environment so that the included files doen't need to know that they are
  410  * included.
  411  */
  412 
  413         .data
  414         .p2align 4
  415         .text
  416         SUPERALIGN_TEXT
  417 MCOUNT_LABEL(bintr)
  418 
  419 #ifdef DEV_ATPIC
  420 #include <i386/i386/atpic_vector.s>
  421 #endif
  422 
  423 #if defined(DEV_APIC) && defined(DEV_ATPIC)
  424         .data
  425         .p2align 4
  426         .text
  427         SUPERALIGN_TEXT
  428 #endif
  429 
  430 #ifdef DEV_APIC
  431 #include <i386/i386/apic_vector.s>
  432 #endif
  433 
  434 #ifdef HYPERV
  435         .data
  436         .p2align 4
  437         .text
  438         SUPERALIGN_TEXT
  439 #include <dev/hyperv/vmbus/i386/vmbus_vector.S>
  440 #endif
  441 
  442         .data
  443         .p2align 4
  444         .text
  445         SUPERALIGN_TEXT
  446 #include <i386/i386/vm86bios.s>
  447 
  448         .text
  449 MCOUNT_LABEL(eintr)
  450 
  451 #include <i386/i386/copyout_fast.s>
  452 
  453 /*
  454  * void doreti(struct trapframe)
  455  *
  456  * Handle return from interrupts, traps and syscalls.
  457  */
  458         .text
  459         SUPERALIGN_TEXT
  460         .type   doreti,@function
  461         .globl  doreti
  462 doreti:
  463         FAKE_MCOUNT($bintr)             /* init "from" bintr -> doreti */
  464 doreti_next:
  465         /*
  466          * Check if ASTs can be handled now.  ASTs cannot be safely
  467          * processed when returning from an NMI.
  468          */
  469         cmpb    $T_NMI,TF_TRAPNO(%esp)
  470 #ifdef HWPMC_HOOKS
  471         je      doreti_nmi
  472 #else
  473         je      doreti_exit
  474 #endif
  475         /*
  476          * PSL_VM must be checked first since segment registers only
  477          * have an RPL in non-VM86 mode.
  478          * ASTs can not be handled now if we are in a vm86 call.
  479          */
  480         testl   $PSL_VM,TF_EFLAGS(%esp)
  481         jz      doreti_notvm86
  482         movl    PCPU(CURPCB),%ecx
  483         testl   $PCB_VM86CALL,PCB_FLAGS(%ecx)
  484         jz      doreti_ast
  485         jmp     doreti_popl_fs
  486 
  487 doreti_notvm86:
  488         testb   $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
  489         jz      doreti_exit             /* can't handle ASTs now if not */
  490 
  491 doreti_ast:
  492         /*
  493          * Check for ASTs atomically with returning.  Disabling CPU
  494          * interrupts provides sufficient locking even in the SMP case,
  495          * since we will be informed of any new ASTs by an IPI.
  496          */
  497         cli
  498         movl    PCPU(CURTHREAD),%eax
  499         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
  500         je      doreti_exit
  501         sti
  502         pushl   %esp                    /* pass a pointer to the trapframe */
  503         movl    $ast, %eax
  504         call    *%eax
  505         add     $4,%esp
  506         jmp     doreti_ast
  507 
  508         /*
  509          * doreti_exit: pop registers, iret.
  510          *
  511          *      The segment register pop is a special case, since it may
  512          *      fault if (for example) a sigreturn specifies bad segment
  513          *      registers.  The fault is handled in trap.c.
  514          */
  515 doreti_exit:
  516         MEXITCOUNT
  517 
  518         cmpl    $T_NMI, TF_TRAPNO(%esp)
  519         je      doreti_iret_nmi
  520         cmpl    $T_MCHK, TF_TRAPNO(%esp)
  521         je      doreti_iret_nmi
  522         cmpl    $T_TRCTRAP, TF_TRAPNO(%esp)
  523         je      doreti_iret_nmi
  524         movl    $TF_SZ, %ecx
  525         testl   $PSL_VM,TF_EFLAGS(%esp)
  526         jz      1f                      /* PCB_VM86CALL is not set */
  527         addl    $VM86_STACK_SPACE, %ecx
  528         jmp     2f
  529 1:      testl   $SEL_RPL_MASK, TF_CS(%esp)
  530         jz      doreti_popl_fs
  531 2:      movl    $handle_ibrs_exit,%eax
  532         pushl   %ecx                    /* preserve enough call-used regs */
  533         call    *%eax
  534         movl    mds_handler,%eax
  535         call    *%eax
  536         popl    %ecx
  537         movl    %esp, %esi
  538         movl    PCPU(TRAMPSTK), %edx
  539         subl    %ecx, %edx
  540         movl    %edx, %edi
  541         rep; movsb
  542         movl    %edx, %esp
  543         movl    PCPU(CURPCB),%eax
  544         movl    PCB_CR3(%eax), %eax
  545         movl    %eax, %cr3
  546 
  547         .globl  doreti_popl_fs
  548 doreti_popl_fs:
  549         popl    %fs
  550         .globl  doreti_popl_es
  551 doreti_popl_es:
  552         popl    %es
  553         .globl  doreti_popl_ds
  554 doreti_popl_ds:
  555         popl    %ds
  556         popal
  557         addl    $8,%esp
  558         .globl  doreti_iret
  559 doreti_iret:
  560         iret
  561 
  562 doreti_iret_nmi:
  563         movl    TF_ERR(%esp), %eax
  564         movl    %eax, %cr3
  565         jmp     doreti_popl_fs
  566 
  567         /*
  568          * doreti_iret_fault and friends.  Alternative return code for
  569          * the case where we get a fault in the doreti_exit code
  570          * above.  trap() (i386/i386/trap.c) catches this specific
  571          * case, and continues in the corresponding place in the code
  572          * below.
  573          *
  574          * If the fault occured during return to usermode, we recreate
  575          * the trap frame and call trap() to send a signal.  Otherwise
  576          * the kernel was tricked into fault by attempt to restore invalid
  577          * usermode segment selectors on return from nested fault or
  578          * interrupt, where interrupted kernel entry code not yet loaded
  579          * kernel selectors.  In the latter case, emulate iret and zero
  580          * the invalid selector.
  581          */
  582         ALIGN_TEXT
  583         .globl  doreti_iret_fault
  584 doreti_iret_fault:
  585         pushl   $0      /* tf_err */
  586         pushl   $0      /* tf_trapno XXXKIB: provide more useful value ? */
  587         pushal
  588         pushl   $0
  589         movw    %ds,(%esp)
  590         .globl  doreti_popl_ds_fault
  591 doreti_popl_ds_fault:
  592         testb   $SEL_RPL_MASK,TF_CS-TF_DS(%esp)
  593         jz      doreti_popl_ds_kfault
  594         pushl   $0
  595         movw    %es,(%esp)
  596         .globl  doreti_popl_es_fault
  597 doreti_popl_es_fault:
  598         testb   $SEL_RPL_MASK,TF_CS-TF_ES(%esp)
  599         jz      doreti_popl_es_kfault
  600         pushl   $0
  601         movw    %fs,(%esp)
  602         .globl  doreti_popl_fs_fault
  603 doreti_popl_fs_fault:
  604         testb   $SEL_RPL_MASK,TF_CS-TF_FS(%esp)
  605         jz      doreti_popl_fs_kfault
  606         movl    $0,TF_ERR(%esp) /* XXX should be the error code */
  607         movl    $T_PROTFLT,TF_TRAPNO(%esp)
  608         SET_KERNEL_SREGS
  609         jmp     calltrap
  610 
  611 doreti_popl_ds_kfault:
  612         movl    $0,(%esp)
  613         jmp     doreti_popl_ds
  614 doreti_popl_es_kfault:
  615         movl    $0,(%esp)
  616         jmp     doreti_popl_es
  617 doreti_popl_fs_kfault:
  618         movl    $0,(%esp)
  619         jmp     doreti_popl_fs
  620 
  621 #ifdef HWPMC_HOOKS
  622 doreti_nmi:
  623         /*
  624          * Since we are returning from an NMI, check if the current trap
  625          * was from user mode and if so whether the current thread
  626          * needs a user call chain capture.
  627          */
  628         testl   $PSL_VM, TF_EFLAGS(%esp)
  629         jnz     doreti_exit
  630         testb   $SEL_RPL_MASK,TF_CS(%esp)
  631         jz      doreti_exit
  632         movl    PCPU(CURTHREAD),%eax    /* curthread present? */
  633         orl     %eax,%eax
  634         jz      doreti_exit
  635         testl   $TDP_CALLCHAIN,TD_PFLAGS(%eax) /* flagged for capture? */
  636         jz      doreti_exit
  637         /*
  638          * Switch to thread stack.  Reset tf_trapno to not indicate NMI,
  639          * to cause normal userspace exit.
  640          */
  641         movl    $T_RESERVED, TF_TRAPNO(%esp)
  642         NMOVE_STACKS
  643         /*
  644          * Take the processor out of NMI mode by executing a fake "iret".
  645          */
  646         pushfl
  647         pushl   %cs
  648         call    1f
  649 1:      popl    %eax
  650         leal    (outofnmi-1b)(%eax),%eax
  651         pushl   %eax
  652         iret
  653 outofnmi:
  654         /*
  655          * Call the callchain capture hook after turning interrupts back on.
  656          */
  657         movl    pmc_hook,%ecx
  658         orl     %ecx,%ecx
  659         jz      doreti_exit
  660         pushl   %esp                    /* frame pointer */
  661         pushl   $PMC_FN_USER_CALLCHAIN  /* command */
  662         movl    PCPU(CURTHREAD),%eax
  663         pushl   %eax                    /* curthread */
  664         sti
  665         call    *%ecx
  666         addl    $12,%esp
  667         jmp     doreti_ast
  668 #endif
  669 
  670 ENTRY(end_exceptions)

Cache object: 06f354ab860cc3bbf8b879c732575148


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.