Index: Makefile
===================================================================
--- Makefile	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ Makefile	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -69,4 +69,7 @@
 ifeq ($(CONFIG_DEBUG_SPINLOCK),y)
 	DEFS += -DCONFIG_DEBUG_SPINLOCK
+endif
+ifeq ($(CONFIG_DEBUG_AS_WATCHPOINT),y)
+	DEFS += -DCONFIG_DEBUG_AS_WATCHPOINT
 endif
 ifeq ($(CONFIG_FPU_LAZY),y)
@@ -136,5 +139,6 @@
 	generic/src/smp/ipi.c \
 	generic/src/ipc/ipc.c \
-	generic/src/ipc/sysipc.c
+	generic/src/ipc/sysipc.c \
+	generic/src/ipc/ipcrsc.c
 
 ## Test sources
Index: arch/amd64/Makefile.inc
===================================================================
--- arch/amd64/Makefile.inc	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/Makefile.inc	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -104,5 +104,6 @@
 	arch/$(ARCH)/src/proc/scheduler.c \
 	arch/$(ARCH)/src/userspace.c \
-	arch/$(ARCH)/src/syscall.c
+	arch/$(ARCH)/src/syscall.c \
+	arch/$(ARCH)/src/debugger.c
 
 ifeq ($(CONFIG_SMP),y)
Index: arch/amd64/include/asm.h
===================================================================
--- arch/amd64/include/asm.h	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/include/asm.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -142,54 +142,4 @@
 }
 
-/** Read CR0
- *
- * Return value in CR0
- *
- * @return Value read.
- */
-static inline __u64 read_cr0(void) 
-{ 
-	__u64 v; 
-	__asm__ volatile ("movq %%cr0,%0\n" : "=r" (v)); 
-	return v; 
-}
-
-/** Read CR2
- *
- * Return value in CR2
- *
- * @return Value read.
- */
-static inline __u64 read_cr2(void) 
-{ 
-	__u64 v; 
-	__asm__ volatile ("movq %%cr2,%0\n" : "=r" (v)); 
-	return v; 
-}
-
-/** Write CR3
- *
- * Write value to CR3.
- *
- * @param v Value to be written.
- */
-static inline void write_cr3(__u64 v) 
-{ 
-	__asm__ volatile ("movq %0,%%cr3\n" : : "r" (v)); 
-}
-
-/** Read CR3
- *
- * Return value in CR3
- *
- * @return Value read.
- */
-static inline __u64 read_cr3(void) 
-{ 
-	__u64 v;
-	__asm__ volatile ("movq %%cr3,%0" : "=r" (v)); 
-	return v; 
-}
-
 /** Write to MSR */
 static inline void write_msr(__u32 msr, __u64 value)
@@ -251,4 +201,36 @@
 }
 
+#define GEN_READ_REG(reg) static inline __native read_ ##reg (void) \
+    { \
+	__native res; \
+	__asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \
+	return res; \
+    }
+
+#define GEN_WRITE_REG(reg) static inline void write_ ##reg (__native regn) \
+    { \
+	__asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \
+    }
+
+GEN_READ_REG(cr0);
+GEN_READ_REG(cr2);
+GEN_READ_REG(cr3);
+GEN_WRITE_REG(cr3);
+
+GEN_READ_REG(dr0);
+GEN_READ_REG(dr1);
+GEN_READ_REG(dr2);
+GEN_READ_REG(dr3);
+GEN_READ_REG(dr6);
+GEN_READ_REG(dr7);
+
+GEN_WRITE_REG(dr0);
+GEN_WRITE_REG(dr1);
+GEN_WRITE_REG(dr2);
+GEN_WRITE_REG(dr3);
+GEN_WRITE_REG(dr6);
+GEN_WRITE_REG(dr7);
+
+
 extern size_t interrupt_handler_size;
 extern void interrupt_handlers(void);
Index: arch/amd64/include/cpu.h
===================================================================
--- arch/amd64/include/cpu.h	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/include/cpu.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -30,4 +30,5 @@
 #define __amd64_CPU_H__
 
+#define RFLAGS_RF       (1 << 16)
 
 #define EFER_MSR_NUM    0xc0000080
