]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/amd64/ia32/ia32_sigtramp.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / amd64 / ia32 / ia32_sigtramp.S
1 /*-
2  * Copyright (c) 2003 Peter Wemm
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include "opt_compat.h"
30
31 #include <machine/asmacros.h>
32 #include <sys/syscall.h>
33
34 #include "ia32_assym.h"
35
36         .text
37         .code32
38 /*
39  * Signal trampoline, copied to top of user stack
40  * XXX may need to be MD to match backend sendsig handoff protocol
41  */
42         ALIGN_TEXT
43         .globl  ia32_sigcode
44 ia32_sigcode:
45         calll   *IA32_SIGF_HANDLER(%esp)
46         leal    IA32_SIGF_UC(%esp),%eax /* get ucontext */
47         pushl   %eax
48         movl    $SYS_sigreturn,%eax
49         pushl   %eax                    /* junk to fake return addr. */
50         int     $0x80                   /* enter kernel with args */
51                                         /* on stack */
52 1:
53         jmp     1b
54
55 #ifdef COMPAT_FREEBSD4
56         ALIGN_TEXT
57 freebsd4_ia32_sigcode:
58         calll   *IA32_SIGF_HANDLER(%esp)
59         leal    IA32_SIGF_UC4(%esp),%eax/* get ucontext */
60         pushl   %eax
61         movl    $344,%eax               /* 4.x SYS_sigreturn */
62         pushl   %eax                    /* junk to fake return addr. */
63         int     $0x80                   /* enter kernel with args */
64                                         /* on stack */
65 1:
66         jmp     1b
67 #endif
68
69 #ifdef COMPAT_43
70         ALIGN_TEXT
71 ia32_osigcode:
72         calll   *IA32_SIGF_HANDLER(%esp)/* call signal handler */
73         leal    IA32_SIGF_SC(%esp),%eax /* get sigcontext */
74         pushl   %eax
75         movl    $103,%eax               /* 3.x SYS_sigreturn */
76         pushl   %eax                    /* junk to fake return addr. */
77         int     $0x80                   /* enter kernel with args */
78 1:
79         jmp     1b
80
81
82 /*
83  * The lcall $7,$0 emulator cannot use the call gate that does an
84  * inter-privilege transition. The reason is that the call gate
85  * does not disable interrupts, and, before the swapgs is
86  * executed, we would have a window where the ring 0 code is
87  * executed with the wrong gsbase.
88  *
89  * Instead, reflect the lcall $7,$0 back to ring 3 trampoline
90  * which sets up the frame for int $0x80.
91  */
92         ALIGN_TEXT
93 lcall_tramp:
94         .code64
95         /*
96          * There, we are in 64bit mode and need to return to 32bit.
97          * First, convert call frame from 64 to 32 bit format.
98          */
99         pushq   %rax
100         movl    16(%rsp),%eax
101         movl    %eax,20(%rsp)   /* ret %cs */
102         movl    8(%rsp),%eax
103         movl    %eax,16(%rsp)   /* ret %rip -> %eip */
104         popq    %rax
105         addq    $8,%rsp
106         /* Now return to 32bit */
107         pushq   $0x33 /* _ucode32sel UPL */
108         callq   1f
109 1:
110         addq    $2f-1b,(%rsp)
111         lretq
112 2:
113         /* Back in 32bit mode */
114         .code32
115         cmpl    $SYS_vfork,%eax
116         je      4f
117         pushl   %ebp
118         movl    %esp,%ebp
119         pushl   0x24(%ebp) /* arg 6 */
120         pushl   0x20(%ebp)
121         pushl   0x1c(%ebp)
122         pushl   0x18(%ebp)
123         pushl   0x14(%ebp)
124         pushl   0x10(%ebp) /* arg 1 */
125         pushl   0xc(%ebp)  /* gap */
126         int     $0x80
127         leavel
128 3:
129         lretl
130 4:
131         /*
132          * vfork handling is special and relies on the libc stub saving
133          * the return ip in %ecx.  If vfork failed, then there is no
134          * child which can corrupt the frame created by call gate.
135          */
136         int     $0x80
137         jb      3b
138         addl    $8,%esp
139         jmpl    *%ecx
140 #endif
141
142         ALIGN_TEXT
143 esigcode:
144
145         .data
146         .globl  sz_ia32_sigcode
147 sz_ia32_sigcode:
148         .long   esigcode-ia32_sigcode
149 #ifdef COMPAT_FREEBSD4
150         .globl  sz_freebsd4_ia32_sigcode
151 sz_freebsd4_ia32_sigcode:
152         .long   esigcode-freebsd4_ia32_sigcode
153 #endif
154 #ifdef COMPAT_43
155         .globl  sz_ia32_osigcode
156 sz_ia32_osigcode:
157         .long   esigcode-ia32_osigcode
158         .globl  sz_lcall_tramp
159 sz_lcall_tramp:
160         .long   esigcode-lcall_tramp
161 #endif