17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
58efd794sudheer * Common Development and Distribution License (the "License").
68efd794sudheer * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate
227c478bdstevel@tonic-gate/*
23bdf0047Roger A. Faulkner * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277be238fRoger A. Faulkner/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287be238fRoger A. Faulkner/*	  All Rights Reserved  	*/
297c478bdstevel@tonic-gate
307c478bdstevel@tonic-gate#include <sys/param.h>
317c478bdstevel@tonic-gate#include <sys/types.h>
327c478bdstevel@tonic-gate#include <sys/vmparam.h>
337c478bdstevel@tonic-gate#include <sys/systm.h>
347c478bdstevel@tonic-gate#include <sys/signal.h>
357c478bdstevel@tonic-gate#include <sys/stack.h>
367c478bdstevel@tonic-gate#include <sys/regset.h>
377c478bdstevel@tonic-gate#include <sys/privregs.h>
387c478bdstevel@tonic-gate#include <sys/frame.h>
397c478bdstevel@tonic-gate#include <sys/proc.h>
408f798d3Roger A. Faulkner#include <sys/brand.h>
417c478bdstevel@tonic-gate#include <sys/psw.h>
427c478bdstevel@tonic-gate#include <sys/ucontext.h>
437c478bdstevel@tonic-gate#include <sys/asm_linkage.h>
447c478bdstevel@tonic-gate#include <sys/errno.h>
457c478bdstevel@tonic-gate#include <sys/archsystm.h>
467c478bdstevel@tonic-gate#include <sys/schedctl.h>
477c478bdstevel@tonic-gate#include <sys/debug.h>
487c478bdstevel@tonic-gate#include <sys/sysmacros.h>
497c478bdstevel@tonic-gate
507c478bdstevel@tonic-gate/*
517c478bdstevel@tonic-gate * Save user context.
527c478bdstevel@tonic-gate */
537c478bdstevel@tonic-gatevoid
54bdf0047Roger A. Faulknersavecontext(ucontext_t *ucp, const k_sigset_t *mask)
557c478bdstevel@tonic-gate{
567c478bdstevel@tonic-gate	proc_t *p = ttoproc(curthread);
577c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
588efd794sudheer	struct regs *rp = lwptoregs(lwp);
597c478bdstevel@tonic-gate
607c478bdstevel@tonic-gate	/*
617c478bdstevel@tonic-gate	 * We unconditionally assign to every field through the end
627c478bdstevel@tonic-gate	 * of the gregs, but we need to bzero() everything -after- that
637c478bdstevel@tonic-gate	 * to avoid having any kernel stack garbage escape to userland.
647c478bdstevel@tonic-gate	 */
657c478bdstevel@tonic-gate	bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext_t) -
667c478bdstevel@tonic-gate	    offsetof(ucontext_t, uc_mcontext.fpregs));
677c478bdstevel@tonic-gate
687c478bdstevel@tonic-gate	ucp->uc_flags = UC_ALL;
697c478bdstevel@tonic-gate	ucp->uc_link = (struct ucontext *)lwp->lwp_oldcontext;
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate	/*
727c478bdstevel@tonic-gate	 * Try to copyin() the ustack if one is registered. If the stack
737c478bdstevel@tonic-gate	 * has zero size, this indicates that stack bounds checking has
747c478bdstevel@tonic-gate	 * been disabled for this LWP. If stack bounds checking is disabled
757c478bdstevel@tonic-gate	 * or the copyin() fails, we fall back to the legacy behavior.
767c478bdstevel@tonic-gate	 */
777e12cebToomas Soome	if (lwp->lwp_ustack == (uintptr_t)NULL ||
787c478bdstevel@tonic-gate	    copyin((void *)lwp->lwp_ustack, &ucp->uc_stack,
797c478bdstevel@tonic-gate	    sizeof (ucp->uc_stack)) != 0 ||
807c478bdstevel@tonic-gate	    ucp->uc_stack.ss_size == 0) {
817c478bdstevel@tonic-gate
827c478bdstevel@tonic-gate		if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) {
837c478bdstevel@tonic-gate			ucp->uc_stack = lwp->lwp_sigaltstack;
847c478bdstevel@tonic-gate		} else {
857c478bdstevel@tonic-gate			ucp->uc_stack.ss_sp = p->p_usrstack - p->p_stksize;
867c478bdstevel@tonic-gate			ucp->uc_stack.ss_size = p->p_stksize;
877c478bdstevel@tonic-gate			ucp->uc_stack.ss_flags = 0;
887c478bdstevel@tonic-gate		}
897c478bdstevel@tonic-gate	}
907c478bdstevel@tonic-gate
9186d5155ksadhukh	/*
9286d5155ksadhukh	 * If either the trace flag or REQUEST_STEP is set,
9386d5155ksadhukh	 * arrange for single-stepping and turn off the trace flag.
9486d5155ksadhukh	 */
9586d5155ksadhukh	if ((rp->r_ps & PS_T) || (lwp->lwp_pcb.pcb_flags & REQUEST_STEP)) {
9686d5155ksadhukh		/*
9786d5155ksadhukh		 * Clear PS_T so that saved user context won't have trace
9886d5155ksadhukh		 * flag set.
9986d5155ksadhukh		 */
10086d5155ksadhukh		rp->r_ps &= ~PS_T;
10186d5155ksadhukh
10286d5155ksadhukh		if (!(lwp->lwp_pcb.pcb_flags & REQUEST_NOSTEP)) {
10386d5155ksadhukh			lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
10486d5155ksadhukh			/*
10586d5155ksadhukh			 * trap() always checks DEBUG_PENDING before
10686d5155ksadhukh			 * checking for any pending signal. This at times
10786d5155ksadhukh			 * can potentially lead to DEBUG_PENDING not being
10886d5155ksadhukh			 * honoured. (for eg: the lwp is stopped by
10986d5155ksadhukh			 * stop_on_fault() called from trap(), after being
11086d5155ksadhukh			 * awakened it might see a pending signal and call
11186d5155ksadhukh			 * savecontext(), however on the way back to userland
11286d5155ksadhukh			 * there is no place it can be detected). Hence in
11386d5155ksadhukh			 * anticipation of such occassions, set AST flag for
11486d5155ksadhukh			 * the thread which will make the thread take an
11586d5155ksadhukh			 * excursion through trap() where it will be handled
11686d5155ksadhukh			 * appropriately.
11786d5155ksadhukh			 */
11886d5155ksadhukh			aston(curthread);
11986d5155ksadhukh		}
12086d5155ksadhukh	}
12186d5155ksadhukh
1227c478bdstevel@tonic-gate	getgregs(lwp, ucp->uc_mcontext.gregs);
1237c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
1247c478bdstevel@tonic-gate		getfpregs(lwp, &ucp->uc_mcontext.fpregs);
1257c478bdstevel@tonic-gate	else
1267c478bdstevel@tonic-gate		ucp->uc_flags &= ~UC_FPU;
1277c478bdstevel@tonic-gate
128bdf0047Roger A. Faulkner	sigktou(mask, &ucp->uc_sigmask);
1297c478bdstevel@tonic-gate}
1307c478bdstevel@tonic-gate
1317c478bdstevel@tonic-gate/*
1327c478bdstevel@tonic-gate * Restore user context.
1337c478bdstevel@tonic-gate */
1347c478bdstevel@tonic-gatevoid
1357c478bdstevel@tonic-gaterestorecontext(ucontext_t *ucp)
1367c478bdstevel@tonic-gate{
1377c478bdstevel@tonic-gate	kthread_t *t = curthread;
1387c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(t);
1397c478bdstevel@tonic-gate
1407c478bdstevel@tonic-gate	lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link;
1417c478bdstevel@tonic-gate
1427c478bdstevel@tonic-gate	if (ucp->uc_flags & UC_STACK) {
1437c478bdstevel@tonic-gate		if (ucp->uc_stack.ss_flags == SS_ONSTACK)
1447c478bdstevel@tonic-gate			lwp->lwp_sigaltstack = ucp->uc_stack;
1457c478bdstevel@tonic-gate		else
1467c478bdstevel@tonic-gate			lwp->lwp_sigaltstack.ss_flags &= ~SS_ONSTACK;
1477c478bdstevel@tonic-gate	}
1487c478bdstevel@tonic-gate
1497c478bdstevel@tonic-gate	if (ucp->uc_flags & UC_CPU) {
1508efd794sudheer		/*
1518efd794sudheer		 * If the trace flag is set, mark the lwp to take a
1528efd794sudheer		 * single-step trap on return to user level (below).
1538efd794sudheer		 * The x86 lcall interface and sysenter has already done this,
1548efd794sudheer		 * and turned off the flag, but amd64 syscall interface has not.
1558efd794sudheer		 */
1568efd794sudheer		if (lwptoregs(lwp)->r_ps & PS_T)
1578efd794sudheer			lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
1587c478bdstevel@tonic-gate		setgregs(lwp, ucp->uc_mcontext.gregs);
1597c478bdstevel@tonic-gate		lwp->lwp_eosys = JUSTRETURN;
1607c478bdstevel@tonic-gate		t->t_post_sys = 1;
161d8aa0f5sudheer		aston(curthread);
1627c478bdstevel@tonic-gate	}
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate	if (ucp->uc_flags & UC_FPU)
1657c478bdstevel@tonic-gate		setfpregs(lwp, &ucp->uc_mcontext.fpregs);
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gate	if (ucp->uc_flags & UC_SIGMASK) {
1687be238fRoger A. Faulkner		/*
1697be238fRoger A. Faulkner		 * We don't need to acquire p->p_lock here;
1707be238fRoger A. Faulkner		 * we are manipulating thread-private data.
1717be238fRoger A. Faulkner		 */
1727c478bdstevel@tonic-gate		schedctl_finish_sigblock(t);
1737c478bdstevel@tonic-gate		sigutok(&ucp->uc_sigmask, &t->t_hold);
1747be238fRoger A. Faulkner		if (sigcheck(ttoproc(t), t))
1757c478bdstevel@tonic-gate			t->t_sig_check = 1;
1767c478bdstevel@tonic-gate	}
1777c478bdstevel@tonic-gate}
1787c478bdstevel@tonic-gate
1797c478bdstevel@tonic-gate
1807c478bdstevel@tonic-gateint
1817c478bdstevel@tonic-gategetsetcontext(int flag, void *arg)
1827c478bdstevel@tonic-gate{
1837c478bdstevel@tonic-gate	ucontext_t uc;
1847c478bdstevel@tonic-gate	ucontext_t *ucp;
1857c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
1867c478bdstevel@tonic-gate	stack_t dummy_stk;
1877c478bdstevel@tonic-gate
1887c478bdstevel@tonic-gate	/*
1897c478bdstevel@tonic-gate	 * In future releases, when the ucontext structure grows,
1907c478bdstevel@tonic-gate	 * getcontext should be modified to only return the fields
1917c478bdstevel@tonic-gate	 * specified in the uc_flags.  That way, the structure can grow
1927c478bdstevel@tonic-gate	 * and still be binary compatible will all .o's which will only
1937c478bdstevel@tonic-gate	 * have old fields defined in uc_flags
1947c478bdstevel@tonic-gate	 */
1957c478bdstevel@tonic-gate
1967c478bdstevel@tonic-gate	switch (flag) {
1977c478bdstevel@tonic-gate	default:
1987c478bdstevel@tonic-gate		return (set_errno(EINVAL));
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate	case GETCONTEXT:
2017be238fRoger A. Faulkner		schedctl_finish_sigblock(curthread);
202bdf0047Roger A. Faulkner		savecontext(&uc, &curthread->t_hold);
2038f798d3Roger A. Faulkner		if (uc.uc_flags & UC_SIGMASK)
2048f798d3Roger A. Faulkner			SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
2057c478bdstevel@tonic-gate		if (copyout(&uc, arg, sizeof (uc)))
2067c478bdstevel@tonic-gate			return (set_errno(EFAULT));
2077c478bdstevel@tonic-gate		return (0);
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gate	case SETCONTEXT:
2107c478bdstevel@tonic-gate		ucp = arg;
2117c478bdstevel@tonic-gate		if (ucp == NULL)
2127c478bdstevel@tonic-gate			exit(CLD_EXITED, 0);
2137c478bdstevel@tonic-gate		/*
2147c478bdstevel@tonic-gate		 * Don't copyin filler or floating state unless we need it.
2157c478bdstevel@tonic-gate		 * The ucontext_t struct and fields are specified in the ABI.
2167c478bdstevel@tonic-gate		 */
2177c478bdstevel@tonic-gate		if (copyin(ucp, &uc, sizeof (ucontext_t) -
2187c478bdstevel@tonic-gate		    sizeof (uc.uc_filler) -
2197c478bdstevel@tonic-gate		    sizeof (uc.uc_mcontext.fpregs))) {
2207c478bdstevel@tonic-gate			return (set_errno(EFAULT));
2217c478bdstevel@tonic-gate		}
2228f798d3Roger A. Faulkner		if (uc.uc_flags & UC_SIGMASK)
2238f798d3Roger A. Faulkner			SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
2247c478bdstevel@tonic-gate
2257c478bdstevel@tonic-gate		if ((uc.uc_flags & UC_FPU) &&
2267c478bdstevel@tonic-gate		    copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
2277c478bdstevel@tonic-gate		    sizeof (uc.uc_mcontext.fpregs))) {
2287c478bdstevel@tonic-gate			return (set_errno(EFAULT));
2297c478bdstevel@tonic-gate		}
2307c478bdstevel@tonic-gate
2317c478bdstevel@tonic-gate		restorecontext(&uc);
2327c478bdstevel@tonic-gate
2337c478bdstevel@tonic-gate		if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
2347c478bdstevel@tonic-gate			(void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack,
2357c478bdstevel@tonic-gate			    sizeof (uc.uc_stack));
2367c478bdstevel@tonic-gate		return (0);
2377c478bdstevel@tonic-gate
2387c478bdstevel@tonic-gate	case GETUSTACK:
2397c478bdstevel@tonic-gate		if (copyout(&lwp->lwp_ustack, arg, sizeof (caddr_t)))
2407c478bdstevel@tonic-gate			return (set_errno(EFAULT));
2417c478bdstevel@tonic-gate		return (0);
2427c478bdstevel@tonic-gate
2437c478bdstevel@tonic-gate	case SETUSTACK:
2447c478bdstevel@tonic-gate		if (copyin(arg, &dummy_stk, sizeof (dummy_stk)))
2457c478bdstevel@tonic-gate			return (set_errno(EFAULT));
2467c478bdstevel@tonic-gate		lwp->lwp_ustack = (uintptr_t)arg;
2477c478bdstevel@tonic-gate		return (0);
2487c478bdstevel@tonic-gate	}
2497c478bdstevel@tonic-gate}
2507c478bdstevel@tonic-gate
2517c478bdstevel@tonic-gate#ifdef _SYSCALL32_IMPL
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate/*
2547c478bdstevel@tonic-gate * Save user context for 32-bit processes.
2557c478bdstevel@tonic-gate */
2567c478bdstevel@tonic-gatevoid
257bdf0047Roger A. Faulknersavecontext32(ucontext32_t *ucp, const k_sigset_t *mask)
2587c478bdstevel@tonic-gate{
2597c478bdstevel@tonic-gate	proc_t *p = ttoproc(curthread);
2607c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
2618efd794sudheer	struct regs *rp = lwptoregs(lwp);
2627c478bdstevel@tonic-gate
2637c478bdstevel@tonic-gate	bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext32_t) -
2647c478bdstevel@tonic-gate	    offsetof(ucontext32_t, uc_mcontext.fpregs));
2657c478bdstevel@tonic-gate
2667c478bdstevel@tonic-gate	ucp->uc_flags = UC_ALL;
2677c478bdstevel@tonic-gate	ucp->uc_link = (caddr32_t)lwp->lwp_oldcontext;
2687c478bdstevel@tonic-gate
2697e12cebToomas Soome	if (lwp->lwp_ustack == (uintptr_t)NULL ||
2707c478bdstevel@tonic-gate	    copyin((void *)lwp->lwp_ustack, &ucp->uc_stack,
2717c478bdstevel@tonic-gate	    sizeof (ucp->uc_stack)) != 0 ||
2727c478bdstevel@tonic-gate	    ucp->uc_stack.ss_size == 0) {
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate		if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) {
2757c478bdstevel@tonic-gate			ucp->uc_stack.ss_sp =
2767c478bdstevel@tonic-gate			    (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
2777c478bdstevel@tonic-gate			ucp->uc_stack.ss_size =
2787c478bdstevel@tonic-gate			    (size32_t)lwp->lwp_sigaltstack.ss_size;
2797c478bdstevel@tonic-gate			ucp->uc_stack.ss_flags = SS_ONSTACK;
2807c478bdstevel@tonic-gate		} else {
2817c478bdstevel@tonic-gate			ucp->uc_stack.ss_sp = (caddr32_t)(uintptr_t)
2827c478bdstevel@tonic-gate			    (p->p_usrstack - p->p_stksize);
2837c478bdstevel@tonic-gate			ucp->uc_stack.ss_size = (size32_t)p->p_stksize;
2847c478bdstevel@tonic-gate			ucp->uc_stack.ss_flags = 0;
2857c478bdstevel@tonic-gate		}
2867c478bdstevel@tonic-gate	}
2877c478bdstevel@tonic-gate
28886d5155ksadhukh	/*
28986d5155ksadhukh	 * If either the trace flag or REQUEST_STEP is set, arrange
29086d5155ksadhukh	 * for single-stepping and turn off the trace flag.
29186d5155ksadhukh	 */
29286d5155ksadhukh	if ((rp->r_ps & PS_T) || (lwp->lwp_pcb.pcb_flags & REQUEST_STEP)) {
29386d5155ksadhukh		/*
29486d5155ksadhukh		 * Clear PS_T so that saved user context won't have trace
29586d5155ksadhukh		 * flag set.
29686d5155ksadhukh		 */
29786d5155ksadhukh		rp->r_ps &= ~PS_T;
29886d5155ksadhukh
29986d5155ksadhukh		if (!(lwp->lwp_pcb.pcb_flags & REQUEST_NOSTEP)) {
30086d5155ksadhukh			lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING;
30186d5155ksadhukh			/*
30286d5155ksadhukh			 * See comments in savecontext().
30386d5155ksadhukh			 */
30486d5155ksadhukh			aston(curthread);
30586d5155ksadhukh		}
30686d5155ksadhukh	}
30786d5155ksadhukh
3087c478bdstevel@tonic-gate	getgregs32(lwp, ucp->uc_mcontext.gregs);
3097c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
3107c478bdstevel@tonic-gate		getfpregs32(lwp, &ucp->uc_mcontext.fpregs);
3117c478bdstevel@tonic-gate	else
3127c478bdstevel@tonic-gate		ucp->uc_flags &= ~UC_FPU;
3137c478bdstevel@tonic-gate
314bdf0047Roger A. Faulkner	sigktou(mask, &ucp->uc_sigmask);
3157c478bdstevel@tonic-gate}
3167c478bdstevel@tonic-gate
3177c478bdstevel@tonic-gateint
3187c478bdstevel@tonic-gategetsetcontext32(int flag, void *arg)
3197c478bdstevel@tonic-gate{
3207c478bdstevel@tonic-gate	ucontext32_t uc;
3217c478bdstevel@tonic-gate	ucontext_t ucnat;
3227c478bdstevel@tonic-gate	ucontext32_t *ucp;
3237c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
3247c478bdstevel@tonic-gate	caddr32_t ustack32;
3257c478bdstevel@tonic-gate	stack32_t dummy_stk32;
3267c478bdstevel@tonic-gate
3277c478bdstevel@tonic-gate	switch (flag) {
3287c478bdstevel@tonic-gate	default:
3297c478bdstevel@tonic-gate		return (set_errno(EINVAL));
3307c478bdstevel@tonic-gate
3317c478bdstevel@tonic-gate	case GETCONTEXT:
3327be238fRoger A. Faulkner		schedctl_finish_sigblock(curthread);
333bdf0047Roger A. Faulkner		savecontext32(&uc, &curthread->t_hold);
3348f798d3Roger A. Faulkner		if (uc.uc_flags & UC_SIGMASK)
3358f798d3Roger A. Faulkner			SIGSET_NATIVE_TO_BRAND(&uc.uc_sigmask);
3367c478bdstevel@tonic-gate		if (copyout(&uc, arg, sizeof (uc)))
3377c478bdstevel@tonic-gate			return (set_errno(EFAULT));
3387c478bdstevel@tonic-gate		return (0);
3397c478bdstevel@tonic-gate
3407c478bdstevel@tonic-gate	case SETCONTEXT:
3417c478bdstevel@tonic-gate		ucp = arg;
3427c478bdstevel@tonic-gate		if (ucp == NULL)
3437c478bdstevel@tonic-gate			exit(CLD_EXITED, 0);
3447c478bdstevel@tonic-gate		if (copyin(ucp, &uc, sizeof (uc) -
3457c478bdstevel@tonic-gate		    sizeof (uc.uc_filler) -
3467c478bdstevel@tonic-gate		    sizeof (uc.uc_mcontext.fpregs))) {
3477c478bdstevel@tonic-gate			return (set_errno(EFAULT));
3487c478bdstevel@tonic-gate		}
3498f798d3Roger A. Faulkner		if (uc.uc_flags & UC_SIGMASK)
3508f798d3Roger A. Faulkner			SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);
3517c478bdstevel@tonic-gate		if ((uc.uc_flags & UC_FPU) &&
3527c478bdstevel@tonic-gate		    copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
3537c478bdstevel@tonic-gate		    sizeof (uc.uc_mcontext.fpregs))) {
3547c478bdstevel@tonic-gate			return (set_errno(EFAULT));
3557c478bdstevel@tonic-gate		}
3567c478bdstevel@tonic-gate
3577c478bdstevel@tonic-gate		ucontext_32ton(&uc, &ucnat);
3587c478bdstevel@tonic-gate		restorecontext(&ucnat);
3597c478bdstevel@tonic-gate
3607c478bdstevel@tonic-gate		if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
3617c478bdstevel@tonic-gate			(void) copyout(&uc.uc_stack,
3627c478bdstevel@tonic-gate			    (stack32_t *)lwp->lwp_ustack, sizeof (uc.uc_stack));
3637c478bdstevel@tonic-gate		return (0);
3647c478bdstevel@tonic-gate
3657c478bdstevel@tonic-gate	case GETUSTACK:
3667c478bdstevel@tonic-gate		ustack32 = (caddr32_t)lwp->lwp_ustack;
3677c478bdstevel@tonic-gate		if (copyout(&ustack32, arg, sizeof (ustack32)))
3687c478bdstevel@tonic-gate			return (set_errno(EFAULT));
3697c478bdstevel@tonic-gate		return (0);
3707c478bdstevel@tonic-gate
3717c478bdstevel@tonic-gate	case SETUSTACK:
3727c478bdstevel@tonic-gate		if (copyin(arg, &dummy_stk32, sizeof (dummy_stk32)))
3737c478bdstevel@tonic-gate			return (set_errno(EFAULT));
3747c478bdstevel@tonic-gate		lwp->lwp_ustack = (uintptr_t)arg;
3757c478bdstevel@tonic-gate		return (0);
3767c478bdstevel@tonic-gate	}
3777c478bdstevel@tonic-gate}
3787c478bdstevel@tonic-gate
3797c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
380