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

FreeBSD/Linux Kernel Cross Reference
sys/amd64/amd64/exception.S

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*-
  2  * Copyright (c) 1989, 1990 William F. Jolitz.
  3  * Copyright (c) 1990 The Regents of the University of California.
  4  * Copyright (c) 2007 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  *
 10  * Redistribution and use in source and binary forms, with or without
 11  * modification, are permitted provided that the following conditions
 12  * are met:
 13  * 1. Redistributions of source code must retain the above copyright
 14  *    notice, this list of conditions and the following disclaimer.
 15  * 2. Redistributions in binary form must reproduce the above copyright
 16  *    notice, this list of conditions and the following disclaimer in the
 17  *    documentation and/or other materials provided with the distribution.
 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: src/sys/amd64/amd64/exception.S,v 1.135 2008/12/14 09:06:28 jkoshy Exp $
 35  */
 36 
 37 #include "opt_atpic.h"
 38 #include "opt_compat.h"
 39 #include "opt_hwpmc_hooks.h"
 40 #include "opt_kdtrace.h"
 41 
 42 #include <machine/asmacros.h>
 43 #include <machine/psl.h>
 44 #include <machine/trap.h>
 45 
 46 #include "assym.s"
 47 
 48 #ifdef KDTRACE_HOOKS
 49         .bss
 50         .globl  dtrace_invop_jump_addr
 51         .align  8
 52         .type   dtrace_invop_jump_addr, @object
 53         .size   dtrace_invop_jump_addr, 8
 54 dtrace_invop_jump_addr:
 55         .zero   8
 56         .globl  dtrace_invop_calltrap_addr
 57         .align  8
 58         .type   dtrace_invop_calltrap_addr, @object
 59         .size   dtrace_invop_calltrap_addr, 8
 60 dtrace_invop_calltrap_addr:
 61         .zero   8
 62 #endif
 63         .text
 64 #ifdef HWPMC_HOOKS
 65         ENTRY(start_exceptions)
 66 #endif
 67 
 68 /*****************************************************************************/
 69 /* Trap handling                                                             */
 70 /*****************************************************************************/
 71 /*
 72  * Trap and fault vector routines.
 73  *
 74  * All traps are 'interrupt gates', SDT_SYSIGT.  An interrupt gate pushes
 75  * state on the stack but also disables interrupts.  This is important for
 76  * us for the use of the swapgs instruction.  We cannot be interrupted
 77  * until the GS.base value is correct.  For most traps, we automatically
 78  * then enable interrupts if the interrupted context had them enabled.
 79  * This is equivalent to the i386 port's use of SDT_SYS386TGT.
 80  *
 81  * The cpu will push a certain amount of state onto the kernel stack for
 82  * the current process.  See amd64/include/frame.h.  
 83  * This includes the current RFLAGS (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 
 96 MCOUNT_LABEL(user)
 97 MCOUNT_LABEL(btrap)
 98 
 99 /* Traps that we leave interrupts disabled for.. */
