Index: kernel/arch/ia64/Makefile.inc
===================================================================
--- kernel/arch/ia64/Makefile.inc	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/Makefile.inc	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -83,4 +83,5 @@
 	arch/$(ARCH)/src/proc/scheduler.c \
 	arch/$(ARCH)/src/ddi/ddi.c \
+	arch/$(ARCH)/src/smp/smp.c \
 	arch/$(ARCH)/src/drivers/it.c
 
@@ -99,2 +100,6 @@
 endif
 
+ifeq ($(CONFIG_SMP),y)
+	DEFS += -DCONFIG_SMP
+endif
+
Index: kernel/arch/ia64/include/atomic.h
===================================================================
--- kernel/arch/ia64/include/atomic.h	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/include/atomic.h	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -52,4 +52,18 @@
 }
 
+
+static inline uint64_t test_and_set(atomic_t *val) {
+	uint64_t v;
+		
+	asm volatile (
+		"movl %0=0x01;;\n"
+		"xchg8 %0=%1,%0;;\n"
+		: "=r" (v),"+m" (val->count)
+	);
+	
+	return v;
+}
+
+
 static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); }
 static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); }
Index: kernel/arch/ia64/include/bootinfo.h
===================================================================
--- kernel/arch/ia64/include/bootinfo.h	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/include/bootinfo.h	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -30,5 +30,5 @@
 #define KERN_ia64_BOOTINFO_H_
 
-
+#define BOOTINFO_ADDRESS 0x4401000
 
 #define CONFIG_INIT_TASKS	32
@@ -47,4 +47,8 @@
 typedef struct {
 	binit_t taskmap;
+
+	unsigned long * sapic;
+	unsigned int wakeup_intno;
+
 } bootinfo_t;
 
Index: kernel/arch/ia64/include/cpu.h
===================================================================
--- kernel/arch/ia64/include/cpu.h	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/include/cpu.h	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -39,4 +39,5 @@
 #include <arch/register.h>
 #include <arch/asm.h>
+#include <arch/bootinfo.h>
 
 #define FAMILY_ITANIUM	0x7
@@ -64,4 +65,31 @@
 }
 
+
+#define CR64_ID_SHIFT 24
+#define CR64_ID_MASK 0xff000000
+#define CR64_EID_SHIFT 16
+#define CR64_EID_MASK 0xff0000
+
+static inline int ia64_get_cpu_id(void)
+{
+	uint64_t cr64=cr64_read();
+	return ((CR64_ID_MASK)&cr64)>>CR64_ID_SHIFT;
+}
+
+static inline int ia64_get_cpu_eid(void)
+{
+	uint64_t cr64=cr64_read();
+	return ((CR64_EID_MASK)&cr64)>>CR64_EID_SHIFT;
+}
+
+
+
+static inline void ipi_send_ipi(int id,int eid,int intno)
+{
+	(bootinfo->sapic)[2*(id*256+eid)]=intno;
+}
+
+
+
 #endif
 
Index: kernel/arch/ia64/include/mm/page.h
===================================================================
--- kernel/arch/ia64/include/mm/page.h	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/include/mm/page.h	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -47,4 +47,16 @@
 #define KERNEL_PAGE_WIDTH		28	/* 256M */
 #define IO_PAGE_WIDTH			26	/* 64M */
