summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2005-04-03 20:21:45 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2005-04-03 20:21:45 +0000
commitaa57b9ae3e444364b080e0152f32c1f4eb686586 (patch)
tree586d7f07da1c846236a440fe4e8f0279677c8871 /sys
parent4f93a7acad22f9b4279bc5db1a721e758a10beda (diff)
Implemente PT_[GS]ETXMMREGS ptrace(2) requests on i386.
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/i386/process_machdep.c82
-rw-r--r--sys/arch/i386/include/ptrace.h11
-rw-r--r--sys/arch/i386/include/reg.h6
-rw-r--r--sys/kern/sys_process.c42
4 files changed, 123 insertions, 18 deletions
diff --git a/sys/arch/i386/i386/process_machdep.c b/sys/arch/i386/i386/process_machdep.c
index 31fac01b813..36d97bd426f 100644
--- a/sys/arch/i386/i386/process_machdep.c
+++ b/sys/arch/i386/i386/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.19 2004/07/20 21:04:37 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.20 2005/04/03 20:21:44 kettenis Exp $ */
/* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */
/*
@@ -81,6 +81,7 @@
static __inline struct trapframe *process_frame(struct proc *);
static __inline union savefpu *process_fpframe(struct proc *);
+void process_fninit_xmm(struct savexmm *);
static __inline struct trapframe *
process_frame(struct proc *p)
@@ -164,6 +165,24 @@ process_s87_to_xmm(const struct save87 *s87, struct savexmm *sxmm)
sxmm->sv_ex_sw = s87->sv_ex_sw;
}
+void
+process_fninit_xmm(struct savexmm *sxmm)
+{
+ /*
+ * The initial control word was already set by setregs(), so
+ * save it temporarily.
+ */
+ uint32_t mxcsr = sxmm->sv_env.en_mxcsr;
+ uint16_t cw = sxmm->sv_env.en_cw;
+
+ /* XXX Don't zero XMM regs? */
+ memset(sxmm, 0, sizeof(*sxmm));
+ sxmm->sv_env.en_cw = cw;
+ sxmm->sv_env.en_mxcsr = mxcsr;
+ sxmm->sv_env.en_sw = 0x0000;
+ sxmm->sv_env.en_tw = 0x00;
+}
+
int
process_read_regs(p, regs)
struct proc *p;
@@ -214,22 +233,14 @@ process_read_fpregs(p, regs)
npxsave_proc(p, 1);
#endif
} else {
- /*
- * Fake a FNINIT.
- * The initial control word was already set by setregs(), so
- * save it temporarily.
- */
+ /* Fake a FNINIT. */
if (i386_use_fxsave) {
- uint32_t mxcsr = frame->sv_xmm.sv_env.en_mxcsr;
- uint16_t cw = frame->sv_xmm.sv_env.en_cw;
-
- /* XXX Don't zero XMM regs? */
- memset(&frame->sv_xmm, 0, sizeof(frame->sv_xmm));
- frame->sv_xmm.sv_env.en_cw = cw;
- frame->sv_xmm.sv_env.en_mxcsr = mxcsr;
- frame->sv_xmm.sv_env.en_sw = 0x0000;
- frame->sv_xmm.sv_env.en_tw = 0x00;
+ process_fninit_xmm(&frame->sv_xmm);
} else {
+ /*
+ * The initial control word was already set by
+ * setregs(), so save it temporarily.
+ */
uint16_t cw = frame->sv_87.sv_env.en_cw;
memset(&frame->sv_87, 0, sizeof(frame->sv_87));
@@ -326,6 +337,47 @@ process_write_fpregs(p, regs)
}
int
+process_read_xmmregs(struct proc *p, struct xmmregs *regs)
+{
+ union savefpu *frame = process_fpframe(p);
+
+ if (!i386_use_fxsave)
+ return (EINVAL);
+
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+#if NNPX > 0
+ npxsave_proc(p, 1);
+#endif
+ } else {
+ /* Fake a FNINIT. */
+ process_fninit_xmm(&frame->sv_xmm);
+ p->p_md.md_flags |= MDP_USEDFPU;
+ }
+
+ memcpy(regs, &frame->sv_xmm, sizeof(*regs));
+ return (0);
+}
+
+int
+process_write_xmmregs(struct proc *p, const struct xmmregs *regs)
+{
+ union savefpu *frame = process_fpframe(p);
+
+ if (!i386_use_fxsave)
+ return (EINVAL);
+
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+#if NNPX > 0
+ npxsave_proc(p, 0);
+#endif
+ } else
+ p->p_md.md_flags |= MDP_USEDFPU;
+
+ memcpy(&frame->sv_xmm, regs, sizeof(*regs));
+ return (0);
+}
+
+int
process_sstep(p, sstep)
struct proc *p;
int sstep;
diff --git a/sys/arch/i386/include/ptrace.h b/sys/arch/i386/include/ptrace.h
index e1a6affc732..ff34a920992 100644
--- a/sys/arch/i386/include/ptrace.h
+++ b/sys/arch/i386/include/ptrace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ptrace.h,v 1.2 2000/08/05 22:07:32 niklas Exp $ */
+/* $OpenBSD: ptrace.h,v 1.3 2005/04/03 20:21:44 kettenis Exp $ */
/* $NetBSD: ptrace.h,v 1.6 1995/08/06 05:33:23 mycroft Exp $ */
/*
@@ -39,3 +39,12 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
+#define PT_GETXMMREGS (PT_FIRSTMACH + 5)
+#define PT_SETXMMREGS (PT_FIRSTMACH + 6)
+
+#ifdef _KERNEL
+struct xmmregs;
+
+int process_read_xmmregs(struct proc *, struct xmmregs *);
+int process_write_xmmregs(struct proc *, const struct xmmregs *);
+#endif
diff --git a/sys/arch/i386/include/reg.h b/sys/arch/i386/include/reg.h
index cafcc14b87c..2b92eb0d520 100644
--- a/sys/arch/i386/include/reg.h
+++ b/sys/arch/i386/include/reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: reg.h,v 1.5 2005/02/17 18:07:35 jfb Exp $ */
+/* $OpenBSD: reg.h,v 1.6 2005/04/03 20:21:44 kettenis Exp $ */
/* $NetBSD: reg.h,v 1.14 1995/10/11 04:20:24 mycroft Exp $ */
/*-
@@ -96,4 +96,8 @@ struct fpreg {
char __data[116];
};
+struct xmmregs {
+ char __data[512];
+};
+
#endif /* !_I386_REG_H_ */
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 21180cda141..1498a10c954 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_process.c,v 1.28 2004/06/13 21:49:26 niklas Exp $ */
+/* $OpenBSD: sys_process.c,v 1.29 2005/04/03 20:21:44 kettenis Exp $ */
/* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */
/*-
@@ -87,6 +87,9 @@ sys_ptrace(p, v, retval)
struct uio uio;
struct iovec iov;
struct ptrace_io_desc piod;
+#if defined (PT_SETXMMREGS) || defined (PT_GETXMMREGS)
+ struct xmmregs xmmregs;
+#endif
#ifdef PT_WCOOKIE
register_t wcookie;
#endif
@@ -179,6 +182,12 @@ sys_ptrace(p, v, retval)
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
+#ifdef PT_GETXMMREGS
+ case PT_GETXMMREGS:
+#endif
+#ifdef PT_SETXMMREGS
+ case PT_SETXMMREGS:
+#endif
#ifdef PT_WCOOKIE
case PT_WCOOKIE:
#endif
@@ -432,6 +441,37 @@ sys_ptrace(p, v, retval)
return (procfs_dofpregs(p, t, NULL, &uio));
}
#endif
+#ifdef PT_SETXMMREGS
+ case PT_SETXMMREGS:
+ if (!procfs_validfpregs(t, NULL))
+ return (EINVAL);
+
+ if ((error = procfs_checkioperm(p, t)) != 0)
+ return (error);
+
+ error = copyin(SCARG(uap, addr), &xmmregs, sizeof(xmmregs));
+ if (error)
+ return (error);
+ PHOLD(p);
+ error = process_write_xmmregs(t, &xmmregs);
+ PRELE(p);
+ return (error);
+#endif
+#ifdef PT_GETXMMREGS
+ case PT_GETXMMREGS:
+ if (!procfs_validfpregs(t, NULL))
+ return (EINVAL);
+
+ if ((error = procfs_checkioperm(p, t)) != 0)
+ return (error);
+
+ PHOLD(p);
+ error = process_read_xmmregs(t, &xmmregs);
+ PRELE(p);
+ if (error)
+ return (error);
+ return (copyout(&xmmregs, SCARG(uap, addr), sizeof (xmmregs)));
+#endif
#ifdef PT_WCOOKIE
case PT_WCOOKIE:
wcookie = process_get_wcookie (t);