Module Name:    src
Committed By:   maxv
Date:           Thu Jul 26 09:29:08 UTC 2018

Modified Files:
        src/sys/arch/amd64/amd64: locore.S machdep.c netbsd32_machdep.c trap.c
        src/sys/arch/amd64/include: pcb.h userret.h
        src/sys/arch/i386/i386: locore.S machdep.c trap.c
        src/sys/arch/i386/include: pcb.h userret.h
        src/sys/arch/x86/include: dbregs.h
        src/sys/arch/x86/x86: dbregs.c vm_machdep.c

Log Message:
Rework dbregs, to switch the registers during context switches, and not on
each user->kernel transition via userret. Reloads of DR6/DR7 are expensive
on both native and xen.


To generate a diff of this commit:
cvs rdiff -u -r1.172 -r1.173 src/sys/arch/amd64/amd64/locore.S
cvs rdiff -u -r1.308 -r1.309 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.115 -r1.116 src/sys/arch/amd64/amd64/netbsd32_machdep.c
cvs rdiff -u -r1.113 -r1.114 src/sys/arch/amd64/amd64/trap.c
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/amd64/include/pcb.h
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/amd64/include/userret.h
cvs rdiff -u -r1.159 -r1.160 src/sys/arch/i386/i386/locore.S
cvs rdiff -u -r1.807 -r1.808 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.295 -r1.296 src/sys/arch/i386/i386/trap.c
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/i386/include/pcb.h
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/i386/include/userret.h
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/x86/include/dbregs.h
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/x86/x86/dbregs.c
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/x86/x86/vm_machdep.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/locore.S
diff -u src/sys/arch/amd64/amd64/locore.S:1.172 src/sys/arch/amd64/amd64/locore.S:1.173
--- src/sys/arch/amd64/amd64/locore.S:1.172	Sat Jul 21 06:09:13 2018
+++ src/sys/arch/amd64/amd64/locore.S	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.172 2018/07/21 06:09:13 maxv Exp $	*/
+/*	$NetBSD: locore.S,v 1.173 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright-o-rama!
@@ -1143,6 +1143,11 @@ ENTRY(cpu_switchto)
 #endif
 .Lring0_switched:
 
+	/* Switch the dbregs. */
+	movq	%r13,%rdi
+	movq	%r12,%rsi
+	callq	_C_LABEL(x86_dbregs_switch)
+
 #ifndef XEN
 	movb	_C_LABEL(x86_fpu_eager),%dl
 	testb	%dl,%dl

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.308 src/sys/arch/amd64/amd64/machdep.c:1.309
--- src/sys/arch/amd64/amd64/machdep.c:1.308	Sun Jul 22 15:02:51 2018
+++ src/sys/arch/amd64/amd64/machdep.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.308 2018/07/22 15:02:51 maxv Exp $	*/
+/*	$NetBSD: machdep.c,v 1.309 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,7 +110,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.308 2018/07/22 15:02:51 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.309 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_modular.h"
 #include "opt_user_ldt.h"
@@ -280,8 +280,6 @@ void (*delay_func)(unsigned int) = xen_d
 void (*initclock_func)(void) = xen_initclocks;
 #endif
 
-extern struct pool x86_dbregspl;
-
 struct nmistore {
 	uint64_t cr3;
 	uint64_t scratch;
@@ -1367,10 +1365,7 @@ setregs(struct lwp *l, struct exec_packa
 	fpu_save_area_clear(l, pack->ep_osversion >= 699002600
 	    ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__);
 	pcb->pcb_flags = 0;
-	if (pcb->pcb_dbregs != NULL) {
-		pool_put(&x86_dbregspl, pcb->pcb_dbregs);
-		pcb->pcb_dbregs = NULL;
-	}
+	x86_dbregs_clear(l);
 
 	l->l_proc->p_flag &= ~PK_32;
 

Index: src/sys/arch/amd64/amd64/netbsd32_machdep.c
diff -u src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.115 src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.116
--- src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.115	Thu Dec  7 23:11:50 2017
+++ src/sys/arch/amd64/amd64/netbsd32_machdep.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_machdep.c,v 1.115 2017/12/07 23:11:50 christos Exp $	*/
+/*	$NetBSD: netbsd32_machdep.c,v 1.116 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.115 2017/12/07 23:11:50 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.116 2018/07/26 09:29:08 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -63,6 +63,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_mac
 #include <sys/kauth.h>
 
 #include <x86/fpu.h>
+#include <x86/dbregs.h>
 #include <machine/frame.h>
 #include <machine/reg.h>
 #include <machine/vmparam.h>
@@ -80,8 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_mac
 #include <compat/sys/signal.h>
 #include <compat/sys/signalvar.h>
 
-extern struct pool x86_dbregspl;
-
 /* Provide a the name of the architecture we're emulating */
 const char	machine32[] = "i386";
 const char	machine_arch32[] = "i386";	