Index: arch/amd64/include/debugger.h
===================================================================
--- arch/amd64/include/debugger.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
+++ arch/amd64/include/debugger.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * 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.
+ */
+
+#ifndef __amd64_DEBUGGER_H__
+#define __amd64_DEBUGGER_H__
+
+#include <arch/types.h>
+
+#define BKPOINTS_MAX 4
+
+/* Flags that are passed to breakpoint_add function */
+#define BKPOINT_INSTR        0x1
+#define BKPOINT_WRITE        0x2 
+#define BKPOINT_READ_WRITE   0x4
+
+#define BKPOINT_CHECK_ZERO   0x8
+
+
+extern void debugger_init(void);
+extern int breakpoint_add(void * where, int flags);
+extern void breakpoint_del(int slot);
+
+#endif
Index: arch/amd64/include/interrupt.h
===================================================================
--- arch/amd64/include/interrupt.h	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/include/interrupt.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -54,4 +54,5 @@
 #endif
 
+#define VECTOR_DEBUG            1
 #define VECTOR_PIC_SPUR		(IVT_IRQBASE+IRQ_PIC_SPUR)
 #define VECTOR_CLK		(IVT_IRQBASE+IRQ_CLK)
Index: arch/amd64/src/amd64.c
===================================================================
--- arch/amd64/src/amd64.c	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/src/amd64.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -47,4 +47,5 @@
 #include <interrupt.h>
 #include <arch/syscall.h>
+#include <arch/debugger.h>
 
 /** Disable I/O on non-privileged levels
@@ -130,8 +131,10 @@
 	if (config.cpu_active == 1) {
 		ega_init();	/* video */
+		/* Enable debugger */
+		debugger_init();
 	}
 	/* Setup fast SYSCALL/SYSRET */
 	syscall_setup_cpu();
-
+	
 }
 
