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