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 *)&regs;
+
+	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, &regs.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, &regs.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

Reply via email to