Index: arch/amd64/src/debugger.c
===================================================================
--- arch/amd64/src/debugger.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
+++ arch/amd64/src/debugger.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * 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.
+ */
+
+#include <arch/debugger.h>
+#include <console/kconsole.h>
+#include <console/cmd.h>
+#include <symtab.h>
+#include <print.h>
+#include <panic.h>
+#include <interrupt.h>
+#include <arch/asm.h>
+#include <arch/cpu.h>
+#include <debug.h>
+#include <func.h>
+
+typedef struct  {
+	__address address;      /**< Breakpoint address */
+	int flags;              /**< Flags regarding breakpoint */
+	int counter;            /**< How many times the exception occured */
+} bpinfo_t;
+
+static bpinfo_t breakpoints[BKPOINTS_MAX];
+SPINLOCK_INITIALIZE(bkpoint_lock);
+
+static int cmd_print_breakpoints(cmd_arg_t *argv);
+static cmd_info_t bkpts_info = {
+	.name = "bkpts",
+	.description = "Print breakpoint table.",
+	.func = cmd_print_breakpoints,
+	.argc = 0,
+};
+
+static int cmd_del_breakpoint(cmd_arg_t *argv);
+static cmd_arg_t del_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t delbkpt_info = {
+	.name = "delbkpt",
+	.description = "delbkpt <number> - Delete breakpoint.",
+	.func = cmd_del_breakpoint,
+	.argc = 1,
+	.argv = &del_argv
+};
+
+static int cmd_add_breakpoint(cmd_arg_t *argv);
+static cmd_arg_t add_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t addbkpt_info = {
+	.name = "addbkpt",
+	.description = "addbkpt <&symbol> - new breakpoint.",
+	.func = cmd_add_breakpoint,
+	.argc = 1,
+	.argv = &add_argv
+};
+
+static cmd_arg_t addw_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t addwatchp_info = {
+	.name = "addwatchp",
+	.description = "addbwatchp <&symbol> - new write watchpoint.",
+	.func = cmd_add_breakpoint,
+	.argc = 1,
+	.argv = &addw_argv
+};
+
+
+/** Print table of active breakpoints */
+int cmd_print_breakpoints(cmd_arg_t *argv)
+{
+	int i;
+	char *symbol;
+
+	printf("Breakpoint table.\n");
+	for (i=0; i < BKPOINTS_MAX; i++)
+		if (breakpoints[i].address) {
+			symbol = get_symtab_entry(breakpoints[i].address);
+			printf("%d. 0x%p in %s\n",i,
+			       breakpoints[i].address, symbol);
+			printf("     Count(%d) ", breakpoints[i].counter);
+			printf("\n");
+		}
+	return 1;
+}
+
+/** Enable hardware breakpoint
+ *
+ *
+ * @param where Address of HW breakpoint
+ * @param flags Type of breakpoint (EXECUTE, WRITE)
+ * @return Debug slot on success, -1 - no available HW breakpoint
+ */
+int breakpoint_add(void * where, int flags)
+{
+	bpinfo_t *cur = NULL;
+	int curidx;
+	ipl_t ipl;
+	int i;
+	__native dr7;
+
+	ASSERT( flags & (BKPOINT_INSTR | BKPOINT_WRITE | BKPOINT_READ_WRITE));
+
+	ipl = interrupts_disable();
+	spinlock_lock(&bkpoint_lock);
+	
+	/* Find free space in slots */
+	for (i=0; i<BKPOINTS_MAX; i++)
+		if (!breakpoints[i].address) {
+			cur = &breakpoints[i];
+			curidx = i;
+			break;
+		}
+	if (!cur) {
+		/* Too many breakpoints */
+		spinlock_unlock(&bkpoint_lock);
+		interrupts_restore(ipl);
+		return -1;
+	}
+	cur->address = (__address) where;
+	cur->flags = flags;
+	cur->counter = 0;
+
+	/* Set breakpoint to debug registers */
+	switch (curidx) {
+	case 0:
+		write_dr0(cur->address);
+		break;
+	case 1:
+		write_dr1(cur->address);
+		break;
+	case 2:
+		write_dr2(cur->address);
+		break;
+	case 3:
+		write_dr3(cur->address);
+		break;
+	}
+	dr7 = read_dr7();
+	/* Set type to requested breakpoint & length*/
+	dr7 &= ~ (0x3 << (16 + 4*curidx));
+	dr7 &= ~ (0x3 << (18 + 4*curidx));
+	if ((flags & BKPOINT_INSTR)) {
+		printf("Instr breakpoint\n");
+		;
+	} else {
+		if (sizeof(int) == 4)
+			dr7 |= 0x3 << (18 + 4*curidx);
+		else /* 8 */
+			dr7 |= 0x2 << (18 + 4*curidx);
+			
+		if ((flags & BKPOINT_WRITE))
+			dr7 |= 0x1 << (16 + 4*curidx);
+		else if ((flags & BKPOINT_READ_WRITE))
+			dr7 |= 0x3 << (16 + 4*curidx);
+	}
+
+	/* Enable global breakpoint */
+	dr7 |= 0x2 << (curidx*2);
+
+	write_dr7(dr7);
+
+	spinlock_unlock(&bkpoint_lock);
+	interrupts_restore(ipl);
+
+	return curidx;
+}
+
+static void handle_exception(int slot, istate_t *istate)
+{
+	ASSERT(breakpoints[slot].address);
+
+	/* Handle zero checker */
+	if (! (breakpoints[slot].flags & BKPOINT_INSTR)) {
+		if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) {
+			if (*((__native *) breakpoints[slot].address) != 0)
+				return;
+			printf("**** Found ZERO on address %P ****\n",
+			       slot, breakpoints[slot].address);
+		} else {
+			printf("Data watchpoint - new data: %P\n",
+			       *((__native *) breakpoints[slot].address));
+		}
+	}
+	printf("Reached breakpoint %d:%P(%s)\n", slot, istate->rip,
+	       get_symtab_entry(istate->rip));
+	printf("***Type 'exit' to exit kconsole.\n");
+	atomic_set(&haltstate,1);
+	kconsole("debug");
+	atomic_set(&haltstate,0);
+}
+
+static void debug_exception(int n, istate_t *istate)
+{
+	__native dr6;
+	int i;
+	
+	/* Set RF to restart the instruction  */
+	istate->rflags |= RFLAGS_RF;
+
+	dr6 = read_dr6();
+	for (i=0; i < BKPOINTS_MAX; i++) {
+		if (dr6 & (1 << i)) {
+			dr6 &= ~ (1 << i);
+			write_dr6(dr6);
+			
+			handle_exception(i, istate);
+		}
+	}
+}
+
+void breakpoint_del(int slot)
+{
+	bpinfo_t *cur;
+	ipl_t ipl;
+	__native dr7;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&bkpoint_lock);
+
+	cur = &breakpoints[slot];
+	if (!cur->address) {
+		spinlock_unlock(&bkpoint_lock);
+		interrupts_restore(ipl);
+		return;
+	}
+
+	cur->address = NULL;
+
+	/* Disable breakpoint in DR7 */
+	dr7 = read_dr7();
+	dr7 &= ~(0x2 << (slot*2));
+	write_dr7(dr7);
+
+	spinlock_unlock(&bkpoint_lock);
+	interrupts_restore(ipl);
+}
+
+/** Remove breakpoint from table */
+int cmd_del_breakpoint(cmd_arg_t *argv)
+{
+	if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
+		printf("Invalid breakpoint number.\n");
+		return 0;
+	}
+	breakpoint_del(argv->intval);
+	return 1;
+}
+
+/** Add new breakpoint to table */
+static int cmd_add_breakpoint(cmd_arg_t *argv)
+{
+	int flags;
+
+	if (argv == &add_argv) {
+		flags = BKPOINT_INSTR;
+	} else { /* addwatchp */
+		flags = BKPOINT_WRITE;
+	}
+	printf("Adding breakpoint on address: %p\n", argv->intval);
+	if (breakpoint_add((void *)argv->intval, flags))
+		printf("Add breakpoint failed.\n");
+	
+	return 1;
+}
+
+/** Initialize debugger */
+void debugger_init()
+{
+	int i;
+
+	for (i=0; i<BKPOINTS_MAX; i++)
+		breakpoints[i].address = NULL;
+	
+	cmd_initialize(&bkpts_info);
+	if (!cmd_register(&bkpts_info))
+		panic("could not register command %s\n", bkpts_info.name);
+
+	cmd_initialize(&delbkpt_info);
+	if (!cmd_register(&delbkpt_info))
+		panic("could not register command %s\n", delbkpt_info.name);
+
+	cmd_initialize(&addbkpt_info);
+	if (!cmd_register(&addbkpt_info))
+		panic("could not register command %s\n", addbkpt_info.name);
+
+	cmd_initialize(&addwatchp_info);
+	if (!cmd_register(&addwatchp_info))
+		panic("could not register command %s\n", addwatchp_info.name);
+	
+	exc_register(VECTOR_DEBUG, "debugger",
+		     debug_exception);
+}
Index: arch/amd64/src/proc/scheduler.c
===================================================================
--- arch/amd64/src/proc/scheduler.c	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ arch/amd64/src/proc/scheduler.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -33,4 +33,5 @@
 #include <arch/context.h>	/* SP_DELTA */
 #include <arch/asm.h>
