Module Name: src Committed By: rin Date: Wed Nov 27 09:16:59 UTC 2019
Modified Files: src/sys/arch/amd64/amd64: netbsd32_machdep.c process_machdep.c src/sys/arch/amd64/include: netbsd32_machdep.h ptrace.h Log Message: Add support for PT_[GS]ETXMMREGS requests for COMPAT_NETBSD32 on amd64. For this purpose, PT_[GS]ETXMMREGS are added to amd64/ptrace.h. These are intended for internal usage for COMPAT_NETBSD32, and therefore not exposed to userland. Thanks to kamil, mgorny, and pgoyette for their kind review! XXX pullup to netbsd-9 To generate a diff of this commit: cvs rdiff -u -r1.131 -r1.132 src/sys/arch/amd64/amd64/netbsd32_machdep.c cvs rdiff -u -r1.46 -r1.47 src/sys/arch/amd64/amd64/process_machdep.c cvs rdiff -u -r1.24 -r1.25 src/sys/arch/amd64/include/netbsd32_machdep.h cvs rdiff -u -r1.18 -r1.19 src/sys/arch/amd64/include/ptrace.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/netbsd32_machdep.c diff -u src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.131 src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.132 --- src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.131 Wed Nov 20 19:37:51 2019 +++ src/sys/arch/amd64/amd64/netbsd32_machdep.c Wed Nov 27 09:16:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_machdep.c,v 1.131 2019/11/20 19:37:51 pgoyette Exp $ */ +/* $NetBSD: netbsd32_machdep.c,v 1.132 2019/11/27 09:16:58 rin Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.131 2019/11/20 19:37:51 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.132 2019/11/27 09:16:58 rin Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -86,6 +86,9 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_mac const char machine32[] = "i386"; const char machine_arch32[] = "i386"; +static int netbsd32_process_doxmmregs(struct lwp *, struct lwp *, void *, bool); +static int netbsd32_process_xmmregio(struct lwp *, struct lwp *, struct uio *); + #ifdef USER_LDT static int x86_64_get_ldt32(struct lwp *, void *, register_t *); static int x86_64_set_ldt32(struct lwp *, void *, register_t *); @@ -344,8 +347,8 @@ netbsd32_ptrace_translate_request(int re case PT32_SETREGS: return PT_SETREGS; case PT32_GETFPREGS: return PT_GETFPREGS; case PT32_SETFPREGS: return PT_SETFPREGS; - case PT32_GETXMMREGS: return -1; - case PT32_SETXMMREGS: return -1; + case PT32_GETXMMREGS: return PT_GETXMMREGS; + case PT32_SETXMMREGS: return PT_SETXMMREGS; case PT32_GETDBREGS: return PT_GETDBREGS; case PT32_SETDBREGS: return PT_SETDBREGS; case PT32_SETSTEP: return PT_SETSTEP; @@ -500,6 +503,77 @@ netbsd32_process_write_dbregs(struct lwp return 0; } +static int +netbsd32_process_doxmmregs(struct lwp *curl, struct lwp *l, void *addr, + bool write) + /* curl: tracer */ + /* l: traced */ +{ + struct uio uio; + struct iovec iov; + struct vmspace *vm; + int error; + + if ((curl->l_proc->p_flag & PK_32) == 0 || + (l->l_proc->p_flag & PK_32) == 0) + return EINVAL; + + if (!process_machdep_validfpu(l->l_proc)) + return EINVAL; + + error = proc_vmspace_getref(curl->l_proc, &vm); + if (error) + return error; + + iov.iov_base = addr; + iov.iov_len = sizeof(struct xmmregs32); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = sizeof(struct xmmregs32); + uio.uio_rw = write ? UIO_WRITE : UIO_READ; + uio.uio_vmspace = vm; + + error = netbsd32_process_xmmregio(curl, l, &uio); + uvmspace_free(vm); + return error; +} + +static int +netbsd32_process_xmmregio(struct lwp *curl, struct lwp *l, struct uio *uio) + /* curl: tracer */ + /* l: traced */ +{ + struct xmmregs32 regs; + int error; + char *kv; + size_t kl; + + kl = sizeof(regs); + kv = (char *)®s; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)kl) + return EINVAL; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + + if (kl > uio->uio_resid) + kl = uio->uio_resid; + + process_read_fpregs_xmm(l, ®s.fxstate); + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_proc->p_stat != SSTOP) + error = EBUSY; + else + process_write_fpregs_xmm(l, ®s.fxstate); + } + + uio->uio_offset = 0; + return error; +} + int netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) { @@ -959,6 +1033,8 @@ netbsd32_machdep_md_init(void) MODULE_HOOK_SET(netbsd32_machine32_hook, "mach32", netbsd32_machine32); MODULE_HOOK_SET(netbsd32_reg_validate_hook, "mcontext32from64_validate", cpu_mcontext32from64_validate); + MODULE_HOOK_SET(netbsd32_process_doxmmregs_hook, "xmm32", + netbsd32_process_doxmmregs); } void @@ -967,4 +1043,5 @@ netbsd32_machdep_md_fini(void) MODULE_HOOK_UNSET(netbsd32_machine32_hook); MODULE_HOOK_UNSET(netbsd32_reg_validate_hook); + MODULE_HOOK_UNSET(netbsd32_process_doxmmregs_hook); } Index: src/sys/arch/amd64/amd64/process_machdep.c diff -u src/sys/arch/amd64/amd64/process_machdep.c:1.46 src/sys/arch/amd64/amd64/process_machdep.c:1.47 --- src/sys/arch/amd64/amd64/process_machdep.c:1.46 Wed Nov 27 09:08:14 2019 +++ src/sys/arch/amd64/amd64/process_machdep.c Wed Nov 27 09:16:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: process_machdep.c,v 1.46 2019/11/27 09:08:14 rin Exp $ */ +/* $NetBSD: process_machdep.c,v 1.47 2019/11/27 09:16:58 rin 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.46 2019/11/27 09:08:14 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.47 2019/11/27 09:16:58 rin Exp $"); #include "opt_xen.h" #include <sys/param.h> @@ -94,6 +94,8 @@ __KERNEL_RCSID(0, "$NetBSD: process_mach #include <x86/dbregs.h> #include <x86/fpu.h> +struct netbsd32_process_doxmmregs_hook_t netbsd32_process_doxmmregs_hook; + static inline struct trapframe *process_frame(struct lwp *); static inline struct trapframe * @@ -358,6 +360,16 @@ ptrace_machdep_dorequest( error = process_machdep_doxstate(l, lt, &uio); uvmspace_free(vm); return error; + + case PT_SETXMMREGS: /* only for COMPAT_NETBSD32 */ + write = true; + + /* FALLTHROUGH */ + case PT_GETXMMREGS: /* only for COMPAT_NETBSD32 */ + /* write = false done above. */ + MODULE_HOOK_CALL(netbsd32_process_doxmmregs_hook, + (l, lt, addr, write), EINVAL, error); + return error; } #ifdef DIAGNOSTIC Index: src/sys/arch/amd64/include/netbsd32_machdep.h diff -u src/sys/arch/amd64/include/netbsd32_machdep.h:1.24 src/sys/arch/amd64/include/netbsd32_machdep.h:1.25 --- src/sys/arch/amd64/include/netbsd32_machdep.h:1.24 Wed Jun 26 12:30:12 2019 +++ src/sys/arch/amd64/include/netbsd32_machdep.h Wed Nov 27 09:16:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_machdep.h,v 1.24 2019/06/26 12:30:12 mgorny Exp $ */ +/* $NetBSD: netbsd32_machdep.h,v 1.25 2019/11/27 09:16:58 rin Exp $ */ #ifndef _MACHINE_NETBSD32_H_ #define _MACHINE_NETBSD32_H_ @@ -7,6 +7,8 @@ #include <compat/sys/ucontext.h> #include <compat/sys/siginfo.h> +#include <x86/fpu.h> + /* * i386 ptrace constants * Please keep in sync with sys/arch/i386/include/ptrace.h. @@ -136,6 +138,11 @@ struct dbreg32 { int dr[8]; }; +struct xmmregs32 { + struct fxsave fxstate; +}; +__CTASSERT(sizeof(struct xmmregs32) == 512); + struct x86_get_ldt_args32 { int32_t start; uint32_t desc; Index: src/sys/arch/amd64/include/ptrace.h diff -u src/sys/arch/amd64/include/ptrace.h:1.18 src/sys/arch/amd64/include/ptrace.h:1.19 --- src/sys/arch/amd64/include/ptrace.h:1.18 Wed Nov 27 09:08:14 2019 +++ src/sys/arch/amd64/include/ptrace.h Wed Nov 27 09:16:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.18 2019/11/27 09:08:14 rin Exp $ */ +/* $NetBSD: ptrace.h,v 1.19 2019/11/27 09:16:58 rin Exp $ */ /* * Copyright (c) 1993 Christopher G. Demetriou @@ -47,6 +47,13 @@ #define PT_CLEARSTEP (PT_FIRSTMACH + 8) #define PT_GETXSTATE (PT_FIRSTMACH + 9) #define PT_SETXSTATE (PT_FIRSTMACH + 10) +#ifdef _KERNEL +/* + * Only used internally for COMPAT_NETBSD32 + */ +#define PT_GETXMMREGS (PT_FIRSTMACH + 11) +#define PT_SETXMMREGS (PT_FIRSTMACH + 12) +#endif /* We have machine-dependent process tracing needs. */ #define __HAVE_PTRACE_MACHDEP @@ -85,11 +92,17 @@ */ #define PTRACE_MACHDEP_REQUEST_CASES \ case PT_GETXSTATE: \ - case PT_SETXSTATE: + case PT_SETXSTATE: \ + case PT_GETXMMREGS: \ + case PT_SETXMMREGS: int process_machdep_doxstate(struct lwp *, struct lwp *, struct uio *); int process_machdep_validfpu(struct proc *); +#include <sys/module_hook.h> +MODULE_HOOK(netbsd32_process_doxmmregs_hook, int, + (struct lwp *, struct lwp *, void *, bool)); + #endif /* _KERNEL */ #ifdef _KERNEL_OPT