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 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1988 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 #pragma weak _makecontext = makecontext
  31 
  32 #include "lint.h"
  33 #include <stdarg.h>
  34 #include <ucontext.h>
  35 #include <sys/stack.h>
  36 
  37 /*
  38  * The ucontext_t that the user passes in must have been primed with a
  39  * call to getcontext(2), have the uc_stack member set to reflect the
  40  * stack which this context will use, and have the uc_link member set
  41  * to the context which should be resumed when this context returns.
  42  * When makecontext() returns, the ucontext_t will be set to run the
  43  * given function with the given parameters on the stack specified by
  44  * uc_stack, and which will return to the ucontext_t specified by uc_link.
  45  */
  46 
  47 /*
  48  * The original i386 ABI said that the stack pointer need be only 4-byte
  49  * aligned before a function call (STACK_ALIGN == 4).  The ABI supplement
  50  * version 1.0 changed the required alignment to 16-byte for the benefit of
  51  * floating point code compiled using sse2.  The compiler assumes this
  52  * alignment and maintains it for calls it generates.  If the stack is
  53  * initially properly aligned, it will continue to be so aligned.  If it is
  54  * not initially so aligned, it will never become so aligned.
  55  *
 
 
  98 
  99         ucp->uc_mcontext.gregs[UESP] = (greg_t)sp;
 100 
 101         /*
 102          * "push" all the arguments
 103          */
 104         va_start(ap, argc);
 105         while (argc-- > 0)
 106                 *tsp++ = va_arg(ap, long);
 107         va_end(ap);
 108 }
 109 
 110 
 111 static void
 112 resumecontext(void)
 113 {
 114         ucontext_t uc;
 115 
 116         (void) getcontext(&uc);
 117         (void) setcontext(uc.uc_link);
 118 }
 | 
 
 
  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 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1988 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * Copyright 2023 Oxide Computer Company
  32  */
  33 
  34 #pragma weak _makecontext = makecontext
  35 
  36 #include "lint.h"
  37 #include <stdarg.h>
  38 #include <ucontext.h>
  39 #include <sys/stack.h>
  40 #include <sys/auxv.h>
  41 #include <errno.h>
  42 #include "libc.h"
  43 
  44 /*
  45  * The ucontext_t that the user passes in must have been primed with a
  46  * call to getcontext(2), have the uc_stack member set to reflect the
  47  * stack which this context will use, and have the uc_link member set
  48  * to the context which should be resumed when this context returns.
  49  * When makecontext() returns, the ucontext_t will be set to run the
  50  * given function with the given parameters on the stack specified by
  51  * uc_stack, and which will return to the ucontext_t specified by uc_link.
  52  */
  53 
  54 /*
  55  * The original i386 ABI said that the stack pointer need be only 4-byte
  56  * aligned before a function call (STACK_ALIGN == 4).  The ABI supplement
  57  * version 1.0 changed the required alignment to 16-byte for the benefit of
  58  * floating point code compiled using sse2.  The compiler assumes this
  59  * alignment and maintains it for calls it generates.  If the stack is
  60  * initially properly aligned, it will continue to be so aligned.  If it is
  61  * not initially so aligned, it will never become so aligned.
  62  *
 
 
 105 
 106         ucp->uc_mcontext.gregs[UESP] = (greg_t)sp;
 107 
 108         /*
 109          * "push" all the arguments
 110          */
 111         va_start(ap, argc);
 112         while (argc-- > 0)
 113                 *tsp++ = va_arg(ap, long);
 114         va_end(ap);
 115 }
 116 
 117 
 118 static void
 119 resumecontext(void)
 120 {
 121         ucontext_t uc;
 122 
 123         (void) getcontext(&uc);
 124         (void) setcontext(uc.uc_link);
 125 }
 126 
 127 /*
 128  * This is the ISA-specific allocation logic for allocating and setting up an
 129  * extended ucontext_t. In particular, right now we need to allocate and add
 130  * space for the UC_XSAVE member if we have the appropriate hardware support.
 131  * The i386 / amd64 versions could be consolidated in a single x86 impl, but we
 132  * don't have that right now.
 133  */
 134 ucontext_t *
 135 ucontext_alloc(uint32_t flags)
 136 {
 137         boolean_t do_xsave = B_FALSE;
 138         size_t to_alloc = sizeof (ucontext_t);
 139         ucontext_t *ucp;
 140 
 141         if (flags != 0) {
 142                 errno = EINVAL;
 143                 return (NULL);
 144         }
 145 
 146         /*
 147          * This value isn't really 100% accurate. The xsave size is basically
 148          * the worst case that we can have. The XMM / xsave structures aren't
 149          * included in here, but are going to be enough to cover this. We can
 150          * probably try to do a little better and should consider asking the
 151          * kernel for something more accurate. In particular, the problem with
 152          * tis is that it doesn't account for the right size of future-looking
 153          * dynamic things, but then again neither does rtld. We'll deal with
 154          * this when we have support for the xfd MSR and actually use it. For
 155          * more information see uts/intel/os/fpu.c's big theory statement.
 156          */
 157         switch (___getauxval(AT_SUN_FPTYPE)) {
 158         case AT_386_FPINFO_XSAVE:
 159         case AT_386_FPINFO_XSAVE_AMD:
 160                 do_xsave = B_TRUE;
 161                 to_alloc += ___getauxval(AT_SUN_FPSIZE);
 162                 break;
 163         default:
 164                 break;
 165         }
 166 
 167         ucp = calloc(1, to_alloc);
 168         if (ucp == NULL) {
 169                 return (NULL);
 170         }
 171 
 172         if (do_xsave) {
 173                 uintptr_t addr = (uintptr_t)ucp;
 174                 ucp->uc_xsave = addr + sizeof (ucontext_t);
 175         }
 176 
 177         return (ucp);
 178 }
 179 
 180 void
 181 ucontext_free(ucontext_t *ucp)
 182 {
 183         free(ucp);
 184 }
 |