+#include <arch/debugger.h>
 
 void before_thread_runs_arch(void)
@@ -43,4 +44,14 @@
 		  (__u64)&THREAD->kstack);
 	swapgs();
+
+
+#ifdef CONFIG_DEBUG_AS_WATCHPOINT
+	/* Set watchpoint on AS to ensure that nobody sets it to zero */
+	static int old_slot = -1;
+	if (old_slot >=0)
+		breakpoint_del(old_slot);
+	old_slot = breakpoint_add(&((the_t *) THREAD->kstack)->as, 
+				  BKPOINT_WRITE | BKPOINT_CHECK_ZERO);
+#endif
 }
 
Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ generic/include/ipc/ipc.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -177,4 +177,5 @@
 
 extern answerbox_t *ipc_phone_0;
+extern void ipc_cleanup(task_t *task);
 
 #endif
Index: generic/include/ipc/ipcrsc.h
===================================================================
--- generic/include/ipc/ipcrsc.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
+++ generic/include/ipc/ipcrsc.h	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * 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.
+ */
+
+#ifndef __IPCRSC_H__
+#define __IPCRSC_H__
+
+call_t * get_call(__native callid);
+phone_t * get_phone_and_lock(__native phoneid);
+int phone_alloc(void);
+void phone_dealloc(int phoneid);
+void phone_connect(int phoneid, answerbox_t *box);
+
+
+#endif
Index: generic/src/console/cmd.c
===================================================================
--- generic/src/console/cmd.c	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ generic/src/console/cmd.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -303,12 +303,4 @@
 };
 
-static int cmd_hello(cmd_arg_t *argv);
-static cmd_info_t hello_info = {
-	.name = "hello",
-	.description = "Hello Message",
-	.func = cmd_hello,
-	.argc = 0
-};
-
 /** Data and methods for 'cpus' command. */
 static int cmd_cpus(cmd_arg_t *argv);
