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
        
*** 22,35 ****
--- 22,37 ----
   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  /*
   * Copyright (c) 2013 by Delphix. All rights reserved.
+  * Copyright 2023 Oxide Computer Company
   */
  
  #include <stdarg.h>
  #include <string.h>
+ #include <errno.h>
  #include "Pcontrol.h"
  
  /*
   * This file implements the process services declared in <proc_service.h>.
   * This enables libproc to be used in conjunction with libc_db and
*** 165,176 ****
                  return (PS_OK);
  
          return (PS_BADLID);
  }
  
- #if defined(sparc) || defined(__sparc)
- 
  ps_err_e
  ps_lgetxregsize(struct ps_prochandle *P, lwpid_t lwpid, int *xrsize)
  {
          char fname[PATH_MAX];
          struct stat statb;
--- 167,176 ----
*** 180,193 ****
                  lwp_info_t *lwp;
  
                  for (lwp = list_head(&core->core_lwp_head); lwp != NULL;
                      lwp = list_next(&core->core_lwp_head, lwp)) {
                          if (lwp->lwp_id == lwpid) {
!                                 if (lwp->lwp_xregs != NULL)
!                                         *xrsize = sizeof (prxregset_t);
!                                 else
                                          *xrsize = 0;
                                  return (PS_OK);
                          }
                  }
  
                  return (PS_BADLID);
--- 180,199 ----
                  lwp_info_t *lwp;
  
                  for (lwp = list_head(&core->core_lwp_head); lwp != NULL;
                      lwp = list_next(&core->core_lwp_head, lwp)) {
                          if (lwp->lwp_id == lwpid) {
!                                 if (lwp->lwp_xregs != NULL &&
!                                     lwp->lwp_xregsize > 0) {
!                                         if (lwp->lwp_xregsize >= INT_MAX) {
!                                                 return (PS_ERR);
!                                         }
! 
!                                         *xrsize = (int)lwp->lwp_xregsize;
!                                 } else {
                                          *xrsize = 0;
+                                 }
                                  return (PS_OK);
                          }
                  }
  
                  return (PS_BADLID);
*** 197,225 ****
              procfs_path, (int)P->status.pr_pid, (int)lwpid);
  
          if (stat(fname, &statb) != 0)
                  return (PS_BADLID);
  
          *xrsize = (int)statb.st_size;
          return (PS_OK);
  }
  
  ps_err_e
  ps_lgetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
  {
          if (P->state != PS_STOP && P->state != PS_DEAD)
                  return (PS_ERR);
  
!         /* LINTED - alignment */
!         if (Plwp_getxregs(P, lwpid, (prxregset_t *)xregs) == 0)
                  return (PS_OK);
  
          return (PS_BADLID);
  }
  
  ps_err_e
  ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
  {
          if (P->state != PS_STOP)
                  return (PS_ERR);
  
          /* LINTED - alignment */
--- 203,272 ----
              procfs_path, (int)P->status.pr_pid, (int)lwpid);
  
          if (stat(fname, &statb) != 0)
                  return (PS_BADLID);
  
+         if (statb.st_size > INT_MAX)
+                 return (PS_ERR);
+ 
          *xrsize = (int)statb.st_size;
          return (PS_OK);
  }
  
  ps_err_e
  ps_lgetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
  {
+         size_t xregsize;
+         prxregset_t *prx;
+ 
          if (P->state != PS_STOP && P->state != PS_DEAD)
                  return (PS_ERR);
  
!         if (Plwp_getxregs(P, lwpid, &prx, &xregsize) == 0) {
!                 (void) memcpy(xregs, prx, xregsize);
!                 Plwp_freexregs(P, prx, xregsize);
                  return (PS_OK);
+         }
  
+         if (errno == ENODATA)
+                 return (PS_NOXREGS);
+ 
          return (PS_BADLID);
  }
  
  ps_err_e
  ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
+ {
+         size_t xregsize = 0;
+ 
+         if (P->state != PS_STOP)
+                 return (PS_ERR);
+ 
+         /*
+          * libproc asks the caller for the size of the extended register set.
+          * Unfortunately, right now we aren't given the actual size of this
+          * ourselves and we don't want to break the ABI that folks have used
+          * historically. Therefore, we reach in and ask the structure in a
+          * platform-specific way about what this should be. Sorry, this is a bit
+          * unfortunate. This really shouldn't be a platform-specific #ifdef.
+          */
+ #if defined(__i386) || defined(__amd64)
+         prxregset_hdr_t *hdr = (prxregset_hdr_t *)xregs;
+         xregsize = hdr->pr_size;
+ #endif
+         if (xregsize == 0)
+                 return (PS_ERR);
+ 
+         if (Plwp_setxregs(P, lwpid, (prxregset_t *)xregs, xregsize) == 0)
+                 return (PS_OK);
+ 
+         return (PS_BADLID);
+ }
+ 
+ #if defined(sparc) || defined(__sparc)
+ ps_err_e
+ ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
  {
          if (P->state != PS_STOP)
                  return (PS_ERR);
  
          /* LINTED - alignment */