Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Implement PT_GETXSTATE and PT_SETXSTATE
details: https://anonhg.NetBSD.org/src/rev/bcb7c11a2814
branches: trunk
changeset: 461628:bcb7c11a2814
user: mgorny <mgorny%NetBSD.org@localhost>
date: Wed Jun 26 12:30:12 2019 +0000
description:
Implement PT_GETXSTATE and PT_SETXSTATE
Introduce two new ptrace() requests: PT_GETXSTATE and PT_SETXSTATE,
that provide access to the extended (and extensible) set of FPU
registers on amd64 and i386. At the moment, this covers AVX (YMM)
and AVX-512 (ZMM, opmask) registers. It can be easily extended
to cover further register types without breaking backwards
compatibility.
PT_GETXSTATE issues the XSAVE instruction with all kernel-supported
extended components enabled. The data is copied into 'struct xstate'
(which -- unlike the XSAVE area itself -- has stable format
and offsets).
PT_SETXSTATE issues the XRSTOR instruction to restore the register
values from user-provided 'struct xstate'. The function replaces only
the specific XSAVE components that are listed in 'xs_rfbm' field,
making it possible to issue partial updates.
Both syscalls take a 'struct iovec' pointer rather than a direct
argument. This requires the caller to explicitly specify the buffer
size. As a result, existing code will continue to work correctly
when the structure is extended (performing partial reads/updates).
diffstat:
lib/libc/sys/ptrace.2 | 78 ++-
sys/arch/amd64/amd64/netbsd32_machdep.c | 6 +-
sys/arch/amd64/amd64/process_machdep.c | 135 ++++-
sys/arch/amd64/include/netbsd32_machdep.h | 4 +-
sys/arch/amd64/include/ptrace.h | 25 +-
sys/arch/i386/i386/process_machdep.c | 129 +++-
sys/arch/i386/include/ptrace.h | 15 +-
sys/arch/x86/include/cpu_extended_state.h | 84 ++-
sys/arch/x86/include/fpu.h | 6 +-
sys/arch/x86/x86/fpu.c | 163 +++++-
tests/lib/libc/sys/t_ptrace_wait.c | 6 +-
tests/lib/libc/sys/t_ptrace_x86_wait.h | 894 +++++++++++++++++++++++++++++-
12 files changed, 1502 insertions(+), 43 deletions(-)
diffs (truncated from 1860 to 300 lines):
diff -r 03c0ac62a5ae -r bcb7c11a2814 lib/libc/sys/ptrace.2
--- a/lib/libc/sys/ptrace.2 Wed Jun 26 12:29:00 2019 +0000
+++ b/lib/libc/sys/ptrace.2 Wed Jun 26 12:30:12 2019 +0000
@@ -1,7 +1,7 @@
-.\" $NetBSD: ptrace.2,v 1.74 2019/06/12 12:33:42 wiz Exp $
+.\" $NetBSD: ptrace.2,v 1.75 2019/06/26 12:30:12 mgorny Exp $
.\"
.\" This file is in the public domain.
-.Dd June 12, 2019
+.Dd June 26, 2019
.Dt PTRACE 2
.Os
.Sh NAME
@@ -771,6 +771,69 @@
argument contains the LWP ID of the thread whose registers are to
be written.
If zero is supplied, the first thread of the process is written.
+.It Dv PT_GETXSTATE
+This request reads the traced process' FPU extended state into
+the
+.Dq Li "struct xstate"
+(defined in
+.In machine/cpu_extended_state.h ) .
+.Fa addr
+should be a pointer to
+.Dq Li "struct iovec"
+(defined in
+.In sys/uio.h )
+specifying the pointer to the aforementioned struct as
+.Fa iov_base
+and its size as
+.Fa iov_len .
+The
+.Fa data
+argument contains the LWP ID of the thread whose registers are to
+be read.
+If zero is supplied, the first thread of the process is read.
+The struct will be filled up to the specified
+.Fa iov_len .
+The caller needs to check
+.Fa xs_rfbm
+bitmap in order to determine which fields were provided by the CPU,
+and may check
+.Fa xs_xstate_bv
+to determine which component states were changed from the initial state.
+.It Dv PT_SETXSTATE
+This request is the converse of
+.Dv PT_GETXSTATE ;
+it loads the traced process' extended FPU state from the
+.Dq Li "struct xstate"
+(defined in
+.In machine/cpu_extended_state.h ) .
+.Fa addr
+should be a pointer to
+.Dq Li "struct iovec"
+(defined in
+.In sys/uio.h )
+specifying the pointer to the aforementioned struct as
+.Fa iov_base
+and its size as
+.Fa iov_len .
+The
+.Fa data
+argument contains the LWP ID of the thread whose registers are to
+be written.
+If zero is supplied, the first thread of the process is written.
+The
+.Fa xs_rfbm
+field of the supplied xstate specifies which state components are to
+be updated. Other components (fields) will be ignored. The
+.Fa xs_xstate_bv
+specifies whether component state should be set to provided values
+(when 1) or reset to unitialized (when 0). The request
+will fail if
+.Fa xs_xstate_bv
+is not a subset of
+.Fa xs_rfbm ,
+or any of the specified components is not supported by the CPU or kernel
+(i.e. not returned by
+.Dv PT_GETXSTATE .
.El
.Sh ERRORS
Some requests can cause
@@ -819,8 +882,10 @@
.Dv PT_GETREGS ,
.Dv PT_SETREGS ,
.Dv PT_GETFPREGS ,
+.Dv PT_SETFPREGS ,
+.Dv PT_GETXSTATE ,
or
-.Dv PT_SETFPREGS
+.Dv PT_SETXSTATE
was attempted on a process with no valid register set.
(This is normally true only of system processes.)
.It
@@ -832,6 +897,13 @@
with
.Dv vm.user_va0_disable
set to 1.
+.It
+.Dv PT_SETXSTATE
+attempted to set state components not supported by the kernel,
+or
+.Dv xs_xstate_bv
+was not a subset of
+.Dv xs_rfbm .
.El
.It Bq Er EPERM
.Bl -bullet -compact
diff -r 03c0ac62a5ae -r bcb7c11a2814 sys/arch/amd64/amd64/netbsd32_machdep.c
--- a/sys/arch/amd64/amd64/netbsd32_machdep.c Wed Jun 26 12:29:00 2019 +0000
+++ b/sys/arch/amd64/amd64/netbsd32_machdep.c Wed Jun 26 12:30:12 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_machdep.c,v 1.123 2019/06/04 16:30:19 mgorny Exp $ */
+/* $NetBSD: netbsd32_machdep.c,v 1.124 2019/06/26 12:30:12 mgorny Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.123 2019/06/04 16:30:19 mgorny Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.124 2019/06/26 12:30:12 mgorny Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -353,6 +353,8 @@
case PT32_SETDBREGS: return PT_SETDBREGS;
case PT32_SETSTEP: return PT_SETSTEP;
case PT32_CLEARSTEP: return PT_CLEARSTEP;
+ case PT32_GETXSTATE: return PT_GETXSTATE;
+ case PT32_SETXSTATE: return PT_SETXSTATE;
default: return -1;
}
}
diff -r 03c0ac62a5ae -r bcb7c11a2814 sys/arch/amd64/amd64/process_machdep.c
--- a/sys/arch/amd64/amd64/process_machdep.c Wed Jun 26 12:29:00 2019 +0000
+++ b/sys/arch/amd64/amd64/process_machdep.c Wed Jun 26 12:30:12 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: process_machdep.c,v 1.39 2019/02/11 14:59:32 cherry Exp $ */
+/* $NetBSD: process_machdep.c,v 1.40 2019/06/26 12:30:12 mgorny Exp $ */
/*
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.39 2019/02/11 14:59:32 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.40 2019/06/26 12:30:12 mgorny Exp $");
#include "opt_xen.h"
#include <sys/param.h>
@@ -84,6 +84,9 @@
#include <sys/proc.h>
#include <sys/ptrace.h>
+#include <uvm/uvm_extern.h>
+
+#include <compat/netbsd32/netbsd32.h>
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/segments.h>
@@ -288,3 +291,131 @@
return 0;
}
+
+#ifdef __HAVE_PTRACE_MACHDEP
+static int
+process_machdep_read_xstate(struct lwp *l, struct xstate *regs)
+{
+ return process_read_xstate(l, regs);
+}
+
+static int
+process_machdep_write_xstate(struct lwp *l, const struct xstate *regs)
+{
+ int error;
+
+ /*
+ * Check for security violations.
+ */
+ error = process_verify_xstate(regs);
+ if (error != 0)
+ return error;
+
+ return process_write_xstate(l, regs);
+}
+
+int
+ptrace_machdep_dorequest(
+ struct lwp *l,
+ struct lwp *lt,
+ int req,
+ void *addr,
+ int data
+)
+{
+ struct uio uio;
+ struct iovec iov;
+ struct vmspace *vm;
+ int error;
+ int write = 0;
+
+ switch (req) {
+ case PT_SETXSTATE:
+ write = 1;
+
+ /* FALLTHROUGH */
+ case PT_GETXSTATE:
+ /* write = 0 done above. */
+ if (!process_machdep_validxstate(lt->l_proc))
+ return EINVAL;
+ if (__predict_false(l->l_proc->p_flag & PK_32)) {
+ struct netbsd32_iovec *user_iov;
+ user_iov = (struct netbsd32_iovec*)addr;
+ iov.iov_base = NETBSD32PTR64(user_iov->iov_base);
+ iov.iov_len = user_iov->iov_len;
+ } else {
+ struct iovec *user_iov;
+ user_iov = (struct iovec*)addr;
+ iov.iov_base = user_iov->iov_base;
+ iov.iov_len = user_iov->iov_len;
+ }
+
+ error = proc_vmspace_getref(l->l_proc, &vm);
+ if (error)
+ return error;
+ if (iov.iov_len > sizeof(struct xstate))
+ iov.iov_len = sizeof(struct xstate);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = iov.iov_len;
+ uio.uio_rw = write ? UIO_WRITE : UIO_READ;
+ uio.uio_vmspace = vm;
+ error = process_machdep_doxstate(l, lt, &uio);
+ uvmspace_free(vm);
+ return error;
+ }
+
+#ifdef DIAGNOSTIC
+ panic("ptrace_machdep: impossible");
+#endif
+
+ return 0;
+}
+
+/*
+ * The following functions are used by both ptrace(2) and procfs.
+ */
+
+int
+process_machdep_doxstate(struct lwp *curl, struct lwp *l, struct uio *uio)
+ /* curl: tracer */
+ /* l: traced */
+{
+ int error;
+ struct xstate r;
+ char *kv;
+ ssize_t kl;
+
+ memset(&r, 0, sizeof(r));
+ kl = MIN(uio->uio_iov->iov_len, sizeof(r));
+ kv = (char *) &r;
+
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if (kl > uio->uio_resid)
+ kl = uio->uio_resid;
+
+ if (kl < 0)
+ error = EINVAL;
+ else
+ error = process_machdep_read_xstate(l, &r);
+ if (error == 0)
+ error = uiomove(kv, kl, uio);
+ if (error == 0 && uio->uio_rw == UIO_WRITE)
+ error = process_machdep_write_xstate(l, &r);
+
+ uio->uio_offset = 0;
+ return error;
+}
+
+int
+process_machdep_validxstate(struct proc *p)
+{
+
+ if (p->p_flag & PK_SYSTEM)
+ return 0;
+
+ return 1;
+}
+#endif /* __HAVE_PTRACE_MACHDEP */
diff -r 03c0ac62a5ae -r bcb7c11a2814 sys/arch/amd64/include/netbsd32_machdep.h
--- a/sys/arch/amd64/include/netbsd32_machdep.h Wed Jun 26 12:29:00 2019 +0000
+++ b/sys/arch/amd64/include/netbsd32_machdep.h Wed Jun 26 12:30:12 2019 +0000
@@ -1,4 +1,4 @@
Home |
Main Index |
Thread Index |
Old Index