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  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by the University of
   17  *      California, Berkeley and its contributors.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * $FreeBSD: releng/5.2/sys/i386/i386/exception.s 121990 2003-11-03 22:08:52Z jhb $
   35  */
   36 
   37 #include "opt_npx.h"
   38 
   39 #include <machine/asmacros.h>
   40 #include <machine/psl.h>
   41 #include <machine/trap.h>
   42 
   43 #include "assym.s"
   44 
   45 #define SEL_RPL_MASK    0x0003
   46 
   47         .text
   48 
   49 /*****************************************************************************/
   50 /* Trap handling                                                             */
   51 /*****************************************************************************/
   52 /*
   53  * Trap and fault vector routines.
   54  *
   55  * Most traps are 'trap gates', SDT_SYS386TGT.  A trap gate pushes state on
   56  * the stack that mostly looks like an interrupt, but does not disable 
   57  * interrupts.  A few of the traps we are use are interrupt gates, 
   58  * SDT_SYS386IGT, which are nearly the same thing except interrupts are
   59  * disabled on entry.
   60  *
   61  * The cpu will push a certain amount of state onto the kernel stack for
   62  * the current process.  The amount of state depends on the type of trap 
   63  * and whether the trap crossed rings or not.  See i386/include/frame.h.  
   64  * At the very least the current EFLAGS (status register, which includes 
   65  * the interrupt disable state prior to the trap), the code segment register,
   66  * and the return instruction pointer are pushed by the cpu.  The cpu 
   67  * will also push an 'error' code for certain traps.  We push a dummy 
   68  * error code for those traps where the cpu doesn't in order to maintain 
   69  * a consistent frame.  We also push a contrived 'trap number'.
   70  *
   71  * The cpu does not push the general registers, we must do that, and we 
   72  * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
   73  * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
   74  * must load them with appropriate values for supervisor mode operation.
   75  */
   76 
   77 MCOUNT_LABEL(user)
   78 MCOUNT_LABEL(btrap)
   79 
   80 IDTVEC(div)
   81         pushl $0; TRAP(T_DIVIDE)
   82 IDTVEC(dbg)
   83         pushl $0; TRAP(T_TRCTRAP)
   84 IDTVEC(nmi)
   85         pushl $0; TRAP(T_NMI)
   86 IDTVEC(bpt)
   87         pushl $0; TRAP(T_BPTFLT)
   88 IDTVEC(ofl)
   89         pushl $0; TRAP(T_OFLOW)
   90 IDTVEC(bnd)
   91         pushl $0; TRAP(T_BOUND)
   92 IDTVEC(ill)
   93         pushl $0; TRAP(T_PRIVINFLT)
   94 IDTVEC(dna)
   95         pushl $0; TRAP(T_DNA)
   96 IDTVEC(fpusegm)
   97         pushl $0; TRAP(T_FPOPFLT)
   98 IDTVEC(tss)
   99         TRAP(T_TSSFLT)
  100 IDTVEC(missing)
  101         TRAP(T_SEGNPFLT)
  102 IDTVEC(stk)
  103         TRAP(T_STKFLT)
  104 IDTVEC(prot)
  105         TRAP(T_PROTFLT)
  106 IDTVEC(page)
  107         TRAP(T_PAGEFLT)
  108 IDTVEC(mchk)
  109         pushl $0; TRAP(T_MCHK)
  110 IDTVEC(rsvd)
  111         pushl $0; TRAP(T_RESERVED)
  112 IDTVEC(fpu)
  113         pushl $0; TRAP(T_ARITHTRAP)
  114 IDTVEC(align)
  115         TRAP(T_ALIGNFLT)
  116 
  117 IDTVEC(xmm)
  118         pushl $0; TRAP(T_XMMFLT)
  119         
  120         /*
  121          * alltraps entry point.  Interrupts are enabled if this was a trap
  122          * gate (TGT), else disabled if this was an interrupt gate (IGT).
  123          * Note that int0x80_syscall is a trap gate.  Only page faults
  124          * use an interrupt gate.
  125          */
  126 
  127         SUPERALIGN_TEXT
  128         .globl  alltraps
  129         .type   alltraps,@function
  130 alltraps:
  131         pushal
  132         pushl   %ds
  133         pushl   %es
  134         pushl   %fs
  135 alltraps_with_regs_pushed:
  136         mov     $KDSEL,%ax
  137         mov     %ax,%ds
  138         mov     %ax,%es
  139         mov     $KPSEL,%ax
  140         mov     %ax,%fs
  141         FAKE_MCOUNT(13*4(%esp))
  142 calltrap:
  143         FAKE_MCOUNT(btrap)              /* init "from" btrap -> calltrap */
  144         call    trap
  145 
  146         /*
  147          * Return via doreti to handle ASTs.
  148          */
  149         MEXITCOUNT
  150         jmp     doreti
  151 
  152 /*
  153  * SYSCALL CALL GATE (old entry point for a.out binaries)
  154  *
  155  * The intersegment call has been set up to specify one dummy parameter.
  156  *
  157  * This leaves a place to put eflags so that the call frame can be
  158  * converted to a trap frame. Note that the eflags is (semi-)bogusly
  159  * pushed into (what will be) tf_err and then copied later into the
  160  * final spot. It has to be done this way because esp can't be just
  161  * temporarily altered for the pushfl - an interrupt might come in
  162  * and clobber the saved cs/eip.
  163  */
  164         SUPERALIGN_TEXT
  165 IDTVEC(lcall_syscall)
  166         pushfl                          /* save eflags */
  167         popl    8(%esp)                 /* shuffle into tf_eflags */
  168         pushl   $7                      /* sizeof "lcall 7,0" */
  169         subl    $4,%esp                 /* skip over tf_trapno */
  170         pushal
  171         pushl   %ds
  172         pushl   %es
  173         pushl   %fs
  174         mov     $KDSEL,%ax              /* switch to kernel segments */
  175         mov     %ax,%ds
  176         mov     %ax,%es
  177         mov     $KPSEL,%ax
  178         mov     %ax,%fs
  179         FAKE_MCOUNT(13*4(%esp))
  180         call    syscall
  181         MEXITCOUNT
  182         jmp     doreti
  183 
  184 /*
  185  * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
  186  *
  187  * Even though the name says 'int0x80', this is actually a TGT (trap gate)
  188  * rather then an IGT (interrupt gate).  Thus interrupts are enabled on
  189  * entry just as they are for a normal syscall.
  190  */
  191         SUPERALIGN_TEXT
  192 IDTVEC(int0x80_syscall)
  193         pushl   $2                      /* sizeof "int 0x80" */
  194         subl    $4,%esp                 /* skip over tf_trapno */
  195         pushal
  196         pushl   %ds
  197         pushl   %es
  198         pushl   %fs
  199         mov     $KDSEL,%ax              /* switch to kernel segments */
  200         mov     %ax,%ds
  201         mov     %ax,%es
  202         mov     $KPSEL,%ax
  203         mov     %ax,%fs
  204         FAKE_MCOUNT(13*4(%esp))
  205         call    syscall
  206         MEXITCOUNT
  207         jmp     doreti
  208 
  209 ENTRY(fork_trampoline)
  210         pushl   %esp                    /* trapframe pointer */
  211         pushl   %ebx                    /* arg1 */
  212         pushl   %esi                    /* function */
  213         call    fork_exit
  214         addl    $12,%esp
  215         /* cut from syscall */
  216 
  217         /*
  218          * Return via doreti to handle ASTs.
  219          */
  220         MEXITCOUNT
  221         jmp     doreti
  222 
  223 
  224 /*
  225  * Include vm86 call routines, which want to call doreti.
  226  */
  227 #include "i386/i386/vm86bios.s"
  228 
  229         .data
  230         ALIGN_DATA
  231 
  232 /*
  233  * void doreti(struct trapframe)
  234  *
  235  * Handle return from interrupts, traps and syscalls.
  236  */
  237         .text
  238         SUPERALIGN_TEXT
  239         .globl  doreti
  240         .type   doreti,@function
  241 doreti:
  242         FAKE_MCOUNT(bintr)              /* init "from" bintr -> doreti */
  243 doreti_next:
  244         /*
  245          * Check if ASTs can be handled now.  PSL_VM must be checked first
  246          * since segment registers only have an RPL in non-VM86 mode.
  247          */
  248         testl   $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */
  249         jz      doreti_notvm86
  250         movl    PCPU(CURPCB),%ecx
  251         testl   $PCB_VM86CALL,PCB_FLAGS(%ecx)   /* are we in a vm86 call? */
  252         jz      doreti_ast              /* can handle ASTS now if not */
  253         jmp     doreti_exit
  254 
  255 doreti_notvm86:
  256         testb   $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
  257         jz      doreti_exit             /* can't handle ASTs now if not */
  258 
  259 doreti_ast:
  260         /*
  261          * Check for ASTs atomically with returning.  Disabling CPU
  262          * interrupts provides sufficient locking even in the SMP case,
  263          * since we will be informed of any new ASTs by an IPI.
  264          */
  265         cli
  266         movl    PCPU(CURTHREAD),%eax
  267         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
  268         je      doreti_exit
  269         sti
  270         pushl   %esp                    /* pass a pointer to the trapframe */
  271         call    ast
  272         add     $4,%esp
  273         jmp     doreti_ast
  274 
  275         /*
  276          * doreti_exit: pop registers, iret.
  277          *
  278          *      The segment register pop is a special case, since it may
  279          *      fault if (for example) a sigreturn specifies bad segment
  280          *      registers.  The fault is handled in trap.c.
  281          */
  282 doreti_exit:
  283         MEXITCOUNT
  284 
  285         .globl  doreti_popl_fs
  286 doreti_popl_fs:
  287         popl    %fs
  288         .globl  doreti_popl_es
  289 doreti_popl_es:
  290         popl    %es
  291         .globl  doreti_popl_ds
  292 doreti_popl_ds:
  293         popl    %ds
  294         popal
  295         addl    $8,%esp
  296         .globl  doreti_iret
  297 doreti_iret:
  298         iret
  299 
  300         /*
  301          * doreti_iret_fault and friends.  Alternative return code for
  302          * the case where we get a fault in the doreti_exit code
  303          * above.  trap() (i386/i386/trap.c) catches this specific
  304          * case, sends the process a signal and continues in the
  305          * corresponding place in the code below.
  306          */
  307         ALIGN_TEXT
  308         .globl  doreti_iret_fault
  309 doreti_iret_fault:
  310         subl    $8,%esp
  311         pushal
  312         pushl   %ds
  313         .globl  doreti_popl_ds_fault
  314 doreti_popl_ds_fault:
  315         pushl   %es
  316         .globl  doreti_popl_es_fault
  317 doreti_popl_es_fault:
  318         pushl   %fs
  319         .globl  doreti_popl_fs_fault
  320 doreti_popl_fs_fault:
  321         movl    $0,TF_ERR(%esp) /* XXX should be the error code */
  322         movl    $T_PROTFLT,TF_TRAPNO(%esp)
  323         jmp     alltraps_with_regs_pushed

Cache object: 2b21d943ff79a6455e6431bffc8e5774


[ 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.