Index: arch/ia64/include/interrupt.h
===================================================================
--- arch/ia64/include/interrupt.h	(revision bc314be837c993a70ed30ed4372ac9aa7b16138b)
+++ arch/ia64/include/interrupt.h	(revision 83d2d0e4bbabfdae355ca18dba80470da9b35e38)
@@ -60,4 +60,5 @@
 	__address cr_iip;
 	__u64 pr;
+	__address sp;
 } __attribute__ ((packed));
 
Index: arch/ia64/include/register.h
===================================================================
--- arch/ia64/include/register.h	(revision bc314be837c993a70ed30ed4372ac9aa7b16138b)
+++ arch/ia64/include/register.h	(revision 83d2d0e4bbabfdae355ca18dba80470da9b35e38)
@@ -42,4 +42,7 @@
 #define PSR_RT_MASK	(1<<27)
 #define PSR_IT_MASK	0x0000001000000000
+
+#define PSR_CPL_SHIFT		32
+#define PSR_CPL_MASK_SHIFTED	3
 
 /** Application registers. */
Index: arch/ia64/src/ivt.S
===================================================================
--- arch/ia64/src/ivt.S	(revision bc314be837c993a70ed30ed4372ac9aa7b16138b)
+++ arch/ia64/src/ivt.S	(revision 83d2d0e4bbabfdae355ca18dba80470da9b35e38)
@@ -30,10 +30,14 @@
 #include <arch/stack.h>
 #include <arch/register.h>
-
-#define STACK_ITEMS		12
-#define STACK_FRAME_SIZE	((STACK_ITEMS*STACK_ITEM_SIZE) + STACK_SCRATCH_AREA_SIZE)
-
-#if (STACK_FRAME_SIZE % STACK_ALIGNMENT != 0)
-#error Memory stack must be 16-byte aligned.
+#include <arch/mm/page.h>
+#include <align.h>
+
+#define STACK_ITEMS		13
+#define STACK_FRAME_SIZE	ALIGN_UP((STACK_ITEMS*STACK_ITEM_SIZE) + STACK_SCRATCH_AREA_SIZE, STACK_ALIGNMENT)
+
+#if (STACK_ITEMS % 2 == 0)
+#	define STACK_FRAME_BIAS	8
+#else
+#	define STACK_FRAME_BIAS 16
 #endif
 
@@ -71,5 +75,5 @@
     
 	/*
-	 * Note that r24-r31 from bank0 can be used only as long as PSR.ic = 0.
+	 * Note that r24-r31 from bank 0 can be used only as long as PSR.ic = 0.
 	 */
 	mov r24 = cr.iip
@@ -83,18 +87,41 @@
 	
     /* 3. switch to kernel memory stack */
-	/* TODO: support interruptions from userspace */
-	/* assume kernel stack */
-	
-	add r31 = -8, r12 ;;
+    	mov r30 = cr.ipsr
+	shr.u r31 = r12, VRN_SHIFT ;; 
+
+	/*
+	 * Set p6 to true if the stack register references kernel address space.
+	 * Set p7 to false if the stack register doesn't reference kernel address space.
+	 */
+	cmp.eq p6, p7 = VRN_KERNEL, r31 ;;
+	
+	(p6) shr.u r30 = r30, PSR_CPL_SHIFT ;;
+	(p6) and r30 = PSR_CPL_MASK_SHIFTED, r30 ;;
+
+	/*
+	 * Set p6 to true if the interrupted context executed in kernel mode.
+	 * Set p7 to false if the interrupted context didn't execute in kernel mode.
+	 */
+	(p6) cmp.eq p6, p7 = r30, r0 ;;
+	
+	/*
+	 * Now, p7 is true iff the stack needs to be switched to kernel stack.
+	 */
+	mov r30 = r12
+	(p7) mov r12 = R_KSTACK ;;
+	
+	add r31 = -STACK_FRAME_BIAS, r12 ;;
 	add r12 = -STACK_FRAME_SIZE, r12
 
     /* 4. save registers in bank 0 into memory stack */	
