| @@ -1,506 +1,507 @@ | | | @@ -1,506 +1,507 @@ |
1 | /* $NetBSD: linux_machdep.c,v 1.47 2014/02/15 10:11:15 dsl Exp $ */ | | 1 | /* $NetBSD: linux_machdep.c,v 1.48 2014/02/19 20:50:56 dsl Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. | | 4 | * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. All advertising materials mentioning features or use of this software | | 14 | * 3. All advertising materials mentioning features or use of this software |
15 | * must display the following acknowledgement: | | 15 | * must display the following acknowledgement: |
16 | * This product includes software developed by Emmanuel Dreyfus | | 16 | * This product includes software developed by Emmanuel Dreyfus |
17 | * 4. The name of the author may not be used to endorse or promote | | 17 | * 4. The name of the author may not be used to endorse or promote |
18 | * products derived from this software without specific prior written | | 18 | * products derived from this software without specific prior written |
19 | * permission. | | 19 | * permission. |
20 | * | | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' | | 21 | * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | | 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS | | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. | | 31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | | | 35 | |
36 | __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.47 2014/02/15 10:11:15 dsl Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.48 2014/02/19 20:50:56 dsl Exp $"); |
37 | | | 37 | |
38 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
39 | #include <sys/types.h> | | 39 | #include <sys/types.h> |
40 | #include <sys/systm.h> | | 40 | #include <sys/systm.h> |
41 | #include <sys/signal.h> | | 41 | #include <sys/signal.h> |
42 | #include <sys/exec.h> | | 42 | #include <sys/exec.h> |
43 | #include <sys/proc.h> | | 43 | #include <sys/proc.h> |
44 | #include <sys/ptrace.h> /* for process_read_fpregs() */ | | 44 | #include <sys/ptrace.h> /* for process_read_fpregs() */ |
45 | #include <sys/ucontext.h> | | 45 | #include <sys/ucontext.h> |
46 | #include <sys/conf.h> | | 46 | #include <sys/conf.h> |
47 | | | 47 | |
48 | #include <machine/reg.h> | | 48 | #include <machine/reg.h> |
49 | #include <machine/pcb.h> | | 49 | #include <machine/pcb.h> |
50 | #include <machine/mcontext.h> | | 50 | #include <machine/mcontext.h> |
51 | #include <machine/specialreg.h> | | 51 | #include <machine/specialreg.h> |
52 | #include <machine/vmparam.h> | | 52 | #include <machine/vmparam.h> |
53 | #include <machine/cpufunc.h> | | 53 | #include <machine/cpufunc.h> |
| | | 54 | #include <x86/include/sysarch.h> |
54 | | | 55 | |
55 | /* | | 56 | /* |
56 | * To see whether wscons is configured (for virtual console ioctl calls). | | 57 | * To see whether wscons is configured (for virtual console ioctl calls). |
57 | */ | | 58 | */ |
58 | #if defined(_KERNEL_OPT) | | 59 | #if defined(_KERNEL_OPT) |
59 | #include "wsdisplay.h" | | 60 | #include "wsdisplay.h" |
60 | #endif | | 61 | #endif |
61 | #if (NWSDISPLAY > 0) | | 62 | #if (NWSDISPLAY > 0) |
62 | #include <dev/wscons/wsconsio.h> | | 63 | #include <dev/wscons/wsconsio.h> |
63 | #include <dev/wscons/wsdisplay_usl_io.h> | | 64 | #include <dev/wscons/wsdisplay_usl_io.h> |
64 | #endif | | 65 | #endif |
65 | | | 66 | |
66 | | | 67 | |
67 | #include <compat/linux/common/linux_signal.h> | | 68 | #include <compat/linux/common/linux_signal.h> |
68 | #include <compat/linux/common/linux_errno.h> | | 69 | #include <compat/linux/common/linux_errno.h> |
69 | #include <compat/linux/common/linux_exec.h> | | 70 | #include <compat/linux/common/linux_exec.h> |
70 | #include <compat/linux/common/linux_ioctl.h> | | 71 | #include <compat/linux/common/linux_ioctl.h> |
71 | #include <compat/linux/common/linux_prctl.h> | | 72 | #include <compat/linux/common/linux_prctl.h> |
72 | #include <compat/linux/common/linux_machdep.h> | | 73 | #include <compat/linux/common/linux_machdep.h> |
73 | #include <compat/linux/common/linux_ipc.h> | | 74 | #include <compat/linux/common/linux_ipc.h> |
74 | #include <compat/linux/common/linux_sem.h> | | 75 | #include <compat/linux/common/linux_sem.h> |
75 | #include <compat/linux/linux_syscall.h> | | 76 | #include <compat/linux/linux_syscall.h> |
76 | #include <compat/linux/linux_syscallargs.h> | | 77 | #include <compat/linux/linux_syscallargs.h> |
77 | | | 78 | |
78 | static void linux_buildcontext(struct lwp *, void *, void *); | | 79 | static void linux_buildcontext(struct lwp *, void *, void *); |
79 | | | 80 | |
80 | void | | 81 | void |
81 | linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) | | 82 | linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) |
82 | { | | 83 | { |
83 | struct pcb *pcb = lwp_getpcb(l); | | 84 | struct pcb *pcb = lwp_getpcb(l); |
84 | struct trapframe *tf; | | 85 | struct trapframe *tf; |
85 | | | 86 | |
86 | fpu_save_area_clear(l, __NetBSD_NPXCW__); | | 87 | fpu_save_area_clear(l, __NetBSD_NPXCW__); |
87 | pcb->pcb_flags = 0; | | 88 | pcb->pcb_flags = 0; |
88 | | | 89 | |
89 | l->l_proc->p_flag &= ~PK_32; | | 90 | l->l_proc->p_flag &= ~PK_32; |
90 | | | 91 | |
91 | tf = l->l_md.md_regs; | | 92 | tf = l->l_md.md_regs; |
92 | tf->tf_rax = 0; | | 93 | tf->tf_rax = 0; |
93 | tf->tf_rbx = 0; | | 94 | tf->tf_rbx = 0; |
94 | tf->tf_rcx = epp->ep_entry; | | 95 | tf->tf_rcx = epp->ep_entry; |
95 | tf->tf_rdx = 0; | | 96 | tf->tf_rdx = 0; |
96 | tf->tf_rsi = 0; | | 97 | tf->tf_rsi = 0; |
97 | tf->tf_rdi = 0; | | 98 | tf->tf_rdi = 0; |
98 | tf->tf_rbp = 0; | | 99 | tf->tf_rbp = 0; |
99 | tf->tf_rsp = stack; | | 100 | tf->tf_rsp = stack; |
100 | tf->tf_r8 = 0; | | 101 | tf->tf_r8 = 0; |
101 | tf->tf_r9 = 0; | | 102 | tf->tf_r9 = 0; |
102 | tf->tf_r10 = 0; | | 103 | tf->tf_r10 = 0; |
103 | tf->tf_r11 = 0; | | 104 | tf->tf_r11 = 0; |
104 | tf->tf_r12 = 0; | | 105 | tf->tf_r12 = 0; |
105 | tf->tf_r13 = 0; | | 106 | tf->tf_r13 = 0; |
106 | tf->tf_r14 = 0; | | 107 | tf->tf_r14 = 0; |
107 | tf->tf_r15 = 0; | | 108 | tf->tf_r15 = 0; |
108 | tf->tf_rip = epp->ep_entry; | | 109 | tf->tf_rip = epp->ep_entry; |
109 | tf->tf_rflags = PSL_USERSET; | | 110 | tf->tf_rflags = PSL_USERSET; |
110 | tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); | | 111 | tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); |
111 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); | | 112 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); |
112 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); | | 113 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); |
113 | tf->tf_es = 0; | | 114 | tf->tf_es = 0; |
114 | cpu_fsgs_zero(l); | | 115 | cpu_fsgs_zero(l); |
115 | | | 116 | |
116 | return; | | 117 | return; |
117 | } | | 118 | } |
118 | | | 119 | |
119 | void | | 120 | void |
120 | linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) | | 121 | linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) |
121 | { | | 122 | { |
122 | struct lwp *l = curlwp; | | 123 | struct lwp *l = curlwp; |
123 | struct proc *p = l->l_proc; | | 124 | struct proc *p = l->l_proc; |
124 | struct pcb *pcb = lwp_getpcb(l); | | 125 | struct pcb *pcb = lwp_getpcb(l); |
125 | struct sigacts *ps = p->p_sigacts; | | 126 | struct sigacts *ps = p->p_sigacts; |
126 | int onstack, error; | | 127 | int onstack, error; |
127 | int sig = ksi->ksi_signo; | | 128 | int sig = ksi->ksi_signo; |
128 | struct linux_rt_sigframe *sfp, sigframe; | | 129 | struct linux_rt_sigframe *sfp, sigframe; |
129 | struct linux__fpstate *fpsp; | | 130 | struct linux__fpstate *fpsp; |
130 | struct fpreg fpregs; | | 131 | struct fpreg fpregs; |
131 | struct trapframe *tf = l->l_md.md_regs; | | 132 | struct trapframe *tf = l->l_md.md_regs; |
132 | sig_t catcher = SIGACTION(p, sig).sa_handler; | | 133 | sig_t catcher = SIGACTION(p, sig).sa_handler; |
133 | linux_sigset_t lmask; | | 134 | linux_sigset_t lmask; |
134 | char *sp; | | 135 | char *sp; |
135 | | | 136 | |
136 | /* Do we need to jump onto the signal stack? */ | | 137 | /* Do we need to jump onto the signal stack? */ |
137 | onstack = | | 138 | onstack = |
138 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | | 139 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && |
139 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; | | 140 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; |
140 | | | 141 | |
141 | /* Allocate space for the signal handler context. */ | | 142 | /* Allocate space for the signal handler context. */ |
142 | if (onstack) | | 143 | if (onstack) |
143 | sp = ((char *)l->l_sigstk.ss_sp + | | 144 | sp = ((char *)l->l_sigstk.ss_sp + |
144 | l->l_sigstk.ss_size); | | 145 | l->l_sigstk.ss_size); |
145 | else | | 146 | else |
146 | sp = (char *)tf->tf_rsp - 128; | | 147 | sp = (char *)tf->tf_rsp - 128; |
147 | | | 148 | |
148 | /* Save FPU state */ | | 149 | /* Save FPU state */ |
149 | sp = (char *) (((long)sp - sizeof (*fpsp)) & ~0xfUL); | | 150 | sp = (char *) (((long)sp - sizeof (*fpsp)) & ~0xfUL); |
150 | fpsp = (struct linux__fpstate *)sp; | | 151 | fpsp = (struct linux__fpstate *)sp; |
151 | | | 152 | |
152 | /* | | 153 | /* |
153 | * Populate the rt_sigframe | | 154 | * Populate the rt_sigframe |
154 | */ | | 155 | */ |
155 | sp = (char *) | | 156 | sp = (char *) |
156 | ((((long)sp - sizeof(struct linux_rt_sigframe)) & ~0xfUL) - 8); | | 157 | ((((long)sp - sizeof(struct linux_rt_sigframe)) & ~0xfUL) - 8); |
157 | sfp = (struct linux_rt_sigframe *)sp; | | 158 | sfp = (struct linux_rt_sigframe *)sp; |
158 | | | 159 | |
159 | memset(&sigframe, 0, sizeof(sigframe)); | | 160 | memset(&sigframe, 0, sizeof(sigframe)); |
160 | if (ps->sa_sigdesc[sig].sd_vers != 0) | | 161 | if (ps->sa_sigdesc[sig].sd_vers != 0) |
161 | sigframe.pretcode = | | 162 | sigframe.pretcode = |
162 | (char *)(u_long)ps->sa_sigdesc[sig].sd_tramp; | | 163 | (char *)(u_long)ps->sa_sigdesc[sig].sd_tramp; |
163 | else | | 164 | else |
164 | sigframe.pretcode = NULL; | | 165 | sigframe.pretcode = NULL; |
165 | | | 166 | |
166 | /* | | 167 | /* |
167 | * The user context | | 168 | * The user context |
168 | */ | | 169 | */ |
169 | sigframe.uc.luc_flags = 0; | | 170 | sigframe.uc.luc_flags = 0; |
170 | sigframe.uc.luc_link = NULL; | | 171 | sigframe.uc.luc_link = NULL; |
171 | | | 172 | |
172 | /* This is used regardless of SA_ONSTACK in Linux */ | | 173 | /* This is used regardless of SA_ONSTACK in Linux */ |
173 | sigframe.uc.luc_stack.ss_sp = l->l_sigstk.ss_sp; | | 174 | sigframe.uc.luc_stack.ss_sp = l->l_sigstk.ss_sp; |
174 | sigframe.uc.luc_stack.ss_size = l->l_sigstk.ss_size; | | 175 | sigframe.uc.luc_stack.ss_size = l->l_sigstk.ss_size; |
175 | sigframe.uc.luc_stack.ss_flags = 0; | | 176 | sigframe.uc.luc_stack.ss_flags = 0; |
176 | if (l->l_sigstk.ss_flags & SS_ONSTACK) | | 177 | if (l->l_sigstk.ss_flags & SS_ONSTACK) |
177 | sigframe.uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK; | | 178 | sigframe.uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK; |
178 | if (l->l_sigstk.ss_flags & SS_DISABLE) | | 179 | if (l->l_sigstk.ss_flags & SS_DISABLE) |
179 | sigframe.uc.luc_stack.ss_flags |= LINUX_SS_DISABLE; | | 180 | sigframe.uc.luc_stack.ss_flags |= LINUX_SS_DISABLE; |
180 | | | 181 | |
181 | sigframe.uc.luc_mcontext.r8 = tf->tf_r8; | | 182 | sigframe.uc.luc_mcontext.r8 = tf->tf_r8; |
182 | sigframe.uc.luc_mcontext.r9 = tf->tf_r9; | | 183 | sigframe.uc.luc_mcontext.r9 = tf->tf_r9; |
183 | sigframe.uc.luc_mcontext.r10 = tf->tf_r10; | | 184 | sigframe.uc.luc_mcontext.r10 = tf->tf_r10; |
184 | sigframe.uc.luc_mcontext.r11 = tf->tf_r11; | | 185 | sigframe.uc.luc_mcontext.r11 = tf->tf_r11; |
185 | sigframe.uc.luc_mcontext.r12 = tf->tf_r12; | | 186 | sigframe.uc.luc_mcontext.r12 = tf->tf_r12; |
186 | sigframe.uc.luc_mcontext.r13 = tf->tf_r13; | | 187 | sigframe.uc.luc_mcontext.r13 = tf->tf_r13; |
187 | sigframe.uc.luc_mcontext.r14 = tf->tf_r14; | | 188 | sigframe.uc.luc_mcontext.r14 = tf->tf_r14; |
188 | sigframe.uc.luc_mcontext.r15 = tf->tf_r15; | | 189 | sigframe.uc.luc_mcontext.r15 = tf->tf_r15; |
189 | sigframe.uc.luc_mcontext.rdi = tf->tf_rdi; | | 190 | sigframe.uc.luc_mcontext.rdi = tf->tf_rdi; |
190 | sigframe.uc.luc_mcontext.rsi = tf->tf_rsi; | | 191 | sigframe.uc.luc_mcontext.rsi = tf->tf_rsi; |
191 | sigframe.uc.luc_mcontext.rbp = tf->tf_rbp; | | 192 | sigframe.uc.luc_mcontext.rbp = tf->tf_rbp; |
192 | sigframe.uc.luc_mcontext.rbx = tf->tf_rbx; | | 193 | sigframe.uc.luc_mcontext.rbx = tf->tf_rbx; |
193 | sigframe.uc.luc_mcontext.rdx = tf->tf_rdx; | | 194 | sigframe.uc.luc_mcontext.rdx = tf->tf_rdx; |
194 | sigframe.uc.luc_mcontext.rax = tf->tf_rax; | | 195 | sigframe.uc.luc_mcontext.rax = tf->tf_rax; |
195 | sigframe.uc.luc_mcontext.rcx = tf->tf_rcx; | | 196 | sigframe.uc.luc_mcontext.rcx = tf->tf_rcx; |
196 | sigframe.uc.luc_mcontext.rsp = tf->tf_rsp; | | 197 | sigframe.uc.luc_mcontext.rsp = tf->tf_rsp; |
197 | sigframe.uc.luc_mcontext.rip = tf->tf_rip; | | 198 | sigframe.uc.luc_mcontext.rip = tf->tf_rip; |
198 | sigframe.uc.luc_mcontext.eflags = tf->tf_rflags; | | 199 | sigframe.uc.luc_mcontext.eflags = tf->tf_rflags; |
199 | sigframe.uc.luc_mcontext.cs = tf->tf_cs; | | 200 | sigframe.uc.luc_mcontext.cs = tf->tf_cs; |
200 | sigframe.uc.luc_mcontext.gs = tf->tf_gs; | | 201 | sigframe.uc.luc_mcontext.gs = tf->tf_gs; |
201 | sigframe.uc.luc_mcontext.fs = tf->tf_fs; | | 202 | sigframe.uc.luc_mcontext.fs = tf->tf_fs; |
202 | sigframe.uc.luc_mcontext.err = tf->tf_err; | | 203 | sigframe.uc.luc_mcontext.err = tf->tf_err; |
203 | sigframe.uc.luc_mcontext.trapno = tf->tf_trapno; | | 204 | sigframe.uc.luc_mcontext.trapno = tf->tf_trapno; |
204 | native_to_linux_sigset(&lmask, mask); | | 205 | native_to_linux_sigset(&lmask, mask); |
205 | sigframe.uc.luc_mcontext.oldmask = lmask.sig[0]; | | 206 | sigframe.uc.luc_mcontext.oldmask = lmask.sig[0]; |
206 | sigframe.uc.luc_mcontext.cr2 = (long)pcb->pcb_onfault; | | 207 | sigframe.uc.luc_mcontext.cr2 = (long)pcb->pcb_onfault; |
207 | sigframe.uc.luc_mcontext.fpstate = fpsp; | | 208 | sigframe.uc.luc_mcontext.fpstate = fpsp; |
208 | native_to_linux_sigset(&sigframe.uc.luc_sigmask, mask); | | 209 | native_to_linux_sigset(&sigframe.uc.luc_sigmask, mask); |
209 | native_to_linux_siginfo(&sigframe.info, &ksi->ksi_info); | | 210 | native_to_linux_siginfo(&sigframe.info, &ksi->ksi_info); |
210 | sendsig_reset(l, sig); | | 211 | sendsig_reset(l, sig); |
211 | mutex_exit(p->p_lock); | | 212 | mutex_exit(p->p_lock); |
212 | error = 0; | | 213 | error = 0; |
213 | | | 214 | |
214 | /* | | 215 | /* |
215 | * Save FPU state, if any | | 216 | * Save FPU state, if any |
216 | */ | | 217 | */ |
217 | if (fpsp != NULL) { | | 218 | if (fpsp != NULL) { |
218 | size_t fp_size = sizeof fpregs; | | 219 | size_t fp_size = sizeof fpregs; |
219 | /* The netbsd and linux structures both match the fxsave data */ | | 220 | /* The netbsd and linux structures both match the fxsave data */ |
220 | (void)process_read_fpregs(l, &fpregs, &fp_size); | | 221 | (void)process_read_fpregs(l, &fpregs, &fp_size); |
221 | error = copyout(&fpregs, fpsp, sizeof(*fpsp)); | | 222 | error = copyout(&fpregs, fpsp, sizeof(*fpsp)); |
222 | } | | 223 | } |
223 | | | 224 | |
224 | if (error == 0) | | 225 | if (error == 0) |
225 | error = copyout(&sigframe, sp, sizeof(sigframe)); | | 226 | error = copyout(&sigframe, sp, sizeof(sigframe)); |
226 | | | 227 | |
227 | mutex_enter(p->p_lock); | | 228 | mutex_enter(p->p_lock); |
228 | | | 229 | |
229 | if (error != 0) { | | 230 | if (error != 0) { |
230 | sigexit(l, SIGILL); | | 231 | sigexit(l, SIGILL); |
231 | return; | | 232 | return; |
232 | } | | 233 | } |
233 | | | 234 | |
234 | linux_buildcontext(l, catcher, sp); | | 235 | linux_buildcontext(l, catcher, sp); |
235 | tf->tf_rdi = sigframe.info.lsi_signo; | | 236 | tf->tf_rdi = sigframe.info.lsi_signo; |
236 | tf->tf_rax = 0; | | 237 | tf->tf_rax = 0; |
237 | tf->tf_rsi = (long)&sfp->info; | | 238 | tf->tf_rsi = (long)&sfp->info; |
238 | tf->tf_rdx = (long)&sfp->uc; | | 239 | tf->tf_rdx = (long)&sfp->uc; |
239 | | | 240 | |
240 | /* | | 241 | /* |
241 | * Remember we use signal stack | | 242 | * Remember we use signal stack |
242 | */ | | 243 | */ |
243 | if (onstack) | | 244 | if (onstack) |
244 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 245 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
245 | return; | | 246 | return; |
246 | } | | 247 | } |
247 | | | 248 | |
248 | int | | 249 | int |
249 | linux_sys_modify_ldt(struct lwp *l, const struct linux_sys_modify_ldt_args *v, register_t *retval) | | 250 | linux_sys_modify_ldt(struct lwp *l, const struct linux_sys_modify_ldt_args *v, register_t *retval) |
250 | { | | 251 | { |
251 | printf("linux_sys_modify_ldt\n"); | | 252 | printf("linux_sys_modify_ldt\n"); |
252 | return 0; | | 253 | return 0; |
253 | } | | 254 | } |
254 | | | 255 | |
255 | int | | 256 | int |
256 | linux_sys_iopl(struct lwp *l, const struct linux_sys_iopl_args *v, register_t *retval) | | 257 | linux_sys_iopl(struct lwp *l, const struct linux_sys_iopl_args *v, register_t *retval) |
257 | { | | 258 | { |
258 | return 0; | | 259 | return 0; |
259 | } | | 260 | } |
260 | | | 261 | |
261 | int | | 262 | int |
262 | linux_sys_ioperm(struct lwp *l, const struct linux_sys_ioperm_args *v, register_t *retval) | | 263 | linux_sys_ioperm(struct lwp *l, const struct linux_sys_ioperm_args *v, register_t *retval) |
263 | { | | 264 | { |
264 | return 0; | | 265 | return 0; |
265 | } | | 266 | } |
266 | | | 267 | |
267 | dev_t | | 268 | dev_t |
268 | linux_fakedev(dev_t dev, int raw) | | 269 | linux_fakedev(dev_t dev, int raw) |
269 | { | | 270 | { |
270 | | | 271 | |
271 | extern const struct cdevsw ptc_cdevsw, pts_cdevsw; | | 272 | extern const struct cdevsw ptc_cdevsw, pts_cdevsw; |
272 | const struct cdevsw *cd = cdevsw_lookup(dev); | | 273 | const struct cdevsw *cd = cdevsw_lookup(dev); |
273 | | | 274 | |
274 | if (raw) { | | 275 | if (raw) { |
275 | #if (NWSDISPLAY > 0) | | 276 | #if (NWSDISPLAY > 0) |
276 | extern const struct cdevsw wsdisplay_cdevsw; | | 277 | extern const struct cdevsw wsdisplay_cdevsw; |
277 | if (cd == &wsdisplay_cdevsw) | | 278 | if (cd == &wsdisplay_cdevsw) |
278 | return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1)); | | 279 | return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1)); |
279 | #endif | | 280 | #endif |
280 | } | | 281 | } |
281 | | | 282 | |
282 | if (cd == &ptc_cdevsw) | | 283 | if (cd == &ptc_cdevsw) |
283 | return makedev(LINUX_PTC_MAJOR, minor(dev)); | | 284 | return makedev(LINUX_PTC_MAJOR, minor(dev)); |
284 | if (cd == &pts_cdevsw) | | 285 | if (cd == &pts_cdevsw) |
285 | return makedev(LINUX_PTS_MAJOR, minor(dev)); | | 286 | return makedev(LINUX_PTS_MAJOR, minor(dev)); |
286 | | | 287 | |
287 | return ((minor(dev) & 0xff) | ((major(dev) & 0xfff) << 8) | | 288 | return ((minor(dev) & 0xff) | ((major(dev) & 0xfff) << 8) |
288 | | (((unsigned long long int) (minor(dev) & ~0xff)) << 12) | | 289 | | (((unsigned long long int) (minor(dev) & ~0xff)) << 12) |
289 | | (((unsigned long long int) (major(dev) & ~0xfff)) << 32)); | | 290 | | (((unsigned long long int) (major(dev) & ~0xfff)) << 32)); |
290 | } | | 291 | } |
291 | | | 292 | |
292 | int | | 293 | int |
293 | linux_machdepioctl(struct lwp *l, const struct linux_sys_ioctl_args *v, register_t *retval) | | 294 | linux_machdepioctl(struct lwp *l, const struct linux_sys_ioctl_args *v, register_t *retval) |
294 | { | | 295 | { |
295 | return 0; | | 296 | return 0; |
296 | } | | 297 | } |
297 | | | 298 | |
298 | int | | 299 | int |
299 | linux_sys_rt_sigreturn(struct lwp *l, const void *v, register_t *retval) | | 300 | linux_sys_rt_sigreturn(struct lwp *l, const void *v, register_t *retval) |
300 | { | | 301 | { |
301 | struct linux_ucontext *luctx; | | 302 | struct linux_ucontext *luctx; |
302 | struct trapframe *tf = l->l_md.md_regs; | | 303 | struct trapframe *tf = l->l_md.md_regs; |
303 | struct linux_sigcontext *lsigctx; | | 304 | struct linux_sigcontext *lsigctx; |
304 | struct linux_rt_sigframe frame, *fp; | | 305 | struct linux_rt_sigframe frame, *fp; |
305 | ucontext_t uctx; | | 306 | ucontext_t uctx; |
306 | mcontext_t *mctx; | | 307 | mcontext_t *mctx; |
307 | struct fxsave *fxarea; | | 308 | struct fxsave *fxarea; |
308 | int error; | | 309 | int error; |
309 | | | 310 | |
310 | fp = (struct linux_rt_sigframe *)(tf->tf_rsp - 8); | | 311 | fp = (struct linux_rt_sigframe *)(tf->tf_rsp - 8); |
311 | if ((error = copyin(fp, &frame, sizeof(frame))) != 0) { | | 312 | if ((error = copyin(fp, &frame, sizeof(frame))) != 0) { |
312 | mutex_enter(l->l_proc->p_lock); | | 313 | mutex_enter(l->l_proc->p_lock); |
313 | sigexit(l, SIGILL); | | 314 | sigexit(l, SIGILL); |
314 | return error; | | 315 | return error; |
315 | } | | 316 | } |
316 | luctx = &frame.uc; | | 317 | luctx = &frame.uc; |
317 | lsigctx = &luctx->luc_mcontext; | | 318 | lsigctx = &luctx->luc_mcontext; |
318 | | | 319 | |
319 | memset(&uctx, 0, sizeof(uctx)); | | 320 | memset(&uctx, 0, sizeof(uctx)); |
320 | mctx = (mcontext_t *)&uctx.uc_mcontext; | | 321 | mctx = (mcontext_t *)&uctx.uc_mcontext; |
321 | fxarea = (struct fxsave *)&mctx->__fpregs; | | 322 | fxarea = (struct fxsave *)&mctx->__fpregs; |
322 | | | 323 | |
323 | /* | | 324 | /* |
324 | * Set the flags. Linux always have CPU, stack and signal state, | | 325 | * Set the flags. Linux always have CPU, stack and signal state, |
325 | * FPU is optional. uc_flags is not used to tell what we have. | | 326 | * FPU is optional. uc_flags is not used to tell what we have. |
326 | */ | | 327 | */ |
327 | uctx.uc_flags = (_UC_SIGMASK|_UC_CPU|_UC_STACK|_UC_CLRSTACK); | | 328 | uctx.uc_flags = (_UC_SIGMASK|_UC_CPU|_UC_STACK|_UC_CLRSTACK); |
328 | if (lsigctx->fpstate != NULL) | | 329 | if (lsigctx->fpstate != NULL) |
329 | uctx.uc_flags |= _UC_FPU; | | 330 | uctx.uc_flags |= _UC_FPU; |
330 | uctx.uc_link = NULL; | | 331 | uctx.uc_link = NULL; |
331 | | | 332 | |
332 | /* | | 333 | /* |
333 | * Signal set | | 334 | * Signal set |
334 | */ | | 335 | */ |
335 | linux_to_native_sigset(&uctx.uc_sigmask, &luctx->luc_sigmask); | | 336 | linux_to_native_sigset(&uctx.uc_sigmask, &luctx->luc_sigmask); |
336 | | | 337 | |
337 | /* | | 338 | /* |
338 | * CPU state | | 339 | * CPU state |
339 | */ | | 340 | */ |
340 | mctx->__gregs[_REG_R8] = lsigctx->r8; | | 341 | mctx->__gregs[_REG_R8] = lsigctx->r8; |
341 | mctx->__gregs[_REG_R9] = lsigctx->r9; | | 342 | mctx->__gregs[_REG_R9] = lsigctx->r9; |
342 | mctx->__gregs[_REG_R10] = lsigctx->r10; | | 343 | mctx->__gregs[_REG_R10] = lsigctx->r10; |
343 | mctx->__gregs[_REG_R11] = lsigctx->r11; | | 344 | mctx->__gregs[_REG_R11] = lsigctx->r11; |
344 | mctx->__gregs[_REG_R12] = lsigctx->r12; | | 345 | mctx->__gregs[_REG_R12] = lsigctx->r12; |
345 | mctx->__gregs[_REG_R13] = lsigctx->r13; | | 346 | mctx->__gregs[_REG_R13] = lsigctx->r13; |
346 | mctx->__gregs[_REG_R14] = lsigctx->r14; | | 347 | mctx->__gregs[_REG_R14] = lsigctx->r14; |
347 | mctx->__gregs[_REG_R15] = lsigctx->r15; | | 348 | mctx->__gregs[_REG_R15] = lsigctx->r15; |
348 | mctx->__gregs[_REG_RDI] = lsigctx->rdi; | | 349 | mctx->__gregs[_REG_RDI] = lsigctx->rdi; |
349 | mctx->__gregs[_REG_RSI] = lsigctx->rsi; | | 350 | mctx->__gregs[_REG_RSI] = lsigctx->rsi; |
350 | mctx->__gregs[_REG_RBP] = lsigctx->rbp; | | 351 | mctx->__gregs[_REG_RBP] = lsigctx->rbp; |
351 | mctx->__gregs[_REG_RBX] = lsigctx->rbx; | | 352 | mctx->__gregs[_REG_RBX] = lsigctx->rbx; |
352 | mctx->__gregs[_REG_RAX] = lsigctx->rax; | | 353 | mctx->__gregs[_REG_RAX] = lsigctx->rax; |
353 | mctx->__gregs[_REG_RDX] = lsigctx->rdx; | | 354 | mctx->__gregs[_REG_RDX] = lsigctx->rdx; |
354 | mctx->__gregs[_REG_RCX] = lsigctx->rcx; | | 355 | mctx->__gregs[_REG_RCX] = lsigctx->rcx; |
355 | mctx->__gregs[_REG_RIP] = lsigctx->rip; | | 356 | mctx->__gregs[_REG_RIP] = lsigctx->rip; |
356 | mctx->__gregs[_REG_RFLAGS] = lsigctx->eflags; | | 357 | mctx->__gregs[_REG_RFLAGS] = lsigctx->eflags; |
357 | mctx->__gregs[_REG_CS] = lsigctx->cs; | | 358 | mctx->__gregs[_REG_CS] = lsigctx->cs; |
358 | mctx->__gregs[_REG_GS] = lsigctx->gs; | | 359 | mctx->__gregs[_REG_GS] = lsigctx->gs; |
359 | mctx->__gregs[_REG_FS] = lsigctx->fs; | | 360 | mctx->__gregs[_REG_FS] = lsigctx->fs; |
360 | mctx->__gregs[_REG_ERR] = lsigctx->err; | | 361 | mctx->__gregs[_REG_ERR] = lsigctx->err; |
361 | mctx->__gregs[_REG_TRAPNO] = lsigctx->trapno; | | 362 | mctx->__gregs[_REG_TRAPNO] = lsigctx->trapno; |
362 | mctx->__gregs[_REG_ES] = tf->tf_es; | | 363 | mctx->__gregs[_REG_ES] = tf->tf_es; |
363 | mctx->__gregs[_REG_DS] = tf->tf_ds; | | 364 | mctx->__gregs[_REG_DS] = tf->tf_ds; |
364 | mctx->__gregs[_REG_RSP] = lsigctx->rsp; /* XXX */ | | 365 | mctx->__gregs[_REG_RSP] = lsigctx->rsp; /* XXX */ |
365 | mctx->__gregs[_REG_SS] = tf->tf_ss; | | 366 | mctx->__gregs[_REG_SS] = tf->tf_ss; |
366 | | | 367 | |
367 | /* | | 368 | /* |
368 | * FPU state | | 369 | * FPU state |
369 | */ | | 370 | */ |
370 | if (lsigctx->fpstate != NULL) { | | 371 | if (lsigctx->fpstate != NULL) { |
371 | /* Both structures match the fxstate data */ | | 372 | /* Both structures match the fxstate data */ |
372 | error = copyin(lsigctx->fpstate, fxarea, sizeof(*fxarea)); | | 373 | error = copyin(lsigctx->fpstate, fxarea, sizeof(*fxarea)); |
373 | if (error != 0) { | | 374 | if (error != 0) { |
374 | mutex_enter(l->l_proc->p_lock); | | 375 | mutex_enter(l->l_proc->p_lock); |
375 | sigexit(l, SIGILL); | | 376 | sigexit(l, SIGILL); |
376 | return error; | | 377 | return error; |
377 | } | | 378 | } |
378 | } | | 379 | } |
379 | | | 380 | |
380 | /* | | 381 | /* |
381 | * And the stack | | 382 | * And the stack |
382 | */ | | 383 | */ |
383 | uctx.uc_stack.ss_flags = 0; | | 384 | uctx.uc_stack.ss_flags = 0; |
384 | if (luctx->luc_stack.ss_flags & LINUX_SS_ONSTACK) | | 385 | if (luctx->luc_stack.ss_flags & LINUX_SS_ONSTACK) |
385 | uctx.uc_stack.ss_flags |= SS_ONSTACK; | | 386 | uctx.uc_stack.ss_flags |= SS_ONSTACK; |
386 | | | 387 | |
387 | if (luctx->luc_stack.ss_flags & LINUX_SS_DISABLE) | | 388 | if (luctx->luc_stack.ss_flags & LINUX_SS_DISABLE) |
388 | uctx.uc_stack.ss_flags |= SS_DISABLE; | | 389 | uctx.uc_stack.ss_flags |= SS_DISABLE; |
389 | | | 390 | |
390 | uctx.uc_stack.ss_sp = luctx->luc_stack.ss_sp; | | 391 | uctx.uc_stack.ss_sp = luctx->luc_stack.ss_sp; |
391 | uctx.uc_stack.ss_size = luctx->luc_stack.ss_size; | | 392 | uctx.uc_stack.ss_size = luctx->luc_stack.ss_size; |
392 | | | 393 | |
393 | /* | | 394 | /* |
394 | * And let setucontext deal with that. | | 395 | * And let setucontext deal with that. |
395 | */ | | 396 | */ |
396 | mutex_enter(l->l_proc->p_lock); | | 397 | mutex_enter(l->l_proc->p_lock); |
397 | error = setucontext(l, &uctx); | | 398 | error = setucontext(l, &uctx); |
398 | mutex_exit(l->l_proc->p_lock); | | 399 | mutex_exit(l->l_proc->p_lock); |
399 | if (error) | | 400 | if (error) |
400 | return error; | | 401 | return error; |
401 | | | 402 | |
402 | return EJUSTRETURN; | | 403 | return EJUSTRETURN; |
403 | } | | 404 | } |
404 | | | 405 | |
405 | int | | 406 | int |
406 | linux_sys_arch_prctl(struct lwp *l, | | 407 | linux_sys_arch_prctl(struct lwp *l, |
407 | const struct linux_sys_arch_prctl_args *uap, register_t *retval) | | 408 | const struct linux_sys_arch_prctl_args *uap, register_t *retval) |
408 | { | | 409 | { |
409 | /* { | | 410 | /* { |
410 | syscallarg(int) code; | | 411 | syscallarg(int) code; |
411 | syscallarg(unsigned long) addr; | | 412 | syscallarg(unsigned long) addr; |
412 | } */ | | 413 | } */ |
413 | void *addr = (void *)SCARG(uap, addr); | | 414 | void *addr = (void *)SCARG(uap, addr); |
414 | | | 415 | |
415 | switch(SCARG(uap, code)) { | | 416 | switch(SCARG(uap, code)) { |
416 | case LINUX_ARCH_SET_GS: | | 417 | case LINUX_ARCH_SET_GS: |
417 | return x86_set_sdbase(addr, 'g', l, true); | | 418 | return x86_set_sdbase(addr, 'g', l, true); |
418 | | | 419 | |
419 | case LINUX_ARCH_GET_GS: | | 420 | case LINUX_ARCH_GET_GS: |
420 | return x86_get_sdbase(addr, 'g'); | | 421 | return x86_get_sdbase(addr, 'g'); |
421 | | | 422 | |
422 | case LINUX_ARCH_SET_FS: | | 423 | case LINUX_ARCH_SET_FS: |
423 | return x86_set_sdbase(addr, 'f', l, true); | | 424 | return x86_set_sdbase(addr, 'f', l, true); |
424 | | | 425 | |
425 | case LINUX_ARCH_GET_FS: | | 426 | case LINUX_ARCH_GET_FS: |
426 | return x86_get_sdbase(addr, 'f'); | | 427 | return x86_get_sdbase(addr, 'f'); |
427 | | | 428 | |
428 | default: | | 429 | default: |
429 | #ifdef DEBUG_LINUX | | 430 | #ifdef DEBUG_LINUX |
430 | printf("linux_sys_arch_prctl: unexpected code %d\n", | | 431 | printf("linux_sys_arch_prctl: unexpected code %d\n", |
431 | SCARG(uap, code)); | | 432 | SCARG(uap, code)); |
432 | #endif | | 433 | #endif |
433 | return EINVAL; | | 434 | return EINVAL; |
434 | } | | 435 | } |
435 | /* NOTREACHED */ | | 436 | /* NOTREACHED */ |
436 | } | | 437 | } |
437 | | | 438 | |
438 | const int linux_vsyscall_to_syscall[] = { | | 439 | const int linux_vsyscall_to_syscall[] = { |
439 | LINUX_SYS_gettimeofday, | | 440 | LINUX_SYS_gettimeofday, |
440 | LINUX_SYS_time, | | 441 | LINUX_SYS_time, |
441 | LINUX_SYS_nosys, /* nosys */ | | 442 | LINUX_SYS_nosys, /* nosys */ |
442 | LINUX_SYS_nosys, /* nosys */ | | 443 | LINUX_SYS_nosys, /* nosys */ |
443 | }; | | 444 | }; |
444 | | | 445 | |
445 | int | | 446 | int |
446 | linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg) | | 447 | linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg) |
447 | { | | 448 | { |
448 | struct trapframe *tf = arg; | | 449 | struct trapframe *tf = arg; |
449 | uint64_t retaddr; | | 450 | uint64_t retaddr; |
450 | int vsyscallnr; | | 451 | int vsyscallnr; |
451 | | | 452 | |
452 | /* | | 453 | /* |
453 | * Check for a vsyscall. %rip must be the fault address, | | 454 | * Check for a vsyscall. %rip must be the fault address, |
454 | * and the address must be in the Linux vsyscall area. | | 455 | * and the address must be in the Linux vsyscall area. |
455 | * Also, vsyscalls are only done at 1024-byte boundaries. | | 456 | * Also, vsyscalls are only done at 1024-byte boundaries. |
456 | */ | | 457 | */ |
457 | | | 458 | |
458 | if (__predict_true(trapaddr < LINUX_VSYSCALL_START)) | | 459 | if (__predict_true(trapaddr < LINUX_VSYSCALL_START)) |
459 | return 0; | | 460 | return 0; |
460 | | | 461 | |
461 | if (trapaddr != tf->tf_rip) | | 462 | if (trapaddr != tf->tf_rip) |
462 | return 0; | | 463 | return 0; |
463 | | | 464 | |
464 | if ((tf->tf_rip & (LINUX_VSYSCALL_SIZE - 1)) != 0) | | 465 | if ((tf->tf_rip & (LINUX_VSYSCALL_SIZE - 1)) != 0) |
465 | return 0; | | 466 | return 0; |
466 | | | 467 | |
467 | vsyscallnr = (tf->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SIZE; | | 468 | vsyscallnr = (tf->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SIZE; |
468 | | | 469 | |
469 | if (vsyscallnr > LINUX_VSYSCALL_MAXNR) | | 470 | if (vsyscallnr > LINUX_VSYSCALL_MAXNR) |
470 | return 0; | | 471 | return 0; |
471 | | | 472 | |
472 | /* | | 473 | /* |
473 | * Get the return address from the top of the stack, | | 474 | * Get the return address from the top of the stack, |
474 | * and fix up the return address. | | 475 | * and fix up the return address. |
475 | * This assumes the faulting instruction was callq *reg, | | 476 | * This assumes the faulting instruction was callq *reg, |
476 | * which is the only way that vsyscalls are ever entered. | | 477 | * which is the only way that vsyscalls are ever entered. |
477 | */ | | 478 | */ |
478 | if (copyin((void *)tf->tf_rsp, &retaddr, sizeof retaddr) != 0) | | 479 | if (copyin((void *)tf->tf_rsp, &retaddr, sizeof retaddr) != 0) |
479 | return 0; | | 480 | return 0; |
480 | tf->tf_rip = retaddr; | | 481 | tf->tf_rip = retaddr; |
481 | tf->tf_rax = linux_vsyscall_to_syscall[vsyscallnr]; | | 482 | tf->tf_rax = linux_vsyscall_to_syscall[vsyscallnr]; |
482 | tf->tf_rsp += 8; /* "pop" the return address */ | | 483 | tf->tf_rsp += 8; /* "pop" the return address */ |
483 | | | 484 | |
484 | #if 0 | | 485 | #if 0 |
485 | printf("usertrap: rip %p rsp %p retaddr %p vsys %d sys %d\n", | | 486 | printf("usertrap: rip %p rsp %p retaddr %p vsys %d sys %d\n", |
486 | (void *)tf->tf_rip, (void *)tf->tf_rsp, (void *)retaddr, | | 487 | (void *)tf->tf_rip, (void *)tf->tf_rsp, (void *)retaddr, |
487 | vsyscallnr, (int)tf->tf_rax); | | 488 | vsyscallnr, (int)tf->tf_rax); |
488 | #endif | | 489 | #endif |
489 | | | 490 | |
490 | (*l->l_proc->p_md.md_syscall)(tf); | | 491 | (*l->l_proc->p_md.md_syscall)(tf); |
491 | | | 492 | |
492 | return 1; | | 493 | return 1; |
493 | } | | 494 | } |
494 | | | 495 | |
495 | static void | | 496 | static void |
496 | linux_buildcontext(struct lwp *l, void *catcher, void *f) | | 497 | linux_buildcontext(struct lwp *l, void *catcher, void *f) |
497 | { | | 498 | { |
498 | struct trapframe *tf = l->l_md.md_regs; | | 499 | struct trapframe *tf = l->l_md.md_regs; |
499 | | | 500 | |
500 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); | | 501 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); |
501 | tf->tf_rip = (u_int64_t)catcher; | | 502 | tf->tf_rip = (u_int64_t)catcher; |
502 | tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); | | 503 | tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); |
503 | tf->tf_rflags &= ~PSL_CLEARSIG; | | 504 | tf->tf_rflags &= ~PSL_CLEARSIG; |
504 | tf->tf_rsp = (u_int64_t)f; | | 505 | tf->tf_rsp = (u_int64_t)f; |
505 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); | | 506 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); |
506 | } | | 507 | } |