diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2005-04-03 20:21:45 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2005-04-03 20:21:45 +0000 |
commit | aa57b9ae3e444364b080e0152f32c1f4eb686586 (patch) | |
tree | 586d7f07da1c846236a440fe4e8f0279677c8871 /sys | |
parent | 4f93a7acad22f9b4279bc5db1a721e758a10beda (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.c | 82 | ||||
-rw-r--r-- | sys/arch/i386/include/ptrace.h | 11 | ||||
-rw-r--r-- | sys/arch/i386/include/reg.h | 6 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 42 |
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); |