Index: generic/src/console/klog.c
===================================================================
--- generic/src/console/klog.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
+++ generic/src/console/klog.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -0,0 +1,102 @@
+/*
+ * 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 <mm/frame.h>
+#include <sysinfo/sysinfo.h>
+#include <console/klog.h>
+#include <print.h>
+#include <ipc/irq.h>
+
+/* Order of frame to be allocated for klog communication */
+#define KLOG_ORDER 0
+
+static char *klog;
+static int klogsize;
+static int klogpos;
+
+SPINLOCK_INITIALIZE(klog_lock);
+
+/** Initialize kernel loggin facility
+ *
+ * Allocate pages that are to be shared if uspace for console data
+ */
+void klog_init(void)
+{
+	void *faddr;
+
+	faddr = (void *)PFN2ADDR(frame_alloc(KLOG_ORDER, FRAME_ATOMIC));
+	if (!faddr)
+		panic("Cannot allocate page for klog");
+	klog = (char *)PA2KA(faddr);
+	
+	sysinfo_set_item_val("klog.faddr", NULL, (__native)faddr);
+	sysinfo_set_item_val("klog.pages", NULL, 1 << KLOG_ORDER);
+
+	klogsize = PAGE_SIZE << KLOG_ORDER;
+	klogpos = 0;
+}
+
+static void klog_vprintf(const char *fmt, va_list args)
+{
+	int ret;
+	va_list atst;
+
+	va_copy(atst, args);
+	spinlock_lock(&klog_lock);
+
+	ret = vsnprintf(klog+klogpos, klogsize-klogpos, fmt, atst);
+	// Workaround around bad return value from vsnprintf
+	if (ret+klogpos < klogsize)
+		ret = 100;
+	if (ret == klogsize-klogpos) {
+		klogpos = 0;
+		ret = vsnprintf(klog+klogpos, klogsize-klogpos, fmt, args);
+		ret = 100;
+		if (ret == klogsize)
+			goto out;
+	}
+	ipc_irq_send_msg(IPC_IRQ_KLOG, klogpos, ret);
+	klogpos += ret;
+	if (klogpos >= klogsize)
+		klogpos = 0;
+out:
+	spinlock_unlock(&klog_lock);
+	va_end(atst);
+}
+
+/** Printf a message to kernel-uspace log */
+void klog_printf(const char *fmt, ...)
+{
+	va_list args;
+	
+	va_start(args, fmt);
+	
+	klog_vprintf(fmt, args);
+
+	va_end(args);
+}
Index: generic/src/interrupt/interrupt.c
===================================================================
--- generic/src/interrupt/interrupt.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/interrupt/interrupt.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -91,4 +91,5 @@
 static void exc_undef(int n, istate_t *istate)
 {
+	fault_if_from_uspace(istate, "Unhandled exception %d.", n);
 	panic("Unhandled exception %d.", n);
 }
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/ipc/ipc.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -336,8 +336,5 @@
 		list_append(&request->link, &box->dispatched_calls);
 	} else {
-		/* This can happen regularly after ipc_cleanup, remove
-		 * the warning in the future when the IPC is
-		 * more debugged */
-		printf("WARNING: Spurious IPC wakeup.\n");
+		/* This can happen regularly after ipc_cleanup */
 		spinlock_unlock(&box->lock);
 		goto restart;
Index: generic/src/ipc/irq.c
===================================================================
--- generic/src/ipc/irq.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/ipc/irq.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -157,14 +157,15 @@
 {
 	ipl_t ipl;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
 
 	ipl = interrupts_disable();
-	spinlock_lock(&irq_conns[irq].lock);
-	if (irq_conns[irq].box == box) {
-		irq_conns[irq].box = NULL;
-		code_free(irq_conns[irq].code);
-		irq_conns[irq].code = NULL;
-	}
-
-	spinlock_unlock(&irq_conns[irq].lock);
+	spinlock_lock(&irq_conns[mq].lock);
+	if (irq_conns[mq].box == box) {
+		irq_conns[mq].box = NULL;
+		code_free(irq_conns[mq].code);
+		irq_conns[mq].code = NULL;
+	}
+
+	spinlock_unlock(&irq_conns[mq].lock);
 	interrupts_restore(ipl);
 }
@@ -175,4 +176,5 @@
 	ipl_t ipl;
 	irq_code_t *code;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
 
 	ASSERT(irq_conns);
@@ -186,16 +188,16 @@
 
 	ipl = interrupts_disable();
-	spinlock_lock(&irq_conns[irq].lock);
-
-	if (irq_conns[irq].box) {
-		spinlock_unlock(&irq_conns[irq].lock);
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
+		spinlock_unlock(&irq_conns[mq].lock);
 		interrupts_restore(ipl);
 		code_free(code);
 		return EEXISTS;
 	}
-	irq_conns[irq].box = box;
-	irq_conns[irq].code = code;
-	atomic_set(&irq_conns[irq].counter, 0);
-	spinlock_unlock(&irq_conns[irq].lock);
+	irq_conns[mq].box = box;
+	irq_conns[mq].code = code;
+	atomic_set(&irq_conns[mq].counter, 0);
+	spinlock_unlock(&irq_conns[mq].lock);
 	interrupts_restore(ipl);
 
@@ -203,19 +205,30 @@
 }
 
