summaryrefslogtreecommitdiffstats
path: root/sys/amd64/ia32/ia32_sigtramp.S
blob: 354198842409b8724bda402b9353960d0de9caf5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*-
 * Copyright (c) 2003 Peter Wemm
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#include "opt_compat.h"

#include <machine/asmacros.h>
#include <sys/syscall.h>

#include "ia32_assym.h"

	.text
	.code32
/*
 * Signal trampoline, copied to top of user stack
 * XXX may need to be MD to match backend sendsig handoff protocol
 */
	ALIGN_TEXT
	.globl	ia32_sigcode
ia32_sigcode:
	calll	*IA32_SIGF_HANDLER(%esp)
	leal	IA32_SIGF_UC(%esp),%eax	/* get ucontext */
	pushl	%eax
	movl	$SYS_sigreturn,%eax
	pushl	%eax			/* junk to fake return addr. */
	int	$0x80			/* enter kernel with args */
					/* on stack */
1:
	jmp	1b

#ifdef COMPAT_FREEBSD4
	ALIGN_TEXT
freebsd4_ia32_sigcode:
	calll	*IA32_SIGF_HANDLER(%esp)
	leal	IA32_SIGF_UC4(%esp),%eax/* get ucontext */
	pushl	%eax
	movl	$344,%eax		/* 4.x SYS_sigreturn */
	pushl	%eax			/* junk to fake return addr. */
	int	$0x80			/* enter kernel with args */
					/* on stack */
1:
	jmp	1b
#endif

#ifdef COMPAT_43
	ALIGN_TEXT
ia32_osigcode:
	calll	*IA32_SIGF_HANDLER(%esp)/* call signal handler */
	leal	IA32_SIGF_SC(%esp),%eax	/* get sigcontext */
	pushl	%eax
	movl	$103,%eax		/* 3.x SYS_sigreturn */
	pushl	%eax			/* junk to fake return addr. */
	int	$0x80			/* enter kernel with args */
1:
	jmp	1b


/*
 * The lcall $7,$0 emulator cannot use the call gate that does an
 * inter-privilege transition. The reason is that the call gate
 * does not disable interrupts, and, before the swapgs is
 * executed, we would have a window where the ring 0 code is
 * executed with the wrong gsbase.
 *
 * Instead, reflect the lcall $7,$0 back to ring 3 trampoline
 * which sets up the frame for int $0x80.
 */
	ALIGN_TEXT
lcall_tramp:
	.code64
	/*
	 * There, we are in 64bit mode and need to return to 32bit.
	 * First, convert call frame from 64 to 32 bit format.
	 */
	pushq	%rax
	movl	16(%rsp),%eax
	movl	%eax,20(%rsp)	/* ret %cs */
	movl	8(%rsp),%eax
	movl	%eax,16(%rsp)	/* ret %rip -> %eip */
	popq	%rax
	addq	$8,%rsp
	/* Now return to 32bit */
	pushq	$0x33 /* _ucode32sel UPL */
	callq	1f
1:
	addq	$2f-1b,(%rsp)
	lretq
2:
	/* Back in 32bit mode */
	.code32
	cmpl	$SYS_vfork,%eax
	je	4f
	pushl	%ebp
	movl	%esp,%ebp
	pushl	0x24(%ebp) /* arg 6 */
	pushl	0x20(%ebp)
	pushl	0x1c(%ebp)
	pushl	0x18(%ebp)
	pushl	0x14(%ebp)
	pushl	0x10(%ebp) /* arg 1 */
	pushl	0xc(%ebp)  /* gap */
	int	$0x80
	leavel
3:
	lretl
4:
	/*
	 * vfork handling is special and relies on the libc stub saving
	 * the return ip in %ecx.  If vfork failed, then there is no
	 * child which can corrupt the frame created by call gate.
	 */
	int	$0x80
	jb	3b
	addl	$8,%esp
	jmpl	*%ecx
#endif

	ALIGN_TEXT
esigcode:

	.data
	.globl	sz_ia32_sigcode
sz_ia32_sigcode:
	.long	esigcode-ia32_sigcode
#ifdef COMPAT_FREEBSD4
	.globl	sz_freebsd4_ia32_sigcode
sz_freebsd4_ia32_sigcode:
	.long	esigcode-freebsd4_ia32_sigcode
#endif
#ifdef COMPAT_43
	.globl	sz_ia32_osigcode
sz_ia32_osigcode:
	.long	esigcode-ia32_osigcode
	.globl	sz_lcall_tramp
sz_lcall_tramp:
	.long	esigcode-lcall_tramp
#endif
OpenPOWER on IntegriCloud