Index: arch/ia64/src/asm.S
===================================================================
--- arch/ia64/src/asm.S	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/asm.S	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -27,4 +27,6 @@
 #
 
+#include <arch/register.h>
+
 .text
 
@@ -47,2 +49,41 @@
 	}
 	br halt
+
+/** Switch to userspace - low level code.
+ *
+ * @param in0 Userspace entry point address.
+ * @param in1 Userspace stack pointer address.
+ * @param in2 Userspace register stack pointer address.
+ * @param in3 Value to be stored in IPSR.
+ * @param in4 Value to be stored in RSC.
+ */
+.global switch_to_userspace
+switch_to_userspace:
+	alloc loc0 = ar.pfs, 5, 3, 0, 0
+	rsm (PSR_IC_MASK | PSR_I_MASK)		/* disable interruption collection  and interrupts */
+	srlz.d ;;
+	srlz.i ;;
+	
+	mov cr.ipsr = in3
+	mov cr.iip = in0
+	mov r12 = in1
+
+	xor r1 = r1, r1
+	
+	mov loc1 = cr.ifs
+	movl loc2 = PFM_MASK ;;
+	and loc1 = loc2, loc1 ;;
+	mov cr.ifs = loc1 ;;			/* prevent decrementing BSP by rfi */
+
+	invala
+	
+	mov loc1 = ar.rsc ;;
+	and loc1 = ~3, loc1 ;;			
+	mov ar.rsc = loc1 ;;			/* put RSE into enforced lazy mode */
+
+	flushrs ;;
+	
+	mov ar.bspstore = in2 ;;
+	mov ar.rsc = in4 ;;
+	
+	rfi ;;
Index: arch/ia64/src/dummy.s
===================================================================
--- arch/ia64/src/dummy.s	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/dummy.s	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -31,5 +31,4 @@
 .global calibrate_delay_loop
 .global asm_delay_loop
-.global userspace
 .global cpu_sleep
 .global dummy
@@ -38,5 +37,4 @@
 .global fpu_init
 
-userspace:
 calibrate_delay_loop:
 asm_delay_loop:
Index: arch/ia64/src/ia64.c
===================================================================
--- arch/ia64/src/ia64.c	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/ia64.c	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -32,6 +32,12 @@
 #include <arch/interrupt.h>
 #include <arch/barrier.h>
+#include <arch/asm.h>
+#include <arch/register.h>
 #include <arch/types.h>
-
+#include <arch/context.h>
+#include <arch/mm/page.h>
+#include <mm/as.h>
+#include <config.h>
+#include <userspace.h>
 #include <console/console.h>
 
@@ -44,4 +50,6 @@
 	ski_init_console();
 	it_init();
+	config.init_addr = INIT_ADDRESS;
+	config.init_size = INIT_SIZE;
 }
 
@@ -54,6 +62,30 @@
 }
 
-
 void arch_post_smp_init(void)
 {
 }
+
+/** Enter userspace and never return. */
+void userspace(void)
+{
+	psr_t psr;
+	rsc_t rsc;
+
+	psr.value = psr_read();
+	psr.cpl = PL_USER;
+	psr.i = true;				/* start with interrupts enabled */
+	psr.ic = true;
+	psr.ri = 0;				/* start with instruction #0 */
+
+	__asm__ volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value));
+	rsc.loadrs = 0;
+	rsc.be = false;
+	rsc.pl = PL_USER;
+	rsc.mode = 3;				/* eager mode */
+
+	switch_to_userspace(UTEXT_ADDRESS, USTACK_ADDRESS+PAGE_SIZE-1, USTACK_ADDRESS, psr.value, rsc.value);
+
+	while (1) {
+		;
+	}
+}
Index: arch/ia64/src/ivt.S
===================================================================
--- arch/ia64/src/ivt.S	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/ivt.S	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -137,6 +137,7 @@
 	st8 [r31] = r26, -8		/* save ar.ifs */
 	
-	and r30 = ~3, r24 ;;
-	mov ar.rsc = r30 ;;		/* place RSE in enforced lazy mode */
+	and r24 = ~(RSC_PL_MASK), r24 ;;
+	and r30 = ~(RSC_MODE_MASK), r24 ;;
+	mov ar.rsc = r30 ;;		/* update RSE state */
 	
 	mov r27 = ar.rnat
@@ -163,5 +164,5 @@
 	st8 [r31] = r29, -8 		/* save ar.bsp */
 	
-	mov ar.rsc = r24		/* restore RSE's setting */
+	mov ar.rsc = r24		/* restore RSE's setting + kernel privileges */
 	
     /* steps 6 - 15 are done by heavyweight_handler_inner() */
@@ -301,4 +302,6 @@
 
     /* 10. call handler */
+    	movl r1 = _hardcoded_load_address
+    
     	mov b1 = loc2
 	br.call.sptk.many b0 = b1
Index: arch/ia64/src/mm/tlb.c
===================================================================
--- arch/ia64/src/mm/tlb.c	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/mm/tlb.c	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -64,5 +64,6 @@
  * @param entry The rest of TLB entry as required by TLB insertion format.
  */
-void dtc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry) {
+void dtc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry)
+{
 	tc_mapping_insert(va, asid, entry, true);
 }
@@ -74,5 +75,6 @@
  * @param entry The rest of TLB entry as required by TLB insertion format.
  */
-void itc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry) {
+void itc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry)
+{
 	tc_mapping_insert(va, asid, entry, false);
 }
@@ -336,5 +338,5 @@
 		}
 	}
-	
+
 	t = page_mapping_find(AS, va);
 	if (t) {
Index: arch/ia64/src/start.S
===================================================================
--- arch/ia64/src/start.S	(revision cd373bbb5fd51ad3198655cb712d3d11734ee5e1)
+++ arch/ia64/src/start.S	(revision b994a60c2699d4cf29d9c28497e8256a75eb2a1c)
@@ -125,5 +125,5 @@
 
 	# initialize gp (Global Pointer) register
-	movl r1 = _hardcoded_load_address	;;
+	movl r1 = _hardcoded_load_address
 
 	/*
@@ -132,5 +132,5 @@
 	movl r14 = _hardcoded_ktext_size
 	movl r15 = _hardcoded_kdata_size
-	movl r16 = _hardcoded_load_address
+	movl r16 = _hardcoded_load_address ;;
 	addl r17 = @gprel(hardcoded_ktext_size), gp
 	addl r18 = @gprel(hardcoded_kdata_size), gp