-/** Notify process that an irq had happend
- *
- * We expect interrupts to be disabled
- */
-void ipc_irq_send_notif(int irq)
+/** Add call to proper answerbox queue
+ *
+ * Assume irq_conns[mq].lock is locked */
+static void send_call(int mq, call_t *call)
+{
+	spinlock_lock(&irq_conns[mq].box->irq_lock);
+	list_append(&call->link, &irq_conns[mq].box->irq_notifs);
+	spinlock_unlock(&irq_conns[mq].box->irq_lock);
+		
+	waitq_wakeup(&irq_conns[mq].box->wq, 0);
+}
+
+/** Send notification message
+ *
+ */
+void ipc_irq_send_msg(int irq, __native a2, __native a3)
 {
 	call_t *call;
-
-	ASSERT(irq_conns);
-	spinlock_lock(&irq_conns[irq].lock);
-
-	if (irq_conns[irq].box) {
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
+
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
 		call = ipc_call_alloc(FRAME_ATOMIC);
 		if (!call) {
-			spinlock_unlock(&irq_conns[irq].lock);
+			spinlock_unlock(&irq_conns[mq].lock);
 			return;
 		}
@@ -223,24 +236,54 @@
 		IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
 		IPC_SET_ARG1(call->data, irq);
-		IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[irq].counter));
+		IPC_SET_ARG2(call->data, a2);
+		IPC_SET_ARG3(call->data, a3);
+		
+		send_call(mq, call);
+	}
+	spinlock_unlock(&irq_conns[mq].lock);
+}
+
+/** Notify process that an irq had happend
+ *
+ * We expect interrupts to be disabled
+ */
+void ipc_irq_send_notif(int irq)
+{
+	call_t *call;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
+
+	ASSERT(irq_conns);
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
+		call = ipc_call_alloc(FRAME_ATOMIC);
+		if (!call) {
+			spinlock_unlock(&irq_conns[mq].lock);
+			return;
+		}
+		call->flags |= IPC_CALL_NOTIF;
+		IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
+		IPC_SET_ARG1(call->data, irq);
+		IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[mq].counter));
 
 		/* Execute code to handle irq */
-		code_execute(call, irq_conns[irq].code);
-
-		spinlock_lock(&irq_conns[irq].box->irq_lock);
-		list_append(&call->link, &irq_conns[irq].box->irq_notifs);
-		spinlock_unlock(&irq_conns[irq].box->irq_lock);
-
-		waitq_wakeup(&irq_conns[irq].box->wq, 0);
-	}
+		code_execute(call, irq_conns[mq].code);
 		
-	spinlock_unlock(&irq_conns[irq].lock);
-}
-
-
-/** Initialize table of interrupt handlers */
+		send_call(mq, call);
+	}
+		
+	spinlock_unlock(&irq_conns[mq].lock);
+}
+
+
+/** Initialize table of interrupt handlers
+ *
+ * @param irqcount Count of required hardware IRQs to be supported
+ */
 void ipc_irq_make_table(int irqcount)
 {
 	int i;
+
+	irqcount +=  IPC_IRQ_RESERVED_VIRTUAL;
 
 	irq_conns_size = irqcount;
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/ipc/sysipc.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -554,12 +554,12 @@
 
 /** Connect irq handler to task */
-__native sys_ipc_register_irq(__native irq, irq_code_t *ucode)
+__native sys_ipc_register_irq(int irq, irq_code_t *ucode)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
 		return EPERM;
 
-	if (irq >= IRQ_COUNT)
+	if (irq >= IRQ_COUNT || irq <= -IPC_IRQ_RESERVED_VIRTUAL)
 		return (__native) ELIMIT;
-
+	
 	irq_ipc_bind_arch(irq);
 
@@ -568,10 +568,10 @@
 
 /* Disconnect irq handler from task */
-__native sys_ipc_unregister_irq(__native irq)
+__native sys_ipc_unregister_irq(int irq)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
 		return EPERM;
 
-	if (irq >= IRQ_COUNT)
+	if (irq >= IRQ_COUNT || irq <= -IPC_IRQ_RESERVED_VIRTUAL)
 		return (__native) ELIMIT;
 
Index: generic/src/main/main.c
===================================================================
--- generic/src/main/main.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/main/main.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -75,4 +75,5 @@
 #include <macros.h>
 #include <adt/btree.h>
+#include <console/klog.h>
 
 #ifdef CONFIG_SMP
@@ -219,4 +220,5 @@
 	thread_init();
 	futex_init();
+	klog_init();
 	
 	for (i = 0; i < init.cnt; i++)
Index: generic/src/proc/thread.c
===================================================================
--- generic/src/proc/thread.c	(revision 6f9a9bca0eb57eab9af41bd5a627f7f7fdcdc276)
+++ generic/src/proc/thread.c	(revision 874621f88e11575154ad0c2e08fc906a8d92e4c0)
@@ -389,4 +389,8 @@
 	spinlock_unlock(&THREAD->lock);
 	scheduler();
+
+	/* Not reached */
+	while (1)
+		;
 }
 