-	st8 [r31] = r29, -8 ;;	/* save predicate registers */
-
-	st8 [r31] = r24, -8 ;;	/* save cr.iip */
-	st8 [r31] = r25, -8 ;;	/* save cr.ipsr */
-	st8 [r31] = r26, -8 ;;	/* save cr.iipa */
-	st8 [r31] = r27, -8 ;;	/* save cr.isr */
-	st8 [r31] = r28, -8	/* save cr.ifa */		
+	st8 [r31] = r30, -8 ;;		/* save old stack pointer */ 
+	
+	st8 [r31] = r29, -8 ;;		/* save predicate registers */
+
+	st8 [r31] = r24, -8 ;;		/* save cr.iip */
+	st8 [r31] = r25, -8 ;;		/* save cr.ipsr */
+	st8 [r31] = r26, -8 ;;		/* save cr.iipa */
+	st8 [r31] = r27, -8 ;;		/* save cr.isr */
+	st8 [r31] = r28, -8 ;;		/* save cr.ifa */
 
     /* 5. RSE switch from interrupted context */
@@ -104,6 +131,6 @@
 	mov r26 = cr.ifs
 	
-	st8 [r31] = r24, -8;;	/* save ar.rsc */
-	st8 [r31] = r25, -8;;	/* save ar.pfs */
+	st8 [r31] = r24, -8 ;;	/* save ar.rsc */
+	st8 [r31] = r25, -8 ;;	/* save ar.pfs */
 	st8 [r31] = r26, -8	/* save ar.ifs */
 	
@@ -121,5 +148,5 @@
 	st8 [r31] = r27, -8 ;;	/* save ar.rnat */
 	st8 [r31] = r28, -8 ;;	/* save ar.bspstore */
-	st8 [r31] = r29, -8	/* save ar.bsp */
+	st8 [r31] = r29, -8 	/* save ar.bsp */
 	
 	mov ar.rsc = r24	/* restore RSE's setting */
@@ -175,9 +202,9 @@
 
     /* 18. restore predicate registers from memory stack */
-	ld8 r29 = [r31] , -8 ;;	/* load predicate registers */
+	ld8 r29 = [r31], +8 ;;	/* load predicate registers */
 	mov pr = r29
 	
     /* 19. return from interruption */
-    	add r12 = STACK_FRAME_SIZE, r12
+    	ld8 r12 = [r31]		/* load stack pointer */ 
 	rfi ;;
 
Index: arch/ia64/src/proc/scheduler.c
===================================================================
--- arch/ia64/src/proc/scheduler.c	(revision bc314be837c993a70ed30ed4372ac9aa7b16138b)
+++ arch/ia64/src/proc/scheduler.c	(revision 83d2d0e4bbabfdae355ca18dba80470da9b35e38)
@@ -31,4 +31,5 @@
 #include <arch.h>
 #include <arch/register.h>
+#include <arch/context.h>
 #include <arch/mm/tlb.h>
 #include <config.h>
@@ -58,5 +59,5 @@
 		"mov r23 = %0\n"
 		"bsw.1\n"
-		 : : "r" (THREAD->kstack));
+		 : : "r" (&THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]));
 }
 
Index: doc/arch/ia64
===================================================================
--- doc/arch/ia64	(revision bc314be837c993a70ed30ed4372ac9aa7b16138b)
+++ doc/arch/ia64	(revision 83d2d0e4bbabfdae355ca18dba80470da9b35e38)
@@ -12,5 +12,5 @@
 
 TOOLCHAIN REQUIREMENTS
-        o binutils 2.15, 2.16
-	o gcc 4.0.0
+        o binutils 2.15, 2.16, 2.16.1
+	o gcc 4.0.0, 4.0.1
         o older versions may do as well, but are now obsoleted
