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
        
*** 24,37 ****
   * Use is subject to license terms.
   */
  /*
   * Copyright (c) 2018, Joyent, Inc.
   * Copyright 2019 Doma Gergő Mihály <doma.gergo.mihaly@gmail.com>
   */
  
  /*
!  * User Process Target Intel 32-bit component
   *
   * This file provides the ISA-dependent portion of the user process target.
   * For more details on the implementation refer to mdb_proc.c.
   */
  
--- 24,38 ----
   * Use is subject to license terms.
   */
  /*
   * Copyright (c) 2018, Joyent, Inc.
   * Copyright 2019 Doma Gergő Mihály <doma.gergo.mihaly@gmail.com>
+  * Copyright 2023 Oxide Computer Company
   */
  
  /*
!  * User Process Target Intel 64-bit component
   *
   * This file provides the ISA-dependent portion of the user process target.
   * For more details on the implementation refer to mdb_proc.c.
   */
  
*** 38,54 ****
--- 39,57 ----
  #include <mdb/mdb_proc.h>
  #include <mdb/mdb_kreg.h>
  #include <mdb/mdb_err.h>
  #include <mdb/mdb_isautil.h>
  #include <mdb/mdb_amd64util.h>
+ #include <mdb/proc_x86util.h>
  #include <mdb/mdb.h>
  
  #include <sys/ucontext.h>
  #include <sys/frame.h>
  #include <libproc.h>
  #include <sys/fp.h>
  #include <ieeefp.h>
+ #include <sys/sysmacros.h>
  
  #include <stddef.h>
  
  const mdb_tgt_regdesc_t pt_regdesc[] = {
          { "r15",        REG_R15,        MDB_TGT_R_EXPORT },
*** 277,522 ****
          mdb_printf("   %%err = 0x%x\n", grs[REG_ERR]);
  
          return (set_errno(ENOTSUP));
  }
  
