Subject: kernel stack overflow on netbsd-1-6 branch
To: None <port-i386@netbsd.org>
From: SAITOH Masanobu <masanobu@iij.ad.jp>
List: port-i386
Date: 11/26/2002 19:46:21
 Following patches pullup the KSTACK_CHECK_DR0 functions into netbsd-1-6
branch. You may see "trap on DR0: maybe kernel stack overflow" message
at boot time or heavy load.

 Should we increase UPAGES or am I misunderstanding something?

Index: conf/files.i386
===================================================================
RCS file: /cvsroot/test/src/sys/arch/i386/conf/files.i386,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 files.i386
--- conf/files.i386	2002/10/10 12:09:27	1.1.1.1
+++ conf/files.i386	2002/11/26 09:49:33
@@ -57,11 +57,14 @@
 # Large page size
 defflag			LARGEPAGES
 
+# kernel stack debug
+defflag	opt_kstack_dr0.h		KSTACK_CHECK_DR0
+
 file	arch/i386/i386/autoconf.c
 file	arch/i386/i386/bus_machdep.c
 file	arch/i386/i386/conf.c
 file	arch/i386/i386/consinit.c
-file	arch/i386/i386/db_dbgreg.s	ddb
+file	arch/i386/i386/db_dbgreg.s	ddb | kstack_check_dr0
 file	arch/i386/i386/db_disasm.c	ddb
 file	arch/i386/i386/db_interface.c	ddb
 file	arch/i386/i386/db_memrw.c	ddb | kgdb
Index: i386/pmap.c
===================================================================
RCS file: /cvsroot/test/src/sys/arch/i386/i386/pmap.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pmap.c
--- i386/pmap.c	2002/10/10 12:09:27	1.1.1.1
+++ i386/pmap.c	2002/11/26 09:49:33
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.136 2002/03/27 04:47:28 chs Exp $	*/
+/*	$NetBSD: pmap.c,v 1.137 2002/07/03 02:46:13 yamt Exp $	*/
 
 /*
  *
@@ -60,11 +60,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.136 2002/03/27 04:47:28 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.137 2002/07/03 02:46:13 yamt Exp $");
 
 #include "opt_cputype.h"
 #include "opt_user_ldt.h"
 #include "opt_largepages.h"
+#include "opt_kstack_dr0.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1675,6 +1676,16 @@
 		lcr3(pcb->pcb_cr3);
 	if (pcb == curpcb)
 		lldt(pcb->pcb_ldt_sel);
+
+#ifdef KSTACK_CHECK_DR0
+	/*
+	 * setup breakpoint on the top of stack
+	 */
+	if (p == &proc0)
+		dr0(0, 0, 0, 0);
+	else
+		dr0(KSTACK_LOWEST_ADDR(p), 1, 3, 1);
+#endif
 }
 
 /*
Index: i386/trap.c
===================================================================
RCS file: /cvsroot/test/src/sys/arch/i386/i386/trap.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 trap.c
--- i386/trap.c	2002/10/10 12:09:28	1.1.1.1
+++ i386/trap.c	2002/11/26 09:49:33
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.165 2002/02/18 15:58:02 simonb Exp $	*/
+/*	$NetBSD: trap.c,v 1.166 2002/07/03 02:46:15 yamt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -79,13 +79,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.165 2002/02/18 15:58:02 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.166 2002/07/03 02:46:15 yamt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
 #include "opt_math_emulate.h"
 #include "opt_vm86.h"
 #include "opt_cputype.h"
+#include "opt_kstack_dr0.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -202,6 +203,21 @@
 
 	default:
 	we_re_toast:
+#ifdef KSTACK_CHECK_DR0
+		if (type == T_TRCTRAP) {
+			u_int mask, dr6 = rdr6();
+
+			mask = 1 << 0; /* dr0 */
+			if (dr6 & mask) {
+				panic("trap on DR0: maybe kernel stack overflow\n");
+#if 0
+				dr6 &= ~mask;
+				ldr6(dr6);
+				return;
+#endif
+			}
+		}
+#endif
 #ifdef KGDB
 		if (kgdb_trap(type, &frame))
 			return;
Index: include/cpufunc.h
===================================================================
RCS file: /cvsroot/test/src/sys/arch/i386/include/cpufunc.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 cpufunc.h
--- include/cpufunc.h	2002/10/10 12:09:28	1.1.1.1
+++ include/cpufunc.h	2002/11/26 09:49:33
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.h,v 1.20 2001/07/31 18:28:59 thorpej Exp $	*/
+/*	$NetBSD: cpufunc.h,v 1.21 2002/07/03 02:46:16 yamt Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -134,6 +134,24 @@
 void	setidt	__P((int idx, /*XXX*/caddr_t func, int typ, int dpl));
 #endif
 
+/* debug register */
+void dr0(caddr_t, u_int32_t, u_int32_t, u_int32_t);
+
+static __inline u_int
+rdr6(void)
+{
+	u_int val;
+
+	__asm __volatile("movl %%dr6,%0" : "=r" (val));
+	return val;
+}
+
+static __inline void
+ldr6(u_int val)
+{
+
+	__asm __volatile("movl %0,%%dr6" : : "r" (val));
+}
 
 /* XXXX ought to be in psl.h with spl() functions */
 
Index: include/proc.h
===================================================================
RCS file: /cvsroot/test/src/sys/arch/i386/include/proc.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 proc.h
--- include/proc.h	2002/10/10 12:09:28	1.1.1.1
+++ include/proc.h	2002/11/26 09:49:33
@@ -1,4 +1,4 @@
-/*	$NetBSD: proc.h,v 1.14 2001/09/10 10:11:21 fvdl Exp $	*/
+/*	$NetBSD: proc.h,v 1.15 2002/10/11 17:49:11 yamt Exp $	*/
 
 /*
  * Copyright (c) 1991 Regents of the University of California.
@@ -51,3 +51,12 @@
 /* md_flags */
 #define	MDP_USEDFPU	0x0001	/* has used the FPU */
 #define MDP_USEDMTRR	0x0002	/* has set volatile MTRRs */
+
+/* kernel stack params */
+#ifndef NOREDZONE
+/* override default for redzone */
+#define	KSTACK_LOWEST_ADDR(p)	\
+	((caddr_t)ALIGN((p)->p_addr + 1) + NBPG)
+#define	KSTACK_SIZE	\
+	(USPACE - NBPG*2)
+#endif