100 #define TRAP_NOEN(a)    \
101         subq $TF_RIP,%rsp; \
102         movq $(a),TF_TRAPNO(%rsp) ; \
103         movq $0,TF_ADDR(%rsp) ; \
104         movq $0,TF_ERR(%rsp) ; \
105         jmp alltraps_noen
106 IDTVEC(dbg)
107         TRAP_NOEN(T_TRCTRAP)
108 IDTVEC(bpt)
109         TRAP_NOEN(T_BPTFLT)
110 
111 /* Regular traps; The cpu does not supply tf_err for these. */
112 #define TRAP(a)  \
113         subq $TF_RIP,%rsp; \
114         movq $(a),TF_TRAPNO(%rsp) ; \
115         movq $0,TF_ADDR(%rsp) ; \
116         movq $0,TF_ERR(%rsp) ; \
117         jmp alltraps
118 IDTVEC(div)
119         TRAP(T_DIVIDE)
120 IDTVEC(ofl)
121         TRAP(T_OFLOW)
122 IDTVEC(bnd)
123         TRAP(T_BOUND)
124 IDTVEC(ill)
125         TRAP(T_PRIVINFLT)
126 IDTVEC(dna)
127         TRAP(T_DNA)
128 IDTVEC(fpusegm)
129         TRAP(T_FPOPFLT)
130 IDTVEC(mchk)
131         TRAP(T_MCHK)
132 IDTVEC(rsvd)
133         TRAP(T_RESERVED)
134 IDTVEC(fpu)
135         TRAP(T_ARITHTRAP)
136 IDTVEC(xmm)
137         TRAP(T_XMMFLT)
138 
139 /* This group of traps have tf_err already pushed by the cpu */
140 #define TRAP_ERR(a)     \
141         subq $TF_ERR,%rsp; \
142         movq $(a),TF_TRAPNO(%rsp) ; \
143         movq $0,TF_ADDR(%rsp) ; \
144         jmp alltraps
145 IDTVEC(tss)
146         TRAP_ERR(T_TSSFLT)
147 IDTVEC(missing)
148         TRAP_ERR(T_SEGNPFLT)
149 IDTVEC(stk)
150         TRAP_ERR(T_STKFLT)
151 IDTVEC(align)
152         TRAP_ERR(T_ALIGNFLT)
153 
154         /*
155          * alltraps entry point.  Use swapgs if this is the first time in the
156          * kernel from userland.  Reenable interrupts if they were enabled
157          * before the trap.  This approximates SDT_SYS386TGT on the i386 port.
158          */
159 
160         SUPERALIGN_TEXT
161         .globl  alltraps
162         .type   alltraps,@function
163 alltraps:
164         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
165         jz      alltraps_testi          /* already running with kernel GS.base */
166         swapgs
167 alltraps_testi:
168         testl   $PSL_I,TF_RFLAGS(%rsp)
169         jz      alltraps_pushregs
170         sti
171 alltraps_pushregs:
172         movq    %rdi,TF_RDI(%rsp)
173 alltraps_pushregs_no_rdi:
174         movq    %rsi,TF_RSI(%rsp)
175         movq    %rdx,TF_RDX(%rsp)
176         movq    %rcx,TF_RCX(%rsp)
177         movq    %r8,TF_R8(%rsp)
178         movq    %r9,TF_R9(%rsp)
179         movq    %rax,TF_RAX(%rsp)
180         movq    %rbx,TF_RBX(%rsp)
181         movq    %rbp,TF_RBP(%rsp)
182         movq    %r10,TF_R10(%rsp)
183         movq    %r11,TF_R11(%rsp)
184         movq    %r12,TF_R12(%rsp)
185         movq    %r13,TF_R13(%rsp)
186         movq    %r14,TF_R14(%rsp)
187         movq    %r15,TF_R15(%rsp)
188         FAKE_MCOUNT(TF_RIP(%rsp))
189 #ifdef KDTRACE_HOOKS
190         /*
191          * DTrace Function Boundary Trace (fbt) probes are triggered
192          * by int3 (0xcc) which causes the #BP (T_BPTFLT) breakpoint
193          * interrupt. For all other trap types, just handle them in
194          * the usual way.
195          */
196         cmpq    $T_BPTFLT,TF_TRAPNO(%rsp)
197         jne     calltrap
198 
199         /* Check if there is no DTrace hook registered. */
200         cmpq    $0,dtrace_invop_jump_addr
201         je      calltrap
202 
203         /*
204          * Set our jump address for the jump back in the event that
205          * the breakpoint wasn't caused by DTrace at all.
206          */
207         movq    $calltrap, dtrace_invop_calltrap_addr(%rip)
208 
209         /* Jump to the code hooked in by DTrace. */
210         movq    dtrace_invop_jump_addr, %rax
211         jmpq    *dtrace_invop_jump_addr
212 #endif
213         .globl  calltrap
214         .type   calltrap,@function
215 calltrap:
216         movq    %rsp, %rdi
217         call    trap
218         MEXITCOUNT
219         jmp     doreti                  /* Handle any pending ASTs */
220 
221         /*
222          * alltraps_noen entry point.  Unlike alltraps above, we want to
223          * leave the interrupts disabled.  This corresponds to
224          * SDT_SYS386IGT on the i386 port.
225          */
226         SUPERALIGN_TEXT
227         .globl  alltraps_noen
228         .type   alltraps_noen,@function
229 alltraps_noen:
230         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
231         jz      alltraps_pushregs       /* already running with kernel GS.base */
232         swapgs
233         jmp     alltraps_pushregs
234 
235 IDTVEC(dblfault)
236         subq    $TF_ERR,%rsp
237         movq    $T_DOUBLEFLT,TF_TRAPNO(%rsp)
238         movq    $0,TF_ADDR(%rsp)
239         movq    $0,TF_ERR(%rsp)
240         movq    %rdi,TF_RDI(%rsp)
241         movq    %rsi,TF_RSI(%rsp)
242         movq    %rdx,TF_RDX(%rsp)
243         movq    %rcx,TF_RCX(%rsp)
244         movq    %r8,TF_R8(%rsp)
245         movq    %r9,TF_R9(%rsp)
246         movq    %rax,TF_RAX(%rsp)
247         movq    %rbx,TF_RBX(%rsp)
248         movq    %rbp,TF_RBP(%rsp)
249         movq    %r10,TF_R10(%rsp)
250         movq    %r11,TF_R11(%rsp)
251         movq    %r12,TF_R12(%rsp)
252         movq    %r13,TF_R13(%rsp)
253         movq    %r14,TF_R14(%rsp)
254         movq    %r15,TF_R15(%rsp)
255         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
256         jz      1f                      /* already running with kernel GS.base */
257         swapgs
258 1:      movq    %rsp, %rdi
259         call    dblfault_handler
260 2:      hlt
261         jmp     2b
262 
263 IDTVEC(page)
264         subq    $TF_ERR,%rsp
265         movq    $T_PAGEFLT,TF_TRAPNO(%rsp)
266         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
267         jz      1f                      /* already running with kernel GS.base */
268         swapgs
269 1:
270         movq    %rdi,TF_RDI(%rsp)       /* free up a GP register */
271         movq    %cr2,%rdi               /* preserve %cr2 before ..  */
272         movq    %rdi,TF_ADDR(%rsp)      /* enabling interrupts. */
273         testl   $PSL_I,TF_RFLAGS(%rsp)
274         jz      alltraps_pushregs_no_rdi
275         sti
276         jmp     alltraps_pushregs_no_rdi
277 
278         /*
279          * We have to special-case this one.  If we get a trap in doreti() at
280          * the iretq stage, we'll reenter with the wrong gs state.  We'll have
281          * to do a special the swapgs in this case even coming from the kernel.
282          * XXX linux has a trap handler for their equivalent of load_gs().
283          */
284 IDTVEC(prot)
285         subq    $TF_ERR,%rsp
286         movq    $T_PROTFLT,TF_TRAPNO(%rsp)
287         movq    $0,TF_ADDR(%rsp)
288         movq    %rdi,TF_RDI(%rsp)       /* free up a GP register */
289         leaq    doreti_iret(%rip),%rdi
290         cmpq    %rdi,TF_RIP(%rsp)
291         je      2f                      /* kernel but with user gsbase!! */
292         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
293         jz      1f                      /* already running with kernel GS.base */
294 2:
295         swapgs
296 1:
297         testl   $PSL_I,TF_RFLAGS(%rsp)
298         jz      alltraps_pushregs_no_rdi
299         sti
300         jmp     alltraps_pushregs_no_rdi
301 
302 /*
303  * Fast syscall entry point.  We enter here with just our new %cs/%ss set,
304  * and the new privilige level.  We are still running on the old user stack
305  * pointer.  We have to juggle a few things around to find our stack etc.
306  * swapgs gives us access to our PCPU space only.
307  */
308 IDTVEC(fast_syscall)
309         swapgs
310         movq    %rsp,PCPU(SCRATCH_RSP)
311         movq    PCPU(RSP0),%rsp
312         /* Now emulate a trapframe. Make the 8 byte alignment odd for call. */
313         subq    $TF_SIZE,%rsp
314         /* defer TF_RSP till we have a spare register */
315         movq    %r11,TF_RFLAGS(%rsp)
316         movq    %rcx,TF_RIP(%rsp)       /* %rcx original value is in %r10 */
317         movq    PCPU(SCRATCH_RSP),%r11  /* %r11 already saved */
318         movq    %r11,TF_RSP(%rsp)       /* user stack pointer */
319         sti
320         movq    $KUDSEL,TF_SS(%rsp)
321         movq    $KUCSEL,TF_CS(%rsp)
322         movq    $2,TF_ERR(%rsp)
323         movq    %rdi,TF_RDI(%rsp)       /* arg 1 */
324         movq    %rsi,TF_RSI(%rsp)       /* arg 2 */
325         movq    %rdx,TF_RDX(%rsp)       /* arg 3 */
326         movq    %r10,TF_RCX(%rsp)       /* arg 4 */
327         movq    %r8,TF_R8(%rsp)         /* arg 5 */
328         movq    %r9,TF_R9(%rsp)         /* arg 6 */
329         movq    %rax,TF_RAX(%rsp)       /* syscall number */
330         movq    %rbx,TF_RBX(%rsp)       /* C preserved */
331         movq    %rbp,TF_RBP(%rsp)       /* C preserved */
332         movq    %r12,TF_R12(%rsp)       /* C preserved */
333         movq    %r13,TF_R13(%rsp)       /* C preserved */
334         movq    %r14,TF_R14(%rsp)       /* C preserved */
335         movq    %r15,TF_R15(%rsp)       /* C preserved */
336         FAKE_MCOUNT(TF_RIP(%rsp))
337         movq    %rsp, %rdi
338         call    syscall
339         movq    PCPU(CURPCB),%rax
340         testq   $PCB_FULLCTX,PCB_FLAGS(%rax)
341         jne     3f
342 1:      /* Check for and handle AST's on return to userland */
343         cli
344         movq    PCPU(CURTHREAD),%rax
345         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
346         je      2f
347         sti
348         movq    %rsp, %rdi
349         call    ast
350         jmp     1b
351 2:      /* restore preserved registers */
352         MEXITCOUNT
353         movq    TF_RDI(%rsp),%rdi       /* bonus; preserve arg 1 */
354         movq    TF_RSI(%rsp),%rsi       /* bonus: preserve arg 2 */
355         movq    TF_RDX(%rsp),%rdx       /* return value 2 */
356         movq    TF_RAX(%rsp),%rax       /* return value 1 */
357         movq    TF_RBX(%rsp),%rbx       /* C preserved */
358         movq    TF_RBP(%rsp),%rbp       /* C preserved */
359         movq    TF_R12(%rsp),%r12       /* C preserved */
360         movq    TF_R13(%rsp),%r13       /* C preserved */
361         movq    TF_R14(%rsp),%r14       /* C preserved */
362         movq    TF_R15(%rsp),%r15       /* C preserved */
363         movq    TF_RFLAGS(%rsp),%r11    /* original %rflags */
364         movq    TF_RIP(%rsp),%rcx       /* original %rip */
365         movq    TF_RSP(%rsp),%r9        /* user stack pointer */
366         movq    %r9,%rsp                /* original %rsp */
367         swapgs
368         sysretq
369 3:      /* Requested full context restore, use doreti for that */
370         andq    $~PCB_FULLCTX,PCB_FLAGS(%rax)
371         MEXITCOUNT
372         jmp     doreti
373 
374 /*
375  * Here for CYA insurance, in case a "syscall" instruction gets
376  * issued from 32 bit compatability mode. MSR_CSTAR has to point
377  * to *something* if EFER_SCE is enabled.
378  */
379 IDTVEC(fast_syscall32)
380         sysret
381 
382 /*
383  * NMI handling is special.
384  *
385  * First, NMIs do not respect the state of the processor's RFLAGS.IF
386  * bit and the NMI handler may be invoked at any time, including when
387  * the processor is in a critical section with RFLAGS.IF == 0.  In
388  * particular, this means that the processor's GS.base values could be
389  * inconsistent on entry to the handler, and so we need to read
390  * MSR_GSBASE to determine if a 'swapgs' is needed.  We use '%ebx', a
391  * C-preserved register, to remember whether to swap GS back on the
392  * exit path.
393  *
394  * Second, the processor treats NMIs specially, blocking further NMIs
395  * until an 'iretq' instruction is executed.  We therefore need to
396  * execute the NMI handler with interrupts disabled to prevent a
397  * nested interrupt from executing an 'iretq' instruction and
398  * inadvertently taking the processor out of NMI mode.
399  *
400  * Third, the NMI handler runs on its own stack (tss_ist1), shared
401  * with the double fault handler.
402  */
403 
404 IDTVEC(nmi)
405         subq    $TF_RIP,%rsp
406         movq    $(T_NMI),TF_TRAPNO(%rsp)
407         movq    $0,TF_ADDR(%rsp)
408         movq    $0,TF_ERR(%rsp)
409         movq    %rdi,TF_RDI(%rsp)
410         movq    %rsi,TF_RSI(%rsp)
411         movq    %rdx,TF_RDX(%rsp)
412         movq    %rcx,TF_RCX(%rsp)
413         movq    %r8,TF_R8(%rsp)
414         movq    %r9,TF_R9(%rsp)
415         movq    %rax,TF_RAX(%rsp)
416         movq    %rbx,TF_RBX(%rsp)
417         movq    %rbp,TF_RBP(%rsp)
418         movq    %r10,TF_R10(%rsp)
419         movq    %r11,TF_R11(%rsp)
420         movq    %r12,TF_R12(%rsp)
421         movq    %r13,TF_R13(%rsp)
422         movq    %r14,TF_R14(%rsp)
423         movq    %r15,TF_R15(%rsp)
424         xorl    %ebx,%ebx
425         testb   $SEL_RPL_MASK,TF_CS(%rsp)
426         jnz     nmi_needswapgs          /* we came from userland */
427         movl    $MSR_GSBASE,%ecx
428         rdmsr
429         cmpl    $VM_MAXUSER_ADDRESS >> 32,%edx
430         jae     nmi_calltrap            /* GS.base holds a kernel VA */
431 nmi_needswapgs:
432         incl    %ebx
433         swapgs
434 /* Note: this label is also used by ddb and gdb: */
435 nmi_calltrap:
436         FAKE_MCOUNT(TF_RIP(%rsp))
437         movq    %rsp, %rdi
438         call    trap
439         MEXITCOUNT
440 #ifdef HWPMC_HOOKS
441         /*
442          * Check if the current trap was from user mode and if so
443          * whether the current thread needs a user call chain to be
444          * captured. We are still in NMI mode at this point.
445          */
446         testb   $SEL_RPL_MASK,TF_CS(%rsp)
447         jz      nocallchain
448         movq    PCPU(CURTHREAD),%rax    /* curthread present? */
449         orq     %rax,%rax
450         jz      nocallchain
451         testl   $TDP_CALLCHAIN,TD_PFLAGS(%rax) /* flagged for capture? */
452         jz      nocallchain
453         /*
454          * A user callchain is to be captured, so:
455          * - Move execution to the regular kernel stack, to allow for
456          *   nested NMI interrupts.
457          * - Take the processor out of "NMI" mode by faking an "iret".
458          * - Enable interrupts, so that copyin() can work.
459          */
460         movq    %rsp,%rsi       /* source stack pointer */
461         movq    $TF_SIZE,%rcx
462         movq    PCPU(RSP0),%rdx
463         subq    %rcx,%rdx
464         movq    %rdx,%rdi       /* destination stack pointer */
465 
466         shrq    $3,%rcx         /* trap frame size in long words */
467         cld
468         rep
469         movsq                   /* copy trapframe */
470 
471         movl    %ss,%eax
472         pushq   %rax            /* tf_ss */
473         pushq   %rdx            /* tf_rsp (on kernel stack) */
474         pushfq                  /* tf_rflags */
475         movl    %cs,%eax
476         pushq   %rax            /* tf_cs */
477         pushq   $outofnmi       /* tf_rip */
478         iretq
479 outofnmi:
480         /*
481          * At this point the processor has exited NMI mode and is running
482          * with interrupts turned off on the normal kernel stack.
483          *
484          * If a pending NMI gets recognized at or after this point, it 
485          * will cause a kernel callchain to be traced.
486          *
487          * We turn interrupts back on, and call the user callchain capture hook.
488          */
489         movq    pmc_hook,%rax
490         orq     %rax,%rax
491         jz      nocallchain
492         movq    PCPU(CURTHREAD),%rdi            /* thread */
493         movq    $PMC_FN_USER_CALLCHAIN,%rsi     /* command */
494         movq    %rsp,%rdx                       /* frame */
495         sti
496         call    *%rax
497 nocallchain:
498 #endif
499         testl   %ebx,%ebx
500         jz      nmi_restoreregs
501         swapgs
502 nmi_restoreregs:
503         movq    TF_RDI(%rsp),%rdi
504         movq    TF_RSI(%rsp),%rsi
505         movq    TF_RDX(%rsp),%rdx
506         movq    TF_RCX(%rsp),%rcx
507         movq    TF_R8(%rsp),%r8
508         movq    TF_R9(%rsp),%r9
509         movq    TF_RAX(%rsp),%rax
510         movq    TF_RBX(%rsp),%rbx
511         movq    TF_RBP(%rsp),%rbp
512         movq    TF_R10(%rsp),%r10
513         movq    TF_R11(%rsp),%r11
514         movq    TF_R12(%rsp),%r12
515         movq    TF_R13(%rsp),%r13
516         movq    TF_R14(%rsp),%r14
517         movq    TF_R15(%rsp),%r15
518         addq    $TF_RIP,%rsp
519         iretq
520 
521 ENTRY(fork_trampoline)
522         movq    %r12, %rdi              /* function */
523         movq    %rbx, %rsi              /* arg1 */
524         movq    %rsp, %rdx              /* trapframe pointer */
525         call    fork_exit
526         MEXITCOUNT
527         jmp     doreti                  /* Handle any ASTs */
528 
529 /*
530  * To efficiently implement classification of trap and interrupt handlers
531  * for profiling, there must be only trap handlers between the labels btrap
532  * and bintr, and only interrupt handlers between the labels bintr and
533  * eintr.  This is implemented (partly) by including files that contain
534  * some of the handlers.  Before including the files, set up a normal asm
535  * environment so that the included files doen't need to know that they are
536  * included.
537  */
538 
539 #ifdef COMPAT_IA32
540         .data
541         .p2align 4
542         .text
543         SUPERALIGN_TEXT
544 
545 #include <amd64/ia32/ia32_exception.S>
546 #endif
547 
548         .data
549         .p2align 4
550         .text
551         SUPERALIGN_TEXT
552 MCOUNT_LABEL(bintr)
553 
554 #include <amd64/amd64/apic_vector.S>
555 
556 #ifdef DEV_ATPIC
557         .data
558         .p2align 4
559         .text
560         SUPERALIGN_TEXT
561 
562 #include <amd64/isa/atpic_vector.S>
563 #endif
564 
565         .text
566 MCOUNT_LABEL(eintr)
567 
568 /*
569  * void doreti(struct trapframe)
570  *
571  * Handle return from interrupts, traps and syscalls.
572  */
573         .text
574         SUPERALIGN_TEXT
575         .type   doreti,@function
576 doreti:
577         FAKE_MCOUNT($bintr)             /* init "from" bintr -> doreti */
578         /*
579          * Check if ASTs can be handled now.
580          */
581         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
582         jz      doreti_exit             /* can't handle ASTs now if not */
583 
584 doreti_ast:
585         /*
586          * Check for ASTs atomically with returning.  Disabling CPU
587          * interrupts provides sufficient locking eve in the SMP case,
588          * since we will be informed of any new ASTs by an IPI.
589          */
590         cli
591         movq    PCPU(CURTHREAD),%rax
592         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
593         je      doreti_exit
594         sti
595         movq    %rsp, %rdi                      /* pass a pointer to the trapframe */
596         call    ast
597         jmp     doreti_ast
598 
599         /*
600          * doreti_exit: pop registers, iret.
601          *
602          *      The segment register pop is a special case, since it may
603          *      fault if (for example) a sigreturn specifies bad segment
604          *      registers.  The fault is handled in trap.c.
605          */
606 doreti_exit:
607         MEXITCOUNT
608         movq    TF_RDI(%rsp),%rdi
609         movq    TF_RSI(%rsp),%rsi
610         movq    TF_RDX(%rsp),%rdx
611         movq    TF_RCX(%rsp),%rcx
612         movq    TF_R8(%rsp),%r8
613         movq    TF_R9(%rsp),%r9
614         movq    TF_RAX(%rsp),%rax
615         movq    TF_RBX(%rsp),%rbx
616         movq    TF_RBP(%rsp),%rbp
617         movq    TF_R10(%rsp),%r10
618         movq    TF_R11(%rsp),%r11
619         movq    TF_R12(%rsp),%r12
620         movq    TF_R13(%rsp),%r13
621         movq    TF_R14(%rsp),%r14
622         movq    TF_R15(%rsp),%r15
623         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
624         jz      1f                      /* keep running with kernel GS.base */
625         cli
626         swapgs
627 1:      addq    $TF_RIP,%rsp            /* skip over tf_err, tf_trapno */
628         .globl  doreti_iret
629 doreti_iret:
630         iretq
631 
632         /*
633          * doreti_iret_fault.  Alternative return code for
634          * the case where we get a fault in the doreti_exit code
635          * above.  trap() (amd64/amd64/trap.c) catches this specific
636          * case, sends the process a signal and continues in the
637          * corresponding place in the code below.
638          */
639         ALIGN_TEXT
640         .globl  doreti_iret_fault
641 doreti_iret_fault:
642         subq    $TF_RIP,%rsp            /* space including tf_err, tf_trapno */
643         testl   $PSL_I,TF_RFLAGS(%rsp)
644         jz      1f
645         sti
646 1:      movq    %rdi,TF_RDI(%rsp)
647         movq    %rsi,TF_RSI(%rsp)
648         movq    %rdx,TF_RDX(%rsp)
649         movq    %rcx,TF_RCX(%rsp)
650         movq    %r8,TF_R8(%rsp)
651         movq    %r9,TF_R9(%rsp)
652         movq    %rax,TF_RAX(%rsp)
653         movq    %rbx,TF_RBX(%rsp)
654         movq    %rbp,TF_RBP(%rsp)
655         movq    %r10,TF_R10(%rsp)
656         movq    %r11,TF_R11(%rsp)
657         movq    %r12,TF_R12(%rsp)
658         movq    %r13,TF_R13(%rsp)
659         movq    %r14,TF_R14(%rsp)
660         movq    %r15,TF_R15(%rsp)
661         movq    $T_PROTFLT,TF_TRAPNO(%rsp)
662         movq    $0,TF_ERR(%rsp) /* XXX should be the error code */
663         movq    $0,TF_ADDR(%rsp)
664         FAKE_MCOUNT(TF_RIP(%rsp))
665         jmp     calltrap
666 #ifdef HWPMC_HOOKS
667         ENTRY(end_exceptions)
668 #endif

Cache object: 35aed9b8adb2c2da43b46039b16f13d8


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