@@ -138,10 +137,7 @@ netbsd32_setregs(struct lwp *l, struct e
 	fpu_save_area_clear(l, pack->ep_osversion >= 699002600
 	    ?  __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__);
 
-	if (pcb->pcb_dbregs != NULL) {
-		pool_put(&x86_dbregspl, pcb->pcb_dbregs);
-		pcb->pcb_dbregs = NULL;
-	}
+	x86_dbregs_clear(l);
 
 	p->p_flag |= PK_32;
 

Index: src/sys/arch/amd64/amd64/trap.c
diff -u src/sys/arch/amd64/amd64/trap.c:1.113 src/sys/arch/amd64/amd64/trap.c:1.114
--- src/sys/arch/amd64/amd64/trap.c:1.113	Sun Feb 25 13:09:33 2018
+++ src/sys/arch/amd64/amd64/trap.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.113 2018/02/25 13:09:33 maxv Exp $	*/
+/*	$NetBSD: trap.c,v 1.114 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2000, 2017 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.113 2018/02/25 13:09:33 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.114 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -93,6 +93,7 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.1
 
 #include <machine/cpufunc.h>
 #include <x86/fpu.h>
+#include <x86/dbregs.h>
 #include <machine/psl.h>
 #include <machine/reg.h>
 #include <machine/trap.h>

Index: src/sys/arch/amd64/include/pcb.h
diff -u src/sys/arch/amd64/include/pcb.h:1.28 src/sys/arch/amd64/include/pcb.h:1.29
--- src/sys/arch/amd64/include/pcb.h:1.28	Sun Dec 31 07:23:09 2017
+++ src/sys/arch/amd64/include/pcb.h	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcb.h,v 1.28 2017/12/31 07:23:09 maxv Exp $	*/
+/*	$NetBSD: pcb.h,v 1.29 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -80,6 +80,7 @@
 struct pcb {
 	int	  pcb_flags;
 #define	PCB_COMPAT32	0x01
+#define	PCB_DBREGS	0x02
 	u_int	  pcb_cr0;		/* saved image of CR0 */
 	uint64_t pcb_rsp0;
 	uint64_t pcb_cr2;		/* page fault address (CR2) */

Index: src/sys/arch/amd64/include/userret.h
diff -u src/sys/arch/amd64/include/userret.h:1.12 src/sys/arch/amd64/include/userret.h:1.13
--- src/sys/arch/amd64/include/userret.h:1.12	Thu Feb 23 03:34:22 2017
+++ src/sys/arch/amd64/include/userret.h	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: userret.h,v 1.12 2017/02/23 03:34:22 kamil Exp $	*/
+/*	$NetBSD: userret.h,v 1.13 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * XXXfvdl same as i386 counterpart, but should probably be independent.
@@ -67,7 +67,6 @@
  */
 
 #include <sys/userret.h>
-#include <x86/dbregs.h>
 
 static __inline void userret(struct lwp *);
 
@@ -78,13 +77,6 @@ static __inline void userret(struct lwp 
 static __inline void
 userret(struct lwp *l)
 {
-	struct pcb *pcb = lwp_getpcb(l);
-
 	/* Invoke MI userret code */
 	mi_userret(l);
-
-	if (pcb->pcb_dbregs)
-		x86_dbregs_set(l);
-	else
-		x86_dbregs_clear(l);
 }

Index: src/sys/arch/i386/i386/locore.S
diff -u src/sys/arch/i386/i386/locore.S:1.159 src/sys/arch/i386/i386/locore.S:1.160
--- src/sys/arch/i386/i386/locore.S:1.159	Sat Jul 14 14:29:40 2018
+++ src/sys/arch/i386/i386/locore.S	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.159 2018/07/14 14:29:40 maxv Exp $	*/
+/*	$NetBSD: locore.S,v 1.160 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright-o-rama!
@@ -128,7 +128,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.159 2018/07/14 14:29:40 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.160 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_copy_symtab.h"
 #include "opt_ddb.h"
@@ -1116,6 +1116,12 @@ skip_save:
 	movl	%eax,TSS_ESP0(%ecx)
 #endif
 
+	/* Switch the dbregs. */
+	pushl	%edi
+	pushl	%esi
+	call	_C_LABEL(x86_dbregs_switch)
+	addl	$8,%esp
+
 #ifndef XEN
 	pushl	%edx
 	movb	_C_LABEL(x86_fpu_eager),%dl

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.807 src/sys/arch/i386/i386/machdep.c:1.808
--- src/sys/arch/i386/i386/machdep.c:1.807	Sun Jul 22 15:02:51 2018
+++ src/sys/arch/i386/i386/machdep.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.807 2018/07/22 15:02:51 maxv Exp $	*/
+/*	$NetBSD: machdep.c,v 1.808 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.807 2018/07/22 15:02:51 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.808 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_freebsd.h"
@@ -213,8 +213,6 @@ int i386_use_fxsave;
 int i386_has_sse;
 int i386_has_sse2;
 
-extern struct pool x86_dbregspl;
-
 vaddr_t idt_vaddr;
 paddr_t idt_paddr;
 vaddr_t gdt_vaddr;
@@ -874,10 +872,8 @@ setregs(struct lwp *l, struct exec_packa
 
 	memcpy(&pcb->pcb_fsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_fsd));
 	memcpy(&pcb->pcb_gsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_gsd));
-	if (pcb->pcb_dbregs != NULL) {
-		pool_put(&x86_dbregspl, pcb->pcb_dbregs);
-		pcb->pcb_dbregs = NULL;
-	}
+
+	x86_dbregs_clear(l);
 
 	tf = l->l_md.md_regs;
 	tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL);

Index: src/sys/arch/i386/i386/trap.c
diff -u src/sys/arch/i386/i386/trap.c:1.295 src/sys/arch/i386/i386/trap.c:1.296
--- src/sys/arch/i386/i386/trap.c:1.295	Wed May 16 16:33:23 2018
+++ src/sys/arch/i386/i386/trap.c	Thu Jul 26 09:29:08 2018
@@ -1,5 +1,5 @@
 
-/*	$NetBSD: trap.c,v 1.295 2018/05/16 16:33:23 maxv Exp $	*/
+/*	$NetBSD: trap.c,v 1.296 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.295 2018/05/16 16:33:23 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.296 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -106,6 +106,7 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.2
 #include <machine/mca_machdep.h>
 #endif
 
+#include <x86/dbregs.h>
 #include <x86/nmi.h>
 
 #include "isa.h"

Index: src/sys/arch/i386/include/pcb.h
diff -u src/sys/arch/i386/include/pcb.h:1.57 src/sys/arch/i386/include/pcb.h:1.58
--- src/sys/arch/i386/include/pcb.h:1.57	Tue Oct 31 12:02:20 2017
+++ src/sys/arch/i386/include/pcb.h	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcb.h,v 1.57 2017/10/31 12:02:20 maxv Exp $	*/
+/*	$NetBSD: pcb.h,v 1.58 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2009 The NetBSD Foundation, Inc.
@@ -93,7 +93,10 @@ struct pcb {
 	struct dbreg	*pcb_dbregs;	/* CPU Debug Registers */
 	uint16_t pcb_fpu_dflt_cw;
 
-	int	not_used[16];
+#define	PCB_DBREGS	0x01
+	int	pcb_flags;
+
+	int	not_used[15];
 
 	/* floating point state */
 	struct cpu_info	*pcb_fpcpu;	/* cpu holding our fp state. */

Index: src/sys/arch/i386/include/userret.h
diff -u src/sys/arch/i386/include/userret.h:1.14 src/sys/arch/i386/include/userret.h:1.15
--- src/sys/arch/i386/include/userret.h:1.14	Thu Feb 23 03:34:22 2017
+++ src/sys/arch/i386/include/userret.h	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: userret.h,v 1.14 2017/02/23 03:34:22 kamil Exp $	*/
+/*	$NetBSD: userret.h,v 1.15 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -63,7 +63,6 @@
  */
 
 #include <sys/userret.h>
-#include <x86/dbregs.h>
 
 static __inline void userret(struct lwp *);
 
@@ -74,13 +73,6 @@ static __inline void userret(struct lwp 
 static __inline void
 userret(struct lwp *l)
 {
-	struct pcb *pcb = lwp_getpcb(l);
-
 	/* Invoke MI userret code */
 	mi_userret(l);
-
-	if (pcb->pcb_dbregs)
-		x86_dbregs_set(l);
-	else
-		x86_dbregs_clear(l);
 }

Index: src/sys/arch/x86/include/dbregs.h
diff -u src/sys/arch/x86/include/dbregs.h:1.5 src/sys/arch/x86/include/dbregs.h:1.6
--- src/sys/arch/x86/include/dbregs.h:1.5	Sun Jul 22 15:02:51 2018
+++ src/sys/arch/x86/include/dbregs.h	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: dbregs.h,v 1.5 2018/07/22 15:02:51 maxv Exp $	*/
+/*	$NetBSD: dbregs.h,v 1.6 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -108,11 +108,12 @@ enum x86_dr7_length {
 
 void x86_dbregs_init(void);
 void x86_dbregs_clear(struct lwp *);
+void x86_dbregs_abandon(struct lwp *);
 void x86_dbregs_read(struct lwp *, struct dbreg *);
-void x86_dbregs_set(struct lwp *);
 void x86_dbregs_store_dr6(struct lwp *);
 int x86_dbregs_user_trap(void);
 int x86_dbregs_validate(const struct dbreg *);
 void x86_dbregs_write(struct lwp *, const struct dbreg *);
+void x86_dbregs_switch(struct lwp *, struct lwp *);
 
 #endif /* !_X86_DBREGS_H_ */

Index: src/sys/arch/x86/x86/dbregs.c
diff -u src/sys/arch/x86/x86/dbregs.c:1.10 src/sys/arch/x86/x86/dbregs.c:1.11
--- src/sys/arch/x86/x86/dbregs.c:1.10	Sun Jul 22 15:02:51 2018
+++ src/sys/arch/x86/x86/dbregs.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: dbregs.c,v 1.10 2018/07/22 15:02:51 maxv Exp $	*/
+/*	$NetBSD: dbregs.c,v 1.11 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -39,7 +39,6 @@
 #include <machine/pmap.h>
 
 struct pool x86_dbregspl;
-
 static struct dbreg initdbstate;
 
 #define X86_BREAKPOINT_CONDITION_DETECTED	( \
@@ -79,13 +78,9 @@ x86_dbregs_init(void)
 	    NULL, IPL_NONE);
 }
 
-void
-x86_dbregs_clear(struct lwp *l)
+static void
+x86_dbregs_reset(void)
 {
-	struct pcb *pcb __diagused = lwp_getpcb(l);
-
-	KASSERT(pcb->pcb_dbregs == NULL);
-
 	/*
 	 * It's sufficient to just disable Debug Control Register (DR7).
 	 * It will deactivate hardware watchpoints.
@@ -102,6 +97,41 @@ x86_dbregs_clear(struct lwp *l)
 }
 
 void
+x86_dbregs_clear(struct lwp *l)
+{
+	struct pcb *pcb = lwp_getpcb(l);
+	struct dbreg *dbregs;
+
+	KASSERT(l == curlwp);
+
+	if (__predict_true(pcb->pcb_dbregs == NULL)) {
+		KASSERT((pcb->pcb_flags & PCB_DBREGS) == 0);
+		return;
+	}
+
+	dbregs = pcb->pcb_dbregs;
+
+	kpreempt_disable();
+	pcb->pcb_dbregs = NULL;
+	pcb->pcb_flags &= ~PCB_DBREGS;
+	x86_dbregs_reset();
+	kpreempt_enable();
+
+	pool_put(&x86_dbregspl, dbregs);
+}
+
+void
+x86_dbregs_abandon(struct lwp *l)
+{
+	struct pcb *pcb = lwp_getpcb(l);
+
+	kpreempt_disable();
+	pcb->pcb_flags &= ~PCB_DBREGS;
+	x86_dbregs_reset();
+	kpreempt_enable();
+}
+
+void
 x86_dbregs_read(struct lwp *l, struct dbreg *regs)
 {
 	struct pcb *pcb = lwp_getpcb(l);
@@ -109,12 +139,29 @@ x86_dbregs_read(struct lwp *l, struct db
 	if (pcb->pcb_dbregs == NULL) {
 		pcb->pcb_dbregs = pool_get(&x86_dbregspl, PR_WAITOK);
 		memcpy(pcb->pcb_dbregs, &initdbstate, sizeof(initdbstate));
+		pcb->pcb_flags |= PCB_DBREGS;
 	}
 	memcpy(regs, pcb->pcb_dbregs, sizeof(*regs));
 }
 
-void
-x86_dbregs_set(struct lwp *l)
+static void
+x86_dbregs_save(struct lwp *l)
+{
+	struct pcb *pcb = lwp_getpcb(l);
+
+	KASSERT(pcb->pcb_dbregs != NULL);
+
+	pcb->pcb_dbregs->dr[0] = rdr0();
+	pcb->pcb_dbregs->dr[1] = rdr1();
+	pcb->pcb_dbregs->dr[2] = rdr2();
+	pcb->pcb_dbregs->dr[3] = rdr3();
+
+	pcb->pcb_dbregs->dr[6] = rdr6();
+	pcb->pcb_dbregs->dr[7] = rdr7();
+}
+
+static void
+x86_dbregs_restore(struct lwp *l)
 {
 	struct pcb *pcb = lwp_getpcb(l);
 
@@ -222,4 +269,38 @@ x86_dbregs_write(struct lwp *l, const st
 	}
 
 	memcpy(pcb->pcb_dbregs, regs, sizeof(*regs));
+	pcb->pcb_flags |= PCB_DBREGS;
+}
+
+/*
+ * Called with preemption disabled.
+ */
+void
+x86_dbregs_switch(struct lwp *oldlwp, struct lwp *newlwp)
+{
+	struct pcb *oldpcb, *newpcb;
+	bool olddb, newdb;
+
+	oldpcb = (oldlwp != NULL) ? lwp_getpcb(oldlwp) : NULL;
+	newpcb = lwp_getpcb(newlwp);
+
+	olddb = false;
+	if (oldpcb) {
+		olddb = (oldpcb->pcb_flags & PCB_DBREGS) != 0;
+	}
+	newdb = (newpcb->pcb_flags & PCB_DBREGS) != 0;
+
+	if (__predict_true(!olddb && !newdb)) {
+		/* fast path */
+		return;
+	}
+
+	if (olddb) {
+		x86_dbregs_save(oldlwp);
+	}
+	if (newdb) {
+		x86_dbregs_restore(newlwp);
+	} else if (olddb) {
+		x86_dbregs_reset();
+	}
 }

Index: src/sys/arch/x86/x86/vm_machdep.c
diff -u src/sys/arch/x86/x86/vm_machdep.c:1.35 src/sys/arch/x86/x86/vm_machdep.c:1.36
--- src/sys/arch/x86/x86/vm_machdep.c:1.35	Sun Jul  1 08:32:41 2018
+++ src/sys/arch/x86/x86/vm_machdep.c	Thu Jul 26 09:29:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm_machdep.c,v 1.35 2018/07/01 08:32:41 maxv Exp $	*/
+/*	$NetBSD: vm_machdep.c,v 1.36 2018/07/26 09:29:08 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.35 2018/07/01 08:32:41 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.36 2018/07/26 09:29:08 maxv Exp $");
 
 #include "opt_mtrr.h"
 
@@ -166,6 +166,7 @@ cpu_lwp_fork(struct lwp *l1, struct lwp 
 
 	/* Never inherit CPU Debug Registers */
 	pcb2->pcb_dbregs = NULL;
+	pcb2->pcb_flags &= ~PCB_DBREGS;
 
 #if defined(XEN)
 	pcb2->pcb_iopl = IOPL_KPL;
@@ -262,6 +263,9 @@ cpu_lwp_free(struct lwp *l, int proc)
 	/* If we were using the FPU, forget about it. */
 	fpusave_lwp(l, false);
 
+	/* Abandon the dbregs state. */
+	x86_dbregs_abandon(l);
+
 #ifdef MTRR
 	if (proc && l->l_proc->p_md.md_flags & MDP_USEDMTRR)
 		mtrr_clean(l->l_proc);
@@ -287,7 +291,7 @@ cpu_lwp_free2(struct lwp *l)
 	KASSERT(l->l_md.md_gc_pmap == NULL);
 
 	pcb = lwp_getpcb(l);
-
+	KASSERT((pcb->pcb_flags & PCB_DBREGS) == 0);
 	if (pcb->pcb_dbregs) {
 		pool_put(&x86_dbregspl, pcb->pcb_dbregs);
 		pcb->pcb_dbregs = NULL;

Reply via email to