Module Name:    src
Committed By:   kamil
Date:           Sun Nov 27 14:49:21 UTC 2016

Modified Files:
        src/sys/arch/amd64/amd64: cpufunc.S
        src/sys/arch/i386/i386: i386func.S
        src/sys/arch/x86/include: cpufunc.h
        src/sys/arch/xen/x86: xenfunc.c
Added Files:
        src/sys/arch/x86/include: dbregs.h

Log Message:
Add accessors for available x86 Debug Registers

There are 8 Debug Registers on i386 (available at least since 80386) and 16
on AMD64. Currently DR4 and DR5 are reserved on both cpu-families and
DR9-DR15 are still reserved on AMD64. Therefore add accessors for DR0-DR3,
DR6-DR7 for all ports.

Debug Registers x86:
 * DR0-DR3  Debug Address Registers
 * DR4-DR5  Reserved
 * DR6      Debug Status Register
 * DR7      Debug Control Register
 * DR8-DR15 Reserved

Access the registers is available only from a kernel (ring 0) as there is
needed top protected access. For this reason there is need to use special
XEN functions to get and set the registers in the XEN3 kernels.

XEN specific functions as defined in NetBSD:
 - HYPERVISOR_get_debugreg()
 - HYPERVISOR_set_debugreg()

This code extends the existing rdr6() and ldr6() accessor for additional:
 - rdr0() & ldr0()
 - rdr1() & ldr1()
 - rdr2() & ldr2()
 - rdr3() & ldr3()
 - rdr7() & ldr7()

Traditionally accessors for DR6 were passing vaddr_t argument, while it's
appropriate type for DR0-DR3, DR6-DR7 should be using u_long, however it's
not a big deal. The resulting functionality should be equivalent so stick
to this convention and use the vaddr_t type for all DR accessors.

There was already a function defined for rdr6() in XEN, but it had a nit on
AMD64 as it was casting HYPERVISOR_get_debugreg() to u_int (32-bit on
AMD64), truncating result. It still works for DR6, but for the sake of
simplicity always return full 64-bit value.

New accessors duplicate functionality of the dr0() function available on
i386 within the KSTACK_CHECK_DR0 option. dr0() is a specialized layer with
logic to set appropriate types of interrupts, now accessors are designed to
pass verbatim values from user-land (with simple sanity checks in the
kernel). At the moment there are no plans to make possible to coexist
KSTACK_CHECK_DR0 with debug registers for user applications (debuggers).

     options KSTACK_CHECK_DR0
     Detect kernel stack overflow using DR0 register.  This option uses DR0
     register exclusively so you can't use DR0 register for other purpose
     (e.g., hardware breakpoint) if you turn this on.

The KSTACK_CHECK_DR0 functionality was designed for i386 and never ported
to amd64.

Code tested on i386 and amd64 with kernels: GENERIC, XEN3_DOMU, XEN3_DOM0.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/i386/i386/i386func.S
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/x86/include/cpufunc.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/include/dbregs.h
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/xen/x86/xenfunc.c

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/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.26 src/sys/arch/amd64/amd64/cpufunc.S:1.27
--- src/sys/arch/amd64/amd64/cpufunc.S:1.26	Sun Nov 27 02:32:56 2016
+++ src/sys/arch/amd64/amd64/cpufunc.S	Sun Nov 27 14:49:21 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.26 2016/11/27 02:32:56 kamil Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.27 2016/11/27 14:49:21 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -158,6 +158,38 @@ ENTRY(tlbflush)
 	movq	%rax, %cr3
 	ret
 
+ENTRY(ldr0)
+	movq	%rdi, %dr0
+	ret
+
+ENTRY(rdr0)
+	movq	%dr0, %rax
+	ret
+
+ENTRY(ldr1)
+	movq	%rdi, %dr1
+	ret
+
+ENTRY(rdr1)
+	movq	%dr1, %rax
+	ret
+
+ENTRY(ldr2)
+	movq	%rdi, %dr2
+	ret
+
+ENTRY(rdr2)
+	movq	%dr2, %rax
+	ret
+
+ENTRY(ldr3)
+	movq	%rdi, %dr3
+	ret
+
+ENTRY(rdr3)
+	movq	%dr3, %rax
+	ret
+
 ENTRY(ldr6)
 	movq	%rdi, %dr6
 	ret
