Print this page
OS-3561 lxbrand emulation library should execute on alternate stack
OS-3558 lxbrand add support for full in-kernel syscall handling
OS-3545 lx_syscall_regs should not walk stack
OS-3868 many LTP testcases now hang
OS-3901 lxbrand lx_recvmsg fails to translate control messages when 64-bit
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>


   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);