+#define FW_PAGE_WIDTH			28	/* 256M */
+
+/** Staticly mapped IO spaces */
+
+/* Firmware area (bellow 4GB in phys mem) */
+#define FW_OFFSET             0x00000000F0000000
+/* Legacy IO space */
+#define IO_OFFSET             0x0001000000000000
+/* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000*/
+#define VIO_OFFSET            0x0002000000000000
+
+
 
 
Index: kernel/arch/ia64/src/drivers/it.c
===================================================================
--- kernel/arch/ia64/src/drivers/it.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/src/drivers/it.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -56,12 +56,15 @@
 {
 	cr_itv_t itv;
-
-	irq_initialize(&it_irq);
-	it_irq.inr = INTERRUPT_TIMER;
-	it_irq.devno = device_assign_devno();
-	it_irq.claim = it_claim;
-	it_irq.handler = it_interrupt;
-	irq_register(&it_irq);
-
+	
+	if(config.cpu_active==1)
+	{
+		irq_initialize(&it_irq);
+		it_irq.inr = INTERRUPT_TIMER;
+		it_irq.devno = device_assign_devno();
+		it_irq.claim = it_claim;
+		it_irq.handler = it_interrupt;
+		irq_register(&it_irq);
+	}
+	
 	/* initialize Interval Timer external interrupt vector */
 	itv.value = itv_read();
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/src/ia64.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -55,4 +55,14 @@
 #include <arch/bootinfo.h>
 #include <genarch/kbd/i8042.h>
+#include <genarch/kbd/ns16550.h>
+#include <smp/smp.h>
+#include <smp/ipi.h>
+#include <arch/atomic.h>
+#include <panic.h>
+#include <print.h>
+
+/*NS16550 as a COM 1*/
+#define NS16550_IRQ 4
+#define NS16550_PORT 0x3f8
 
 bootinfo_t *bootinfo;
@@ -103,10 +113,13 @@
 void arch_post_mm_init(void)
 {
-	irq_init(INR_COUNT, INR_COUNT);
-#ifdef SKI
-	ski_init_console();
+	if(config.cpu_active==1)
+	{
+		irq_init(INR_COUNT, INR_COUNT);
+#ifdef SKI
+		ski_init_console();
 #else	
-	ega_init();
+		ega_init();
 #endif	
+	}
 	it_init();	
 }
@@ -128,4 +141,7 @@
 	while (1) {
 		i8042_poll();
+#ifdef CONFIG_NS16550
+		ns16550_poll();
+#endif
 		thread_usleep(POLL_INTERVAL);
 	}
@@ -136,5 +152,5 @@
 {
 
-	if (config.cpu_active == 1) {
+	{
 		/*
 		 * Create thread that polls keyboard.
@@ -154,4 +170,8 @@
 		i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
 
+#ifdef CONFIG_NS16550
+		ns16550_init(kbd, NS16550_IRQ, NS16550_PORT); // as a COM 1
+#else
+#endif
 		thread_t *t;
 		t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
@@ -164,4 +184,5 @@
 	}
 }
+
 
 /** Enter userspace and never return. */
@@ -225,5 +246,5 @@
 void arch_reboot(void)
 {
-	// TODO
+	outb(0x64,0xfe);
 	while (1);
 }
Index: kernel/arch/ia64/src/mm/frame.c
===================================================================
--- kernel/arch/ia64/src/mm/frame.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/src/mm/frame.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -43,18 +43,29 @@
  */
 #define MEMORY_SIZE	(64 * 1024 * 1024)
-#define MEMORY_BASE	(64 * 1024 * 1024)
+#define MEMORY_BASE	(0 * 64 * 1024 * 1024)
+
+#define ONE_TO_ONE_MAPPING_SIZE (256*1048576) // Mapped at start
 
 #define ROM_BASE	0xa0000               //For ski
 #define ROM_SIZE	(384 * 1024)          //For ski
 void poke_char(int x,int y,char ch, char c);
+
+uintptr_t last_frame;
+
 void frame_arch_init(void)
 {
-	zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0);
+
+	if(config.cpu_active==1)
+	{
+		zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0);
 	
-	/*
-	 * Blacklist ROM regions.
-	 */
-	frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE));
-	
+		/*
+		* Blacklist ROM regions.
+		*/
+		//frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE));
+
+		frame_mark_unavailable(ADDR2PFN(0), SIZE2FRAMES(1048576));
+		last_frame=SIZE2FRAMES((VRN_KERNEL<<VRN_SHIFT)+ONE_TO_ONE_MAPPING_SIZE);	
+	}	
 }
 
Index: kernel/arch/ia64/src/mm/page.c
===================================================================
--- kernel/arch/ia64/src/mm/page.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/src/mm/page.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -48,4 +48,5 @@
 #include <arch/barrier.h>
 #include <memstr.h>
+#include <align.h>
 
 static void set_environment(void);
@@ -263,4 +264,26 @@
 }
 
+extern uintptr_t last_frame;
+
+
+uintptr_t hw_map(uintptr_t physaddr, size_t size)
+{
+	if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
+		panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
+	
+	uintptr_t virtaddr = PA2KA(last_frame);
+	pfn_t i;
+	for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) {
+		uintptr_t addr = PFN2ADDR(i);
+		page_mapping_insert(AS_KERNEL, virtaddr + addr, physaddr + addr, PAGE_NOT_CACHEABLE | PAGE_WRITE);
+	}
+	
+	last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
+	
+	return virtaddr;
+}
+
+
+
 /** @}
  */
