Subject: interrupt stack red zones
To: None <port-i386@netbsd.org>
From: David Young <dyoung@pobox.com>
List: port-i386
Date: 08/19/2007 01:03:31
--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I have added red zones to the top and the bottom of the x86 interrupt
stack.  The zones are turned on and off by the same kernel option
(NOREDZONE) as the kernel stack red zone.  See attached patch.  Comments?

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933 ext 24

--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="intrstack.redzone.patch"

Index: intr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/intr.c,v
retrieving revision 1.28
diff -p -u -u -p -r1.28 intr.c
--- intr.c	21 Feb 2007 22:59:55 -0000	1.28
+++ intr.c	19 Aug 2007 06:02:12 -0000
@@ -106,6 +106,7 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.28 2007/02/21 22:59:55 thorpej Exp $");
 
+#include "opt_noredzone.h"
 #include "opt_multiprocessor.h"
 #include "opt_acpi.h"
 
@@ -808,6 +809,16 @@ struct intrhand fake_ipi_intrhand;
 static const char *x86_ipi_names[X86_NIPI] = X86_IPI_NAMES;
 #endif
 
+static inline int
+redzone_const_or_zero(int x)
+{
+#ifdef NOREDZONE
+	return 0;
+#else
+	return x;
+#endif /* !NOREDZONE */
+}
+
 /*
  * Initialize all handlers that aren't dynamically allocated, and exist
  * for each CPU.
@@ -820,7 +831,7 @@ cpu_intr_init(struct cpu_info *ci)
 	int i;
 #endif
 #if defined(INTRSTACKSIZE)
-	char *cp;
+	vaddr_t istack;
 #endif /* defined(INTRSTACKSIZE) */
 
 	MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
@@ -897,8 +908,20 @@ cpu_intr_init(struct cpu_info *ci)
 	intr_calculatemasks(ci);
 
 #if defined(INTRSTACKSIZE)
-	cp = (char *)uvm_km_alloc(kernel_map, INTRSTACKSIZE, 0, UVM_KMF_WIRED);
-	ci->ci_intrstack = cp + INTRSTACKSIZE - sizeof(register_t);
+	/* If the red zone is activated, protect both the top and
+	 * the bottom of the stack with an unmapped page.
+	 */
+	istack = uvm_km_alloc(kernel_map,
+	    INTRSTACKSIZE + redzone_const_or_zero(2 * PAGE_SIZE), 0,
+	    UVM_KMF_WIRED);
+	if (redzone_const_or_zero(1)) {
+		pmap_kremove(istack, PAGE_SIZE);
+		pmap_kremove(istack + INTRSTACKSIZE + PAGE_SIZE, PAGE_SIZE);
+		pmap_update(pmap_kernel());
+	}
+	ci->ci_intrstack =
+	    (char *)istack + redzone_const_or_zero(PAGE_SIZE) + INTRSTACKSIZE -
+	    sizeof(register_t);
 	ci->ci_idepth = -1;
 #endif /* defined(INTRSTACKSIZE) */
 }

--dDRMvlgZJXvWKvBx--