@@ -166,6 +198,14 @@ ENTRY(rdr6)
 	movq	%dr6, %rax
 	ret
 
+ENTRY(ldr7)
+	movq	%rdi, %dr7
+	ret
+
+ENTRY(rdr7)
+	movq	%dr7, %rax
+	ret
+
 ENTRY(x86_disable_intr)
 	cli
 	ret

Index: src/sys/arch/i386/i386/i386func.S
diff -u src/sys/arch/i386/i386/i386func.S:1.17 src/sys/arch/i386/i386/i386func.S:1.18
--- src/sys/arch/i386/i386/i386func.S:1.17	Wed Aug 29 22:43:35 2012
+++ src/sys/arch/i386/i386/i386func.S	Sun Nov 27 14:49:21 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386func.S,v 1.17 2012/08/29 22:43:35 rmind Exp $	*/
+/*	$NetBSD: i386func.S,v 1.18 2016/11/27 14:49:21 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: i386func.S,v 1.17 2012/08/29 22:43:35 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i386func.S,v 1.18 2016/11/27 14:49:21 kamil Exp $");
 
 #include <machine/specialreg.h>
 #include <machine/segments.h>
@@ -123,6 +123,50 @@ ENTRY(tlbflush)
 	ret
 END(tlbflush)
 
+ENTRY(ldr0)
+	movl	4(%esp), %eax
+	movl	%eax, %dr0
+	ret
+END(ldr0)
+
+ENTRY(rdr0)
+	movl	%dr0, %eax
+	ret
+END(rdr0)
+
+ENTRY(ldr1)
+	movl	4(%esp), %eax
+	movl	%eax, %dr1
+	ret
+END(ldr1)
+
+ENTRY(rdr1)
+	movl	%dr1, %eax
+	ret
+END(rdr1)
+
+ENTRY(ldr2)
+	movl	4(%esp), %eax
+	movl	%eax, %dr2
+	ret
+END(ldr2)
+
+ENTRY(rdr2)
+	movl	%dr2, %eax
+	ret
+END(rdr2)
+
+ENTRY(ldr3)
+	movl	4(%esp), %eax
+	movl	%eax, %dr3
+	ret
+END(ldr3)
+
+ENTRY(rdr3)
+	movl	%dr3, %eax
+	ret
+END(rdr3)
+
 ENTRY(ldr6)
 	movl	4(%esp), %eax
 	movl	%eax, %dr6
@@ -134,6 +178,17 @@ ENTRY(rdr6)
 	ret
 END(rdr6)
 
+ENTRY(ldr7)
+	movl	4(%esp), %eax
+	movl	%eax, %dr7
+	ret
+END(ldr7)
+
+ENTRY(rdr7)
+	movl	%dr7, %eax
+	ret
+END(rdr7)
+
 ENTRY(rcr2)
 	movl	%cr2, %eax
 	ret

Index: src/sys/arch/x86/include/cpufunc.h
diff -u src/sys/arch/x86/include/cpufunc.h:1.19 src/sys/arch/x86/include/cpufunc.h:1.20
--- src/sys/arch/x86/include/cpufunc.h:1.19	Tue Jan  5 10:20:22 2016
+++ src/sys/arch/x86/include/cpufunc.h	Sun Nov 27 14:49:21 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.h,v 1.19 2016/01/05 10:20:22 hannken Exp $	*/
+/*	$NetBSD: cpufunc.h,v 1.20 2016/11/27 14:49:21 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
@@ -69,8 +69,18 @@ vaddr_t	rcr8(void);
 void	tlbflush(void);
 void	tlbflushg(void);
 void	dr0(void *, uint32_t, uint32_t, uint32_t);
+vaddr_t	rdr0(void);
+void	ldr0(vaddr_t);
+vaddr_t	rdr1(void);
+void	ldr1(vaddr_t);
+vaddr_t	rdr2(void);
+void	ldr2(vaddr_t);
+vaddr_t	rdr3(void);
+void	ldr3(vaddr_t);
 vaddr_t	rdr6(void);
 void	ldr6(vaddr_t);
+vaddr_t	rdr7(void);
+void	ldr7(vaddr_t);
 void	wbinvd(void);
 void	breakpoint(void);
 void	x86_hlt(void);

Index: src/sys/arch/xen/x86/xenfunc.c
diff -u src/sys/arch/xen/x86/xenfunc.c:1.13 src/sys/arch/xen/x86/xenfunc.c:1.14
--- src/sys/arch/xen/x86/xenfunc.c:1.13	Sun Nov  6 11:40:47 2011
+++ src/sys/arch/xen/x86/xenfunc.c	Sun Nov 27 14:49:21 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: xenfunc.c,v 1.13 2011/11/06 11:40:47 cherry Exp $	*/
+/*	$NetBSD: xenfunc.c,v 1.14 2016/11/27 14:49:21 kamil Exp $	*/
 
 /*
  *
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.13 2011/11/06 11:40:47 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.14 2016/11/27 14:49:21 kamil Exp $");
 
 #include <sys/param.h>
 
@@ -122,12 +122,65 @@ tlbflushg(void)
 }
 
 vaddr_t
+rdr0(void)
+{
+
+	return HYPERVISOR_get_debugreg(0);
+}
+
+void
+ldr0(vaddr_t val)
+{
+
+	HYPERVISOR_set_debugreg(0, val);
+}
+
+vaddr_t
+rdr1(void)
+{
+
+	return HYPERVISOR_get_debugreg(1);
+}
+
+void
+ldr1(vaddr_t val)
+{
+
+	HYPERVISOR_set_debugreg(1, val);
+}
+
+vaddr_t
+rdr2(void)
+{
+
+	return HYPERVISOR_get_debugreg(2);
+}
+
+void
+ldr2(vaddr_t val)
+{
+
+	HYPERVISOR_set_debugreg(2, val);
+}
+
+vaddr_t
+rdr3(void)
+{
+
+	return HYPERVISOR_get_debugreg(3);
+}
+
+void
+ldr3(vaddr_t val)
+{
+
+	HYPERVISOR_set_debugreg(3, val);
+}
+vaddr_t
 rdr6(void)
 {
-	u_int val;
 
-	val = HYPERVISOR_get_debugreg(6);
-	return val;
+	return HYPERVISOR_get_debugreg(6);
 }
 
 void
@@ -137,6 +190,20 @@ ldr6(vaddr_t val)
 	HYPERVISOR_set_debugreg(6, val);
 }
 
+vaddr_t
+rdr7(void)
+{
+
+	return HYPERVISOR_get_debugreg(7);
+}
+
+void
+ldr7(vaddr_t val)
+{
+
+	HYPERVISOR_set_debugreg(7, val);
+}
+
 void
 wbinvd(void)
 {

Added files:

Index: src/sys/arch/x86/include/dbregs.h
diff -u /dev/null src/sys/arch/x86/include/dbregs.h:1.1
--- /dev/null	Sun Nov 27 14:49:21 2016
+++ src/sys/arch/x86/include/dbregs.h	Sun Nov 27 14:49:21 2016
@@ -0,0 +1,45 @@
+/*	$NetBSD: dbregs.h,v 1.1 2016/11/27 14:49:21 kamil Exp $	*/
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef	_X86_DBREGS_H_
+#define	_X86_DBREGS_H_
+
+#ifdef _KERNEL
+
+struct lwp;
+struct dbreg;
+
+void reset_dbregs(void);
+
+int process_write_dbregs(struct lwp *lwp, const struct dbreg *regs);
+int process_read_dbregs(struct lwp *lwp, struct dbreg *regs);
+
+#endif
+
+#endif /* _X86_FPU_H_ */

Reply via email to