3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/vmparam.h>
33 #include <sys/systm.h>
34 #include <sys/signal.h>
35 #include <sys/stack.h>
36 #include <sys/regset.h>
37 #include <sys/privregs.h>
38 #include <sys/frame.h>
39 #include <sys/proc.h>
40 #include <sys/brand.h>
41 #include <sys/psw.h>
42 #include <sys/ucontext.h>
43 #include <sys/asm_linkage.h>
44 #include <sys/errno.h>
45 #include <sys/archsystm.h>
46 #include <sys/schedctl.h>
47 #include <sys/debug.h>
48 #include <sys/sysmacros.h>
49
50 /*
51 * Save user context.
52 */
53 void
54 savecontext(ucontext_t *ucp, const k_sigset_t *mask)
55 {
56 proc_t *p = ttoproc(curthread);
57 klwp_t *lwp = ttolwp(curthread);
58 struct regs *rp = lwptoregs(lwp);
59
60 /*
61 * We unconditionally assign to every field through the end
62 * of the gregs, but we need to bzero() everything -after- that
63 * to avoid having any kernel stack garbage escape to userland.
64 */
65 bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext_t) -
66 offsetof(ucontext_t, uc_mcontext.fpregs));
67
68 ucp->uc_flags = UC_ALL;
108 * honoured. (for eg: the lwp is stopped by
109 * stop_on_fault() called from trap(), after being
110 * awakened it might see a pending signal and call
111 * savecontext(), however on the way back to userland
112 * there is no place it can be detected). Hence in
113 * anticipation of such occassions, set AST flag for
114 * the thread which will make the thread take an
115 * excursion through trap() where it will be handled
116 * appropriately.
117 */
118 aston(curthread);
119 }
120 }
121
122 getgregs(lwp, ucp->uc_mcontext.gregs);
123 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
124 getfpregs(lwp, &ucp->uc_mcontext.fpregs);
125 else
126 ucp->uc_flags &= ~UC_FPU;
127
128 sigktou(mask, &ucp->uc_sigmask);
129 }
130
131 /*
132 * Restore user context.
133 */
134 void
135 restorecontext(ucontext_t *ucp)
136 {
137 kthread_t *t = curthread;
138 klwp_t *lwp = ttolwp(t);
139
140 lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link;
141
142 if (ucp->uc_flags & UC_STACK) {
143 if (ucp->uc_stack.ss_flags == SS_ONSTACK)
144 lwp->lwp_sigaltstack = ucp->uc_stack;
145 else
146 lwp->lwp_sigaltstack.ss_flags &= ~SS_ONSTACK;
147 }
148
149 if (ucp->uc_flags & UC_CPU) {
150 /*
151 * If the trace flag is set, mark the lwp to take a
152 * single-step trap on return to user level (below).
153 * The x86 lcall interface and sysenter has already done this,
154 * and turned off the flag, but amd64 syscall interface has not.
155 */
156 if (lwptoregs(lwp)->r_ps & PS_T)
157 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
158 setgregs(lwp, ucp->uc_mcontext.gregs);
159 lwp->lwp_eosys = JUSTRETURN;
167 if (ucp->uc_flags & UC_SIGMASK) {
168 /*
169 * We don't need to acquire p->p_lock here;
170 * we are manipulating thread-private data.
171 */
172 schedctl_finish_sigblock(t);
173 sigutok(&ucp->uc_sigmask, &t->t_hold);
174 if (sigcheck(ttoproc(t), t))
175 t->t_sig_check = 1;
176 }
177 }
178
179
180 int
181 getsetcontext(int flag, void *arg)
182 {
183 ucontext_t uc;
184 ucontext_t *ucp;
185 klwp_t *lwp = ttolwp(curthread);
186 stack_t dummy_stk;
187
188 /*
189 * In future releases, when the ucontext structure grows,
190 * getcontext should be modified to only return the fields
191 * specified in the uc_flags. That way, the structure can grow
192 * and still be binary compatible will all .o's which will only
193 * have old fields defined in uc_flags
194 */
195
196 switch (flag) {
197 default:
198 return (set_errno(EINVAL));
199
200 case GETCONTEXT:
201 schedctl_finish_sigblock(curthread);
202 savecontext(&uc, &curthread->t_hold);
203 if (uc.uc_flags & UC_SIGMASK)
204 SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
205 if (copyout(&uc, arg, sizeof (uc)))
206 return (set_errno(EFAULT));
211 if (ucp == NULL)
212 exit(CLD_EXITED, 0);
213 /*
214 * Don't copyin filler or floating state unless we need it.
215 * The ucontext_t struct and fields are specified in the ABI.
216 */
217 if (copyin(ucp, &uc, sizeof (ucontext_t) -
218 sizeof (uc.uc_filler) -
219 sizeof (uc.uc_mcontext.fpregs))) {
220 return (set_errno(EFAULT));
221 }
222 if (uc.uc_flags & UC_SIGMASK)
223 SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
224
225 if ((uc.uc_flags & UC_FPU) &&
226 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
227 sizeof (uc.uc_mcontext.fpregs))) {
228 return (set_errno(EFAULT));
229 }
230
231 restorecontext(&uc);
232
233 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
234 (void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack,
235 sizeof (uc.uc_stack));
236 return (0);
237
238 case GETUSTACK:
239 if (copyout(&lwp->lwp_ustack, arg, sizeof (caddr_t)))
240 return (set_errno(EFAULT));
241 return (0);
242
243 case SETUSTACK:
244 if (copyin(arg, &dummy_stk, sizeof (dummy_stk)))
245 return (set_errno(EFAULT));
246 lwp->lwp_ustack = (uintptr_t)arg;
247 return (0);
248 }
249 }
250
294 * Clear PS_T so that saved user context won't have trace
295 * flag set.
296 */
297 rp->r_ps &= ~PS_T;
298
299 if (!(lwp->lwp_pcb.pcb_flags & REQUEST_NOSTEP)) {
300 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
301 /*
302 * See comments in savecontext().
303 */
304 aston(curthread);
305 }
306 }
307
308 getgregs32(lwp, ucp->uc_mcontext.gregs);
309 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
310 getfpregs32(lwp, &ucp->uc_mcontext.fpregs);
311 else
312 ucp->uc_flags &= ~UC_FPU;
313
314 sigktou(mask, &ucp->uc_sigmask);
315 }
316
317 int
318 getsetcontext32(int flag, void *arg)
319 {
320 ucontext32_t uc;
321 ucontext_t ucnat;
322 ucontext32_t *ucp;
323 klwp_t *lwp = ttolwp(curthread);
324 caddr32_t ustack32;
325 stack32_t dummy_stk32;
326
327 switch (flag) {
328 default:
329 return (set_errno(EINVAL));
330
331 case GETCONTEXT:
332 schedctl_finish_sigblock(curthread);
333 savecontext32(&uc, &curthread->t_hold);
334 if (uc.uc_flags & UC_SIGMASK)
335 SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
336 if (copyout(&uc, arg, sizeof (uc)))
337 return (set_errno(EFAULT));
338 return (0);
339
340 case SETCONTEXT:
341 ucp = arg;
342 if (ucp == NULL)
343 exit(CLD_EXITED, 0);
344 if (copyin(ucp, &uc, sizeof (uc) -
345 sizeof (uc.uc_filler) -
346 sizeof (uc.uc_mcontext.fpregs))) {
347 return (set_errno(EFAULT));
348 }
349 if (uc.uc_flags & UC_SIGMASK)
350 SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
351 if ((uc.uc_flags & UC_FPU) &&
352 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
353 sizeof (uc.uc_mcontext.fpregs))) {
354 return (set_errno(EFAULT));
355 }
356
357 ucontext_32ton(&uc, &ucnat);
358 restorecontext(&ucnat);
359
360 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
361 (void) copyout(&uc.uc_stack,
362 (stack32_t *)lwp->lwp_ustack, sizeof (uc.uc_stack));
363 return (0);
364
365 case GETUSTACK:
366 ustack32 = (caddr32_t)lwp->lwp_ustack;
367 if (copyout(&ustack32, arg, sizeof (ustack32)))
368 return (set_errno(EFAULT));
369 return (0);
370
371 case SETUSTACK:
372 if (copyin(arg, &dummy_stk32, sizeof (dummy_stk32)))
373 return (set_errno(EFAULT));
374 lwp->lwp_ustack = (uintptr_t)arg;
375 return (0);
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Joyent, Inc.
24 */
25 /*
26 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
32
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/vmparam.h>
36 #include <sys/systm.h>
37 #include <sys/signal.h>
38 #include <sys/stack.h>
39 #include <sys/regset.h>
40 #include <sys/privregs.h>
41 #include <sys/frame.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/psw.h>
45 #include <sys/ucontext.h>
46 #include <sys/asm_linkage.h>
47 #include <sys/errno.h>
48 #include <sys/archsystm.h>
49 #include <sys/schedctl.h>
50 #include <sys/debug.h>
51 #include <sys/sysmacros.h>
52 #include <sys/sdt.h>
53
54 /*
55 * Save user context.
56 */
57 void
58 savecontext(ucontext_t *ucp, const k_sigset_t *mask)
59 {
60 proc_t *p = ttoproc(curthread);
61 klwp_t *lwp = ttolwp(curthread);
62 struct regs *rp = lwptoregs(lwp);
63
64 /*
65 * We unconditionally assign to every field through the end
66 * of the gregs, but we need to bzero() everything -after- that
67 * to avoid having any kernel stack garbage escape to userland.
68 */
69 bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext_t) -
70 offsetof(ucontext_t, uc_mcontext.fpregs));
71
72 ucp->uc_flags = UC_ALL;
112 * honoured. (for eg: the lwp is stopped by
113 * stop_on_fault() called from trap(), after being
114 * awakened it might see a pending signal and call
115 * savecontext(), however on the way back to userland
116 * there is no place it can be detected). Hence in
117 * anticipation of such occassions, set AST flag for
118 * the thread which will make the thread take an
119 * excursion through trap() where it will be handled
120 * appropriately.
121 */
122 aston(curthread);
123 }
124 }
125
126 getgregs(lwp, ucp->uc_mcontext.gregs);
127 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
128 getfpregs(lwp, &ucp->uc_mcontext.fpregs);
129 else
130 ucp->uc_flags &= ~UC_FPU;
131
132 if (mask != NULL) {
133 /*
134 * Save signal mask.
135 */
136 sigktou(mask, &ucp->uc_sigmask);
137 } else {
138 ucp->uc_flags &= ~UC_SIGMASK;
139 bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
140 }
141
142 if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext != NULL) {
143 /*
144 * Allow the brand the chance to modify the context we
145 * saved:
146 */
147 BROP(p)->b_savecontext(ucp);
148 }
149 }
150
151 /*
152 * Restore user context.
153 */
154 void
155 restorecontext(ucontext_t *ucp)
156 {
157 kthread_t *t = curthread;
158 klwp_t *lwp = ttolwp(t);
159 proc_t *p = lwptoproc(lwp);
160
161 if (PROC_IS_BRANDED(p) && BROP(p)->b_restorecontext != NULL) {
162 /*
163 * Allow the brand the chance to modify the context before
164 * we restore it:
165 */
166 BROP(p)->b_restorecontext(ucp);
167 }
168
169 DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
170 uintptr_t, lwp->lwp_oldcontext,
171 uintptr_t, (uintptr_t)ucp->uc_link);
172 lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link;
173
174 if (ucp->uc_flags & UC_STACK) {
175 if (ucp->uc_stack.ss_flags == SS_ONSTACK)
176 lwp->lwp_sigaltstack = ucp->uc_stack;
177 else
178 lwp->lwp_sigaltstack.ss_flags &= ~SS_ONSTACK;
179 }
180
181 if (ucp->uc_flags & UC_CPU) {
182 /*
183 * If the trace flag is set, mark the lwp to take a
184 * single-step trap on return to user level (below).
185 * The x86 lcall interface and sysenter has already done this,
186 * and turned off the flag, but amd64 syscall interface has not.
187 */
188 if (lwptoregs(lwp)->r_ps & PS_T)
189 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
190 setgregs(lwp, ucp->uc_mcontext.gregs);
191 lwp->lwp_eosys = JUSTRETURN;
199 if (ucp->uc_flags & UC_SIGMASK) {
200 /*
201 * We don't need to acquire p->p_lock here;
202 * we are manipulating thread-private data.
203 */
204 schedctl_finish_sigblock(t);
205 sigutok(&ucp->uc_sigmask, &t->t_hold);
206 if (sigcheck(ttoproc(t), t))
207 t->t_sig_check = 1;
208 }
209 }
210
211
212 int
213 getsetcontext(int flag, void *arg)
214 {
215 ucontext_t uc;
216 ucontext_t *ucp;
217 klwp_t *lwp = ttolwp(curthread);
218 stack_t dummy_stk;
219 proc_t *p = lwptoproc(lwp);
220
221 /*
222 * In future releases, when the ucontext structure grows,
223 * getcontext should be modified to only return the fields
224 * specified in the uc_flags. That way, the structure can grow
225 * and still be binary compatible will all .o's which will only
226 * have old fields defined in uc_flags
227 */
228
229 switch (flag) {
230 default:
231 return (set_errno(EINVAL));
232
233 case GETCONTEXT:
234 schedctl_finish_sigblock(curthread);
235 savecontext(&uc, &curthread->t_hold);
236 if (uc.uc_flags & UC_SIGMASK)
237 SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
238 if (copyout(&uc, arg, sizeof (uc)))
239 return (set_errno(EFAULT));
244 if (ucp == NULL)
245 exit(CLD_EXITED, 0);
246 /*
247 * Don't copyin filler or floating state unless we need it.
248 * The ucontext_t struct and fields are specified in the ABI.
249 */
250 if (copyin(ucp, &uc, sizeof (ucontext_t) -
251 sizeof (uc.uc_filler) -
252 sizeof (uc.uc_mcontext.fpregs))) {
253 return (set_errno(EFAULT));
254 }
255 if (uc.uc_flags & UC_SIGMASK)
256 SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
257
258 if ((uc.uc_flags & UC_FPU) &&
259 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
260 sizeof (uc.uc_mcontext.fpregs))) {
261 return (set_errno(EFAULT));
262 }
263
264 /*
265 * If this is a branded process, copy in the brand-private
266 * data:
267 */
268 if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
269 &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
270 return (set_errno(EFAULT));
271 }
272
273 restorecontext(&uc);
274
275 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
276 (void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack,
277 sizeof (uc.uc_stack));
278 return (0);
279
280 case GETUSTACK:
281 if (copyout(&lwp->lwp_ustack, arg, sizeof (caddr_t)))
282 return (set_errno(EFAULT));
283 return (0);
284
285 case SETUSTACK:
286 if (copyin(arg, &dummy_stk, sizeof (dummy_stk)))
287 return (set_errno(EFAULT));
288 lwp->lwp_ustack = (uintptr_t)arg;
289 return (0);
290 }
291 }
292
336 * Clear PS_T so that saved user context won't have trace
337 * flag set.
338 */
339 rp->r_ps &= ~PS_T;
340
341 if (!(lwp->lwp_pcb.pcb_flags & REQUEST_NOSTEP)) {
342 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
343 /*
344 * See comments in savecontext().
345 */
346 aston(curthread);
347 }
348 }
349
350 getgregs32(lwp, ucp->uc_mcontext.gregs);
351 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
352 getfpregs32(lwp, &ucp->uc_mcontext.fpregs);
353 else
354 ucp->uc_flags &= ~UC_FPU;
355
356 if (mask != NULL) {
357 /*
358 * Save signal mask.
359 */
360 sigktou(mask, &ucp->uc_sigmask);
361 } else {
362 ucp->uc_flags &= ~UC_SIGMASK;
363 bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
364 }
365
366 if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext32 != NULL) {
367 /*
368 * Allow the brand the chance to modify the context we
369 * saved:
370 */
371 BROP(p)->b_savecontext32(ucp);
372 }
373 }
374
375 int
376 getsetcontext32(int flag, void *arg)
377 {
378 ucontext32_t uc;
379 ucontext_t ucnat;
380 ucontext32_t *ucp;
381 klwp_t *lwp = ttolwp(curthread);
382 caddr32_t ustack32;
383 stack32_t dummy_stk32;
384 proc_t *p = lwptoproc(lwp);
385
386 switch (flag) {
387 default:
388 return (set_errno(EINVAL));
389
390 case GETCONTEXT:
391 schedctl_finish_sigblock(curthread);
392 savecontext32(&uc, &curthread->t_hold);
393 if (uc.uc_flags & UC_SIGMASK)
394 SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
395 if (copyout(&uc, arg, sizeof (uc)))
396 return (set_errno(EFAULT));
397 return (0);
398
399 case SETCONTEXT:
400 ucp = arg;
401 if (ucp == NULL)
402 exit(CLD_EXITED, 0);
403 if (copyin(ucp, &uc, sizeof (uc) -
404 sizeof (uc.uc_filler) -
405 sizeof (uc.uc_mcontext.fpregs))) {
406 return (set_errno(EFAULT));
407 }
408 if (uc.uc_flags & UC_SIGMASK)
409 SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
410 if ((uc.uc_flags & UC_FPU) &&
411 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
412 sizeof (uc.uc_mcontext.fpregs))) {
413 return (set_errno(EFAULT));
414 }
415
416 /*
417 * If this is a branded process, copy in the brand-private
418 * data:
419 */
420 if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
421 &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
422 return (set_errno(EFAULT));
423 }
424
425 ucontext_32ton(&uc, &ucnat);
426 restorecontext(&ucnat);
427
428 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
429 (void) copyout(&uc.uc_stack,
430 (stack32_t *)lwp->lwp_ustack, sizeof (uc.uc_stack));
431 return (0);
432
433 case GETUSTACK:
434 ustack32 = (caddr32_t)lwp->lwp_ustack;
435 if (copyout(&ustack32, arg, sizeof (ustack32)))
436 return (set_errno(EFAULT));
437 return (0);
438
439 case SETUSTACK:
440 if (copyin(arg, &dummy_stk32, sizeof (dummy_stk32)))
441 return (set_errno(EFAULT));
442 lwp->lwp_ustack = (uintptr_t)arg;
443 return (0);
|