Print this page
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
    usr/src/uts/common/fs/proc/prcontrol.c
    usr/src/uts/intel/os/archdep.c
    usr/src/uts/intel/sys/ucontext.h
    usr/src/uts/intel/syscall/getcontext.c
        
@@ -25,16 +25,23 @@
  */
 
 /*      Copyright (c) 1988 AT&T */
 /*        All Rights Reserved   */
 
+/*
+ * Copyright 2023 Oxide Computer Company
+ */
+
 #pragma weak _makecontext = makecontext
 
 #include "lint.h"
 #include <stdarg.h>
 #include <ucontext.h>
 #include <sys/stack.h>
+#include <sys/auxv.h>
+#include <errno.h>
+#include "libc.h"
 
 /*
  * The ucontext_t that the user passes in must have been primed with a
  * call to getcontext(2), have the uc_stack member set to reflect the
  * stack which this context will use, and have the uc_link member set
@@ -117,6 +124,65 @@
 {
         ucontext_t uc;
 
         (void) getcontext(&uc);
         (void) setcontext(uc.uc_link);
+}
+
+/*
+ * This is the ISA-specific allocation logic for allocating and setting up an
+ * extended ucontext_t. In particular, right now we need to allocate and add
+ * space for the UC_XSAVE member if we have the appropriate hardware support.
+ * The i386 / amd64 versions could be consolidated in a single x86 impl, but we
+ * don't have that right now.
+ */
+ucontext_t *
+ucontext_alloc(uint32_t flags)
+{
+        boolean_t do_xsave = B_FALSE;
+        size_t to_alloc = sizeof (ucontext_t);
+        ucontext_t *ucp;
+
+        if (flags != 0) {
+                errno = EINVAL;
+                return (NULL);
+        }
+
+        /*
+         * This value isn't really 100% accurate. The xsave size is basically
+         * the worst case that we can have. The XMM / xsave structures aren't
+         * included in here, but are going to be enough to cover this. We can
+         * probably try to do a little better and should consider asking the
+         * kernel for something more accurate. In particular, the problem with
+         * this is that it doesn't account for the right size of future-looking
+         * dynamic things, but then again neither does rtld. We'll deal with
+         * this when we have support for the xfd MSR and actually use it. For
+         * more information see uts/intel/os/fpu.c's big theory statement.
+         */
+        switch (___getauxval(AT_SUN_FPTYPE)) {
+        case AT_386_FPINFO_XSAVE:
+        case AT_386_FPINFO_XSAVE_AMD:
+                do_xsave = B_TRUE;
+                to_alloc += ___getauxval(AT_SUN_FPSIZE);
+                break;
+        default:
+                break;
+        }
+
+        ucp = calloc(1, to_alloc);
+        if (ucp == NULL) {
+                return (NULL);
+        }
+
+        if (do_xsave) {
+                uintptr_t addr = (uintptr_t)ucp;
+                ucp->uc_xsave = addr + sizeof (ucontext_t);
+        }
+
+        return (ucp);
+}
+
+void
+ucontext_free(ucontext_t *ucp)
+{
+        free(ucp);
 }