- static const char *
- fpcw2str(uint32_t cw, char *buf, size_t nbytes)
- {
-         char *end = buf + nbytes;
-         char *p = buf;
- 
-         buf[0] = '\0';
- 
-         /*
-          * Decode all exception masks in the x87 FPU Control Word.
-          *
-          * See here:
-          * Intel® 64 and IA-32 Architectures Software Developer’s Manual,
-          * Volume 1: Basic Architecture, 8.1.5 x87 FPU Control Word
-          */
-         if (cw & FPIM)  /* Invalid operation mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|IM");
-         if (cw & FPDM)  /* Denormalized operand mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|DM");
-         if (cw & FPZM)  /* Zero divide mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
-         if (cw & FPOM)  /* Overflow mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|OM");
-         if (cw & FPUM)  /* Underflow mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|UM");
-         if (cw & FPPM)  /* Precision mask. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|PM");
- 
-         /*
-          * Decode precision control options.
-          */
-         switch (cw & FPPC) {
-         case FPSIG24:
-                 /* 24-bit significand, single precision. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|SIG24");
-                 break;
-         case FPSIG53:
-                 /* 53-bit significand, double precision. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|SIG53");
-                 break;
-         case FPSIG64:
-                 /* 64-bit significand, double extended precision. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|SIG64");
-                 break;
-         default:
-                 /*
-                  * Should never happen.
-                  * Value 0x00000100 is 'Reserved'.
-                  */
-                 break;
-         }
- 
-         /*
-          * Decode rounding control options.
-          */
-         switch (cw & FPRC) {
-         case FPRTN:
-                 /* Round to nearest, or to even if equidistant. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
-                 break;
-         case FPRD:
-                 /* Round down. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RD");
-                 break;
-         case FPRU:
-                 /* Round up. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RU");
-                 break;
-         case FPCHOP:
-                 /* Truncate. */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
-                 break;
-         default:
-                 /*
-                  * This is a two-bit field.
-                  * No other options left.
-                  */
-                 break;
-         }
- 
-         /*
-          * Decode infinity control options.
-          *
-          * This field has been retained for compatibility with
-          * the 287 and earlier co-processors.
-          * In the more modern FPUs, this bit is disregarded and
-          * both -infinity and +infinity are respected.
-          * Comment source: SIMPLY FPU by Raymond Filiatreault
-          */
-         switch (cw & FPIC) {
-         case FPP:
-                 /*
-                  * Projective infinity.
-                  * Both -infinity and +infinity are treated as
-                  * unsigned infinity.
-                  */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|P");
-                 break;
-         case FPA:
-                 /*
-                  * Affine infinity.
-                  * Respects both -infinity and +infinity.
-                  */
-                 p += mdb_snprintf(p, (size_t)(end - p), "|A");
-                 break;
-         default:
-                 /*
-                  * This is a one-bit field.
-                  * No other options left.
-                  */
-                 break;
-         }
- 
-         if (cw & WFPB17)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|WFPB17");
-         if (cw & WFPB24)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|WFPB24");
- 
-         if (buf[0] == '|')
-                 return (buf + 1);
- 
-         return ("0");
- }
- 
- static const char *
- fpsw2str(uint32_t cw, char *buf, size_t nbytes)
- {
-         char *end = buf + nbytes;
-         char *p = buf;
- 
-         buf[0] = '\0';
- 
-         /*
-          * Decode all masks in the 80387 status word.
-          */
-         if (cw & FPS_IE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|IE");
-         if (cw & FPS_DE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|DE");
-         if (cw & FPS_ZE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
-         if (cw & FPS_OE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|OE");
-         if (cw & FPS_UE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|UE");
-         if (cw & FPS_PE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|PE");
-         if (cw & FPS_SF)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|SF");
-         if (cw & FPS_ES)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|ES");
-         if (cw & FPS_C0)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|C0");
-         if (cw & FPS_C1)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|C1");
-         if (cw & FPS_C2)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|C2");
-         if (cw & FPS_C3)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|C3");
-         if (cw & FPS_B)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|B");
- 
-         if (buf[0] == '|')
-                 return (buf + 1);
- 
-         return ("0");
- }
- 
- static const char *
- fpmxcsr2str(uint32_t mxcsr, char *buf, size_t nbytes)
- {
-         char *end = buf + nbytes;
-         char *p = buf;
- 
-         buf[0] = '\0';
- 
-         /*
-          * Decode the MXCSR word
-          */
-         if (mxcsr & SSE_IE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|IE");
-         if (mxcsr & SSE_DE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|DE");
-         if (mxcsr & SSE_ZE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
-         if (mxcsr & SSE_OE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|OE");
-         if (mxcsr & SSE_UE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|UE");
-         if (mxcsr & SSE_PE)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|PE");
- 
-         if (mxcsr & SSE_DAZ)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|DAZ");
- 
-         if (mxcsr & SSE_IM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|IM");
-         if (mxcsr & SSE_DM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|DM");
-         if (mxcsr & SSE_ZM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
-         if (mxcsr & SSE_OM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|OM");
-         if (mxcsr & SSE_UM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|UM");
-         if (mxcsr & SSE_PM)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|PM");
- 
-         if ((mxcsr & SSE_RC) == (SSE_RD|SSE_RU))
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
-         else if (mxcsr & SSE_RD)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RD");
-         else if (mxcsr & SSE_RU)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RU");
-         else
-                 p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
- 
-         if (mxcsr & SSE_FZ)
-                 p += mdb_snprintf(p, (size_t)(end - p), "|FZ");
- 
-         if (buf[0] == '|')
-                 return (buf + 1);
-         return ("0");
- }
- 
- /*ARGSUSED*/
  int
  pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
  {
!         mdb_tgt_t *t = mdb.m_target;
!         mdb_tgt_tid_t tid;
          prfpregset_t fprs;
          struct _fpchip_state fps;
          char buf[256];
          uint_t top;
!         int i;
  
          /*
           * Union for overlaying _fpreg structure on to quad-precision
           * floating-point value (long double).
           */
--- 280,298 ----
          mdb_printf("   %%err = 0x%x\n", grs[REG_ERR]);
  
          return (set_errno(ENOTSUP));
  }
  
  int
  pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
  {
!         int ret;
          prfpregset_t fprs;
          struct _fpchip_state fps;
          char buf[256];
          uint_t top;
!         size_t i;
  
          /*
           * Union for overlaying _fpreg structure on to quad-precision
           * floating-point value (long double).
           */
*** 524,564 ****
                  struct _fpreg reg;
                  long double ld;
          } fpru;
  
          /*
!          * Array of strings corresponding to FPU tag word values (see
!          * section 7.3.6 of the Intel Programmer's Reference Manual).
           */
!         const char *tag_strings[] = { "valid", "zero", "special", "empty" };
  
-         if (argc != 0)
-                 return (DCMD_USAGE);
- 
-         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
-                 mdb_warn("no process active\n");
-                 return (DCMD_ERR);
-         }
- 
-         if (Pstate(t->t_pshandle) == PS_LOST) {
-                 mdb_warn("debugger has lost control of process\n");
-                 return (DCMD_ERR);
-         }
- 
-         if (flags & DCMD_ADDRSPEC)
-                 tid = (mdb_tgt_tid_t)addr;
-         else
-                 tid = PTL_TID(t);
- 
-         mdb_printf("AMD64 (80486 chip with SSE)\n");
- 
-         if (PTL_GETFPREGS(t, tid, &fprs) != 0) {
-                 mdb_warn("failed to get floating point registers");
-                 return (DCMD_ERR);
-         }
- 
          bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps));
  
          fps.status &= 0xffff;   /* saved status word is really 16 bits */
  
          mdb_printf("cw     0x%04x (%s)\n", fps.cw,
              fpcw2str(fps.cw, buf, sizeof (buf)));
--- 300,319 ----
                  struct _fpreg reg;
                  long double ld;
          } fpru;
  
          /*
!          * We use common code between 32-bit and 64-bit x86 to capture and print
!          * the extended vector state. The remaining classic 387 state is
!          * finicky and different enough that it is left to be dealt with on its
!          * own.
           */
!         if ((ret = x86_pt_fpregs_common(addr, flags, argc, &fprs)) != DCMD_OK)
!                 return (ret);
  
          bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps));
+         mdb_printf("387 and FP Control State\n");
  
          fps.status &= 0xffff;   /* saved status word is really 16 bits */
  
          mdb_printf("cw     0x%04x (%s)\n", fps.cw,
              fpcw2str(fps.cw, buf, sizeof (buf)));
*** 572,582 ****
  
          mdb_printf("fop    0x%x\n", fps.fop);
          mdb_printf("rip    0x%x\n", fps.rip);
          mdb_printf("rdp    0x%x\n\n", fps.rdp);
  
!         for (i = 0; i < 8; i++) {
                  /*
                   * Recall that we need to use the current TOP-of-stack value to
                   * associate the _st[] index back to a physical register number,
                   * since tag word indices are physical register numbers.  Then
                   * to get the tag value, we shift over two bits for each tag
--- 327,337 ----
  
          mdb_printf("fop    0x%x\n", fps.fop);
          mdb_printf("rip    0x%x\n", fps.rip);
          mdb_printf("rdp    0x%x\n\n", fps.rdp);
  
!         for (i = 0; i < ARRAY_SIZE(fps.st); i++) {
                  /*
                   * Recall that we need to use the current TOP-of-stack value to
                   * associate the _st[] index back to a physical register number,
                   * since tag word indices are physical register numbers.  Then
                   * to get the tag value, we shift over two bits for each tag
*** 617,639 ****
  
                  mdb_printf("%%st%d   0x%04x.%04x%04x%04x%04x = %lg %s\n",
                      i, fpru.reg.exponent,
                      fpru.reg.significand[3], fpru.reg.significand[2],
                      fpru.reg.significand[1], fpru.reg.significand[0],
!                     fpru.ld, tag_strings[tag_value]);
          }
  
!         mdb_printf("\nmxcsr  0x%04x (%s)\n", fps.mxcsr,
!             fpmxcsr2str(fps.mxcsr, buf, sizeof (buf)));
!         mdb_printf("xcp    0x%04x (%s)\n\n", fps.xstatus,
!             fpmxcsr2str(fps.xstatus, buf, sizeof (buf)));
  
-         for (i = 0; i < 8; i++)
-                 mdb_printf("%%xmm%d  0x%08x%08x%08x%08x\n", i,
-                     fps.xmm[i]._l[3], fps.xmm[i]._l[2],
-                     fps.xmm[i]._l[1], fps.xmm[i]._l[0]);
- 
          return (DCMD_OK);
  }
  
  /*ARGSUSED*/
  int
--- 372,386 ----
  
                  mdb_printf("%%st%d   0x%04x.%04x%04x%04x%04x = %lg %s\n",
                      i, fpru.reg.exponent,
                      fpru.reg.significand[3], fpru.reg.significand[2],
                      fpru.reg.significand[1], fpru.reg.significand[0],
!                     fpru.ld, fptag2str(tag_value));
          }
  
!         x86_pt_fpregs_sse_ctl(fps.mxcsr, fps.xstatus, buf, sizeof (buf));
  
          return (DCMD_OK);
  }
  
  /*ARGSUSED*/
  int