@@ -353,5 +345,4 @@
 	&zones_info,
 	&zone_info,
-	&hello_info,
 	NULL
 };
@@ -706,9 +697,2 @@
 	return 1;
 }
-
-
-int cmd_hello(cmd_arg_t *argv)
-{
-	printf("\nHello, World !!!\n");
-	return 1;
-}
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ generic/src/ipc/ipc.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -244,2 +244,12 @@
 					  NULL, NULL, 0);
 }
+
+/** Cleans up all IPC communication of the given task
+ *
+ *
+ */
+void ipc_cleanup(task_t *task)
+{
+	/* Cancel all calls in my dispatch queue */
+	
+}
Index: generic/src/ipc/ipcrsc.c
===================================================================
--- generic/src/ipc/ipcrsc.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
+++ generic/src/ipc/ipcrsc.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * 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.
+ */
+
+/* IPC resources management
+ *
+ * The goal of this source code is to properly manage IPC resources
+ * and allow straight and clean clean-up procedure upon task termination.
+ *
+ * The pattern of usage of the resources is:
+ * - allocate empty phone slot, connect | deallocate slot
+ * - disconnect connected phone (some messages might be on the fly)
+ * - find phone in slot and send a message using phone
+ * - answer message to phone
+ * 
+ * 
+ */
+
+#include <synch/spinlock.h>
+#include <ipc/ipc.h>
+#include <arch.h>
+#include <proc/task.h>
+#include <ipc/ipcrsc.h>
+#include <debug.h>
+
+/** Find call_t * in call table according to callid
+ *
+ * @return NULL on not found, otherwise pointer to call structure
+ */
+call_t * get_call(__native callid)
+{
+	/* TODO: Traverse list of dispatched calls and find one */
+	/* TODO: locking of call, ripping it from dispatched calls etc.  */
+	return (call_t *) callid;
+}
+
+/** Return pointer to phone identified by phoneid or NULL if non-existent */
+phone_t * get_phone_and_lock(__native phoneid)
+{
+	phone_t *phone;
+
+	if (phoneid >= IPC_MAX_PHONES)
+		return NULL;
+
+	phone = &TASK->phones[phoneid];
+	spinlock_lock(&phone->lock);
+	if (!phone->callee) {
+		spinlock_unlock(&phone->lock);
+		return NULL;
+	}
+	return phone;
+}
+
+/** Allocate new phone slot in current TASK structure */
+int phone_alloc(void)
+{
+	int i;
+
+	spinlock_lock(&TASK->lock);
+	
+	for (i=0; i < IPC_MAX_PHONES; i++) {
+		if (!TASK->phones[i].busy) {
+			TASK->phones[i].busy = 1;
+			break;
+		}
+	}
+	spinlock_unlock(&TASK->lock);
+
+	if (i >= IPC_MAX_PHONES)
+		return -1;
+	return i;
+}
+
+/** Disconnect phone */
+void phone_dealloc(int phoneid)
+{
+	spinlock_lock(&TASK->lock);
+
+	ASSERT(TASK->phones[phoneid].busy);
+
+	if (TASK->phones[phoneid].callee)
+		ipc_phone_destroy(&TASK->phones[phoneid]);
+
+	TASK->phones[phoneid].busy = 0;
+	spinlock_unlock(&TASK->lock);
+}
+
+void phone_connect(int phoneid, answerbox_t *box)
+{
+	phone_t *phone = &TASK->phones[phoneid];
+	
+	ipc_phone_connect(phone, box);
+}
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ generic/src/ipc/sysipc.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -36,4 +36,5 @@
 #include <ipc/ipc.h>
 #include <ipc/sysipc.h>
+#include <ipc/ipcrsc.h>
 
 
@@ -63,70 +64,4 @@
 {
 	return 1;
-}
-
-/** Find call_t * in call table according to callid
- *
- * @return NULL on not found, otherwise pointer to call structure
- */
-static inline call_t * get_call(__native callid)
-{
-	/* TODO: Traverse list of dispatched calls and find one */
-	/* TODO: locking of call, ripping it from dispatched calls etc.  */
-	return (call_t *) callid;
-}
-
-/** Return pointer to phone identified by phoneid or NULL if non-existent */
-static phone_t * get_phone(__native phoneid)
-{
-	phone_t *phone;
-
-	if (phoneid >= IPC_MAX_PHONES)
-		return NULL;
-
-	phone = &TASK->phones[phoneid];
-	if (!phone->callee)
-		return NULL;
-	return phone;
-}
-
-/** Allocate new phone slot in current TASK structure */
-static int phone_alloc(void)
-{
-	int i;
-
-	spinlock_lock(&TASK->lock);
-	
-	for (i=0; i < IPC_MAX_PHONES; i++) {
-		if (!TASK->phones[i].busy) {
-			TASK->phones[i].busy = 1;
-			break;
-		}
-	}
-	spinlock_unlock(&TASK->lock);
-
-	if (i >= IPC_MAX_PHONES)
-		return -1;
-	return i;
-}
-
-/** Disconnect phone */
-static void phone_dealloc(int phoneid)
-{
-	spinlock_lock(&TASK->lock);
-
-	ASSERT(TASK->phones[phoneid].busy);
-
-	if (TASK->phones[phoneid].callee)
-		ipc_phone_destroy(&TASK->phones[phoneid]);
-
-	TASK->phones[phoneid].busy = 0;
-	spinlock_unlock(&TASK->lock);
-}
-
-static void phone_connect(int phoneid, answerbox_t *box)
-{
-	phone_t *phone = &TASK->phones[phoneid];
-	
-	ipc_phone_connect(phone, box);
 }
 
@@ -213,10 +148,10 @@
 	phone_t *phone;
 
-	phone = get_phone(phoneid);
-	if (!phone)
-		return ENOENT;
-
 	if (is_system_method(method))
 		return EPERM;
+
+	phone = get_phone_and_lock(phoneid);
+	if (!phone)
+		return ENOENT;
 
 	ipc_call_init(&call);
@@ -238,8 +173,4 @@
 	phone_t *phone;
 
-	phone = get_phone(phoneid);
-	if (!phone)
-		return ENOENT;
-
 	ipc_call_init(&call);
 	copy_from_uspace(&call.data, question, sizeof(call.data));
@@ -248,4 +179,8 @@
 		return EPERM;
 	
+	phone = get_phone_and_lock(phoneid);
+	if (!phone)
+		return ENOENT;
+
 	ipc_call_sync(phone, &call);
 
@@ -279,8 +214,4 @@
 	phone_t *phone;
 
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
 	if (is_system_method(method))
 		return IPC_CALLRET_FATAL;
@@ -288,4 +219,8 @@
 	if (check_call_limit())
 		return IPC_CALLRET_TEMPORARY;
+
+	phone = get_phone_and_lock(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
 
 	call = ipc_call_alloc();
@@ -308,10 +243,10 @@
 	phone_t *phone;
 
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
 	if (check_call_limit())
 		return IPC_CALLRET_TEMPORARY;
+
+	phone = get_phone_and_lock(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
 
 	call = ipc_call_alloc();
@@ -345,5 +280,5 @@
 		return ENOENT;
 
-	phone = get_phone(phoneid);
+	phone = get_phone_and_lock(phoneid);
 	if (!phone) {
 		IPC_SET_RETVAL(call->data, EFORWARD);
@@ -437,8 +372,4 @@
 	phone_t *phone;
 
-	phone = get_phone(phoneid);
-	if (!phone)
-		return ENOENT;
-
 	ipc_call_init(&call);
 	IPC_SET_METHOD(call.data, IPC_M_CONNECTTOME);
@@ -446,4 +377,8 @@
 	IPC_SET_ARG2(call.data, arg2);
 	
+	phone = get_phone_and_lock(phoneid);
+	if (!phone)
+		return ENOENT;
+
 	ipc_call_sync(phone, &call);
 
@@ -467,5 +402,5 @@
 	int newphid;
 
-	phone = get_phone(phoneid);
+	phone = get_phone_and_lock(phoneid);
 	if (!phone)
 		return ENOENT;
Index: kernel.config
===================================================================
--- kernel.config	(revision 5a7d9d102f9d67cd763b1c39365a459c0ad22de8)
+++ kernel.config	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
@@ -71,4 +71,7 @@
 ! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n)
 
+# Watchpoint on rewriting AS with zero
+! [CONFIG_DEBUG=y&ARCH=amd64] CONFIG_DEBUG_AS_WATCHPOINT (y/n)
+
 ## Run-time configuration directives
 