Index: kernel/arch/ia64/src/smp/smp.c
===================================================================
--- kernel/arch/ia64/src/smp/smp.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
+++ kernel/arch/ia64/src/smp/smp.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2005 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ia64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch.h>
+#include <arch/ski/ski.h>
+#include <arch/drivers/it.h>
+#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/stack.h>
+#include <arch/mm/page.h>
+#include <mm/as.h>
+#include <config.h>
+#include <userspace.h>
+#include <console/console.h>
+#include <proc/uarg.h>
+#include <syscall/syscall.h>
+#include <ddi/irq.h>
+#include <ddi/device.h>
+#include <arch/drivers/ega.h>
+#include <arch/bootinfo.h>
+#include <genarch/kbd/i8042.h>
+#include <genarch/kbd/ns16550.h>
+#include <smp/smp.h>
+#include <smp/ipi.h>
+#include <arch/atomic.h>
+#include <panic.h>
+#include <print.h>
+
+
+
+
+
+
+#ifdef CONFIG_SMP
+
+
+extern char cpu_by_id_eid_list[256][256];
+
+
+static void sapic_init(void)
+{
+	bootinfo->sapic=(unative_t *)(PA2KA((unative_t)(bootinfo->sapic))|FW_OFFSET);
+}
+
+
+
+static void ipi_broadcast_arch_all(int ipi )
+{
+	int id,eid;
+	int myid,myeid;
+	
+	myid=ia64_get_cpu_id();
+	myeid=ia64_get_cpu_eid();
+
+	printf("Not sending to ID:%d,EID:%d",myid,myeid);
+	
+	for(id=0;id<256;id++)
+		for(eid=0;eid<256;eid++)
+			if((id!=myid) || (eid!=myeid))
+				ipi_send_ipi(id,eid,ipi);
+}
+
+void ipi_broadcast_arch(int ipi )
+{
+	ipi_broadcast_arch_all(ipi);
+}
+
+
+void smp_init(void)
+{
+	sapic_init();
+	ipi_broadcast_arch_all(bootinfo->wakeup_intno);	
+	volatile long long brk;
+        for(brk=0;brk<100LL*1024LL*1024LL;brk++); //wait a while before CPUs starts
+
+	config.cpu_count=0;
+	int id,eid;
+	
+	for(id=0;id<256;id++)
+		for(eid=0;eid<256;eid++)
+		        if(cpu_by_id_eid_list[id][eid]==1){
+		    		config.cpu_count++;
+		    		printf("Found CPU ID:%d EDI:%d\n",id,eid);
+		    		cpu_by_id_eid_list[id][eid]=2;
+
+			}
+}
+
+
+void kmp(void *arg __attribute__((unused)))
+{
+	int id,eid;
+	int myid,myeid;
+	
+	myid=ia64_get_cpu_id();
+	myeid=ia64_get_cpu_eid();
+
+	for(id=0;id<256;id++)
+		for(eid=0;eid<256;eid++)
+		        if((id!=myid) || (eid!=myeid))
+		        	if(cpu_by_id_eid_list[id][eid]!=0){
+		    			if(cpu_by_id_eid_list[id][eid]==1){
+		    		
+			    			//config.cpu_count++;
+				    		//cpu_by_id_eid_list[id][eid]=2;
+				    		printf("Found Late CPU ID:%d EDI:%d Not added to system!!!\n",id,eid);
+				    		continue;
+			    			}
+					cpu_by_id_eid_list[id][eid]=3;
+					/*
+					 * There may be just one AP being initialized at
+					 * the time. After it comes completely up, it is
+					 * supposed to wake us up.
+					 */
+					if (waitq_sleep_timeout(&ap_completion_wq, 1000000,
+					    SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) {
+						printf("%s: waiting for cpu ID:%d EID:%d"
+						    "timed out\n", __FUNCTION__, 
+						    id, eid);
+					    }    
+		
+				}
+}
+#endif
+
+
+/*This is just a hack for linking with assembler - may be removed in future*/
+#ifndef CONFIG_SMP
+void main_ap(void);
+void main_ap(void)
+{
+	while(1);
+}
+
+#endif
+
+/** @}
+ */
+
Index: kernel/arch/ia64/src/start.S
===================================================================
--- kernel/arch/ia64/src/start.S	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/arch/ia64/src/start.S	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -40,7 +40,5 @@
 #define KERNEL_TRANSLATION_VIO 0x0010000000000671
 #define KERNEL_TRANSLATION_IO 0x00100FFFFC000671 
-#define VIO_OFFSET            0x0002000000000000
-
-#define IO_OFFSET             0x0001000000000000
+#define KERNEL_TRANSLATION_FW 0x00100000F0000671 
 
 
@@ -53,4 +51,16 @@
 kernel_image_start:
 	.auto
+
+#identifi self(CPU) in OS structures by ID / EID
+	mov r9=cr64
+	mov r10=1
+	movl r12=0xffffffff
+	movl r8=cpu_by_id_eid_list
+	and r8=r8,r12
+	shr r9=r9,16
+	add r8=r8,r9
+	st1 [r8]=r10
+
+
 
 	mov psr.l = r0
@@ -113,4 +123,21 @@
 	movl r10 = (KERNEL_TRANSLATION_IO)
 	itr.d dtr[r7] = r10
+
+
+#setup mapping for fimware arrea (also SAPIC)
+	mov r11 = cr.itir ;;
+	movl r10 = ~0xfc;;
+	and r10 =r10 , r11  ;;
+	movl r11 = (FW_PAGE_WIDTH << PS_SHIFT);;
+	or r10 =r10 , r11  ;;
+	mov cr.itir = r10;;
+
+
+	movl r7 = 3
+	movl r8 = (VRN_KERNEL << VRN_SHIFT) | FW_OFFSET
+	mov cr.ifa = r8
+	movl r10 = (KERNEL_TRANSLATION_FW)
+	itr.d dtr[r7] = r10
+
 
 
@@ -143,4 +170,10 @@
 	# switch to register bank 1
 	bsw.1
+
+#Am'I BSP or AP
+	movl r20=bsp_started;;
+	ld8 r20=[r20];;
+	cmp.eq p3,p2=r20,r0;;
+
 	
 	# initialize register stack
@@ -161,18 +194,18 @@
 	
 	/*
-	 * Initialize hardcoded_* variables.
+	 * Initialize hardcoded_* variables. Do only BSP
 	 */
-	movl r14 = _hardcoded_ktext_size
-	movl r15 = _hardcoded_kdata_size
-	movl r16 = _hardcoded_load_address ;;
-	addl r17 = @gprel(hardcoded_ktext_size), gp
-	addl r18 = @gprel(hardcoded_kdata_size), gp
-	addl r19 = @gprel(hardcoded_load_address), gp
-	addl r21 = @gprel(bootinfo), gp
+(p3)	movl r14 = _hardcoded_ktext_size
+(p3)	movl r15 = _hardcoded_kdata_size
+(p3)	movl r16 = _hardcoded_load_address ;;
+(p3)	addl r17 = @gprel(hardcoded_ktext_size), gp
+(p3)	addl r18 = @gprel(hardcoded_kdata_size), gp
+(p3)	addl r19 = @gprel(hardcoded_load_address), gp
+(p3)	addl r21 = @gprel(bootinfo), gp
 	;;
-	st8 [r17] = r14
-	st8 [r18] = r15
-	st8 [r19] = r16
-	st8 [r21] = r20
+(p3)	st8 [r17] = r14
+(p3)	st8 [r18] = r15
+(p3)	st8 [r19] = r16
+(p3)	st8 [r21] = r20
 
 	ssm (1 << 19) ;; /* Disable f32 - f127 */
@@ -180,4 +213,14 @@
 	srlz.d ;;
 
+(p2)	movl r18 = main_ap ;;
+(p2)   	mov b1 = r18 ;;
+(p2)	br.call.sptk.many b0 = b1
+
+#Mark that BSP is on
+	mov r20=1;;
+	movl r21=bsp_started;;
+	st8 [r21]=r20;;
+
+
 	br.call.sptk.many b0 = arch_pre_main
 
@@ -189,2 +232,45 @@
 0:
 	br 0b
+.align 4096
+
+kernel_image_ap_start:
+	.auto
+#identifi self(CPU) in OS structures by ID / EID
+	mov r9=cr64
+	mov r10=1
+	movl r12=0xffffffff
+	movl r8=cpu_by_id_eid_list
+	and r8=r8,r12
+	shr r9=r9,16
+	add r8=r8,r9
+	st1 [r8]=r10
+	
+#wait for wakeup sychro signal (#3 in cpu_by_id_eid_list)
+kernel_image_ap_start_loop:
+	movl r11=kernel_image_ap_start_loop
+	and r11=r11,r12
+   	mov b1 = r11 
+
+	ld1 r20=[r8];;
+	movl r21=3;;
+	cmp.eq p2,p3=r20,r21;;
+(p3)br.call.sptk.many b0 = b1
+
+	movl r11=kernel_image_start
+	and r11=r11,r12
+    mov b1 = r11 
+	br.call.sptk.many b0 = b1
+
+
+.align 16
+.global bsp_started
+bsp_started:
+.space 8
+
+
+.align 4096
+.global cpu_by_id_eid_list
+cpu_by_id_eid_list:
+.space 65536
+
+
Index: kernel/generic/include/synch/spinlock.h
===================================================================
--- kernel/generic/include/synch/spinlock.h	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/generic/include/synch/spinlock.h	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -37,4 +37,5 @@
 
 #include <arch/types.h>
+#include <arch/barrier.h>
 #include <preemption.h>
 #include <atomic.h>
Index: kernel/generic/src/mm/tlb.c
===================================================================
--- kernel/generic/src/mm/tlb.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/generic/src/mm/tlb.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -135,5 +135,7 @@
 void tlb_shootdown_ipi_send(void)
 {
+#ifndef ia64
 	ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
+#endif	
 }
 
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision a2a552922110e12b1296ecc23f36d826e7fc4040)
+++ kernel/generic/src/proc/thread.c	(revision 59e4864a51a79cbe1c491a3c86539b884e9005e6)
@@ -296,5 +296,4 @@
 	if (!t)
 		return NULL;
-	
 	/* Not needed, but good for debugging */
 	memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
