Index: kernel/generic/include/interrupt.h
===================================================================
--- kernel/generic/include/interrupt.h	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ kernel/generic/include/interrupt.h	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -46,4 +46,14 @@
 typedef void (* iroutine)(int, istate_t *);
 
+typedef struct {
+	const char *name;
+	iroutine f;
+	uint64_t cycles;
+	uint64_t count;
+} exc_table_t;
+
+IRQ_SPINLOCK_EXTERN(exctbl_lock);
+extern exc_table_t exc_table[];
+
 extern void fault_if_from_uspace(istate_t *, const char *, ...);
 extern iroutine exc_register(int, const char *, iroutine);
Index: kernel/generic/include/sysinfo/abi.h
===================================================================
--- kernel/generic/include/sysinfo/abi.h	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ kernel/generic/include/sysinfo/abi.h	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -40,6 +40,7 @@
 #define LOAD_STEPS  3
 
-/** Maximum task name size */
+/** Maximum name sizes */
 #define TASK_NAME_BUFLEN  20
+#define EXC_NAME_BUFLEN   20
 
 /** Thread states */
@@ -123,4 +124,14 @@
 } stats_thread_t;
 
+/** Statistics about a single exception
+ *
+ */
+typedef struct {
+	unsigned int id;             /**< Exception ID */
+	char desc[EXC_NAME_BUFLEN];  /**< Description */
+	uint64_t cycles;             /**< Number of CPU cycles in the handler */
+	uint64_t count;              /**< Number of handled exceptions */
+} stats_exc_t;
+
 /** Load fixed-point value */
 typedef uint32_t load_t;
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ kernel/generic/src/interrupt/interrupt.c	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -53,11 +53,9 @@
 #include <symtab.h>
 #include <proc/thread.h>
-
-static struct {
-	const char *name;
-	iroutine f;
-} exc_table[IVT_ITEMS];
-
-SPINLOCK_INITIALIZE(exctbl_lock);
+#include <arch/cycle.h>
+#include <str.h>
+
+exc_table_t exc_table[IVT_ITEMS];
+IRQ_SPINLOCK_INITIALIZE(exctbl_lock);
 
 /** Register exception handler
@@ -72,11 +70,13 @@
 	ASSERT(n < IVT_ITEMS);
 	
-	spinlock_lock(&exctbl_lock);
+	irq_spinlock_lock(&exctbl_lock, true);
 	
 	iroutine old = exc_table[n].f;
 	exc_table[n].f = handler;
 	exc_table[n].name = name;
-	
-	spinlock_unlock(&exctbl_lock);
+	exc_table[n].cycles = 0;
+	exc_table[n].count = 0;
+	
+	irq_spinlock_unlock(&exctbl_lock, true);
 	
 	return old;
@@ -92,9 +92,11 @@
 {
 	ASSERT(n < IVT_ITEMS);
+	
+	uint64_t begin_cycle = get_cycle();
 	
 	/* Account user cycles */
 	if (THREAD) {
 		irq_spinlock_lock(&THREAD->lock, false);
-		thread_update_accounting(true);
+		THREAD->ucycles += begin_cycle - THREAD->last_cycle;
 		irq_spinlock_unlock(&THREAD->lock, false);
 	}
@@ -116,7 +118,13 @@
 		thread_exit();
 	
+	/* Account exception handling */
+	uint64_t end_cycle = get_cycle();
+	exc_table[n].cycles += end_cycle - begin_cycle;
+	exc_table[n].count++;
+	
+	/* Do not charge THREAD for exception cycles */
 	if (THREAD) {
 		irq_spinlock_lock(&THREAD->lock, false);
-		thread_update_accounting(false);
+		THREAD->last_cycle = end_cycle;
 		irq_spinlock_unlock(&THREAD->lock, false);
 	}
@@ -185,39 +193,52 @@
 	unsigned int i;
 	
-	spinlock_lock(&exctbl_lock);
+	irq_spinlock_lock(&exctbl_lock, true);
 	
 #ifdef __32_BITS__
-	printf("Exc Description          Handler    Symbol\n");
-	printf("--- -------------------- ---------- --------\n");
+	printf("Exc Description          Count      Cycles     Handler    Symbol\n");
+	printf("--- -------------------- ---------- ---------- ---------- --------\n");
 #endif
 	
 #ifdef __64_BITS__
-	printf("Exc Description          Handler            Symbol\n");
-	printf("--- -------------------- ------------------ --------\n");
+	printf("Exc Description          Count      Cycles     Handler            Symbol\n");
+	printf("--- -------------------- ---------- ---------- ------------------ --------\n");
 #endif
 	
 	for (i = 0; i < IVT_ITEMS; i++) {
-		const char *symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f);
+		uint64_t count;
+		char count_suffix;
+		
+		order_suffix(exc_table[i].count, &count, &count_suffix);
+		
+		uint64_t cycles;
+		char cycles_suffix;
+		
+		order_suffix(exc_table[i].cycles, &cycles, &cycles_suffix);
+		
+		const char *symbol =
+		    symtab_fmt_name_lookup((unative_t) exc_table[i].f);
 		
 #ifdef __32_BITS__
-		printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
-			exc_table[i].f, symbol);
+		printf("%-3u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %10p %s\n",
+		    i + IVT_FIRST, exc_table[i].name, count, count_suffix,
+		    cycles, cycles_suffix, exc_table[i].f, symbol);
 #endif
 		
 #ifdef __64_BITS__
-		printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name,
-			exc_table[i].f, symbol);
+		printf("%-3u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %18p %s\n",
+		    i + IVT_FIRST, exc_table[i].name, count, count_suffix,
+		    cycles, cycles_suffix, exc_table[i].f, symbol);
 #endif
 		
 		if (((i + 1) % 20) == 0) {
 			printf(" -- Press any key to continue -- ");
-			spinlock_unlock(&exctbl_lock);
+			irq_spinlock_unlock(&exctbl_lock, true);
 			indev_pop_character(stdin);
-			spinlock_lock(&exctbl_lock);
+			irq_spinlock_lock(&exctbl_lock, true);
 			printf("\n");
 		}
 	}
 	
-	spinlock_unlock(&exctbl_lock);
+	irq_spinlock_unlock(&exctbl_lock, true);
 #endif
 	
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ kernel/generic/src/sysinfo/stats.c	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -44,4 +44,5 @@
 #include <proc/task.h>
 #include <proc/thread.h>
+#include <interrupt.h>
 #include <str.h>
 #include <errno.h>
@@ -535,4 +536,115 @@
 }
 
+/** Get exceptions statistics
+ *
+ * @param item    Sysinfo item (unused).
+ * @param size    Size of the returned data.
+ * @param dry_run Do not get the data, just calculate the size.
+ *
+ * @return Data containing several stats_exc_t structures.
+ *         If the return value is not NULL, it should be freed
+ *         in the context of the sysinfo request.
+ */
+static void *get_stats_exceptions(struct sysinfo_item *item, size_t *size,
+    bool dry_run)
+{
+	*size = sizeof(stats_exc_t) * IVT_ITEMS;
+	
+	if ((dry_run) || (IVT_ITEMS == 0))
+		return NULL;
+	
+	stats_exc_t *stats_exceptions =
+	    (stats_exc_t *) malloc(*size, FRAME_ATOMIC);
+	if (stats_exceptions == NULL) {
+		/* No free space for allocation */
+		*size = 0;
+		return NULL;
+	}
+	
+	/* Messing with exception table, avoid deadlock */
+	irq_spinlock_lock(&exctbl_lock, true);
+	
+	unsigned int i;
+	for (i = 0; i < IVT_ITEMS; i++) {
+		stats_exceptions[i].id = i + IVT_FIRST;
+		str_cpy(stats_exceptions[i].desc, EXC_NAME_BUFLEN, exc_table[i].name);
+		stats_exceptions[i].cycles = exc_table[i].cycles;
+		stats_exceptions[i].count = exc_table[i].count;
+	}
+	
+	irq_spinlock_unlock(&exctbl_lock, true);
+	
+	return ((void *) stats_exceptions);
+}
+
+/** Get exception statistics
+ *
+ * Get statistics of a given exception. The exception number
+ * is passed as a string (current limitation of the sysinfo
+ * interface, but it is still reasonable for the given purpose).
+ *
+ * @param name    Exception number (string-encoded number).
+ * @param dry_run Do not get the data, just calculate the size.
+ *
+ * @return Sysinfo return holder. The type of the returned
+ *         data is either SYSINFO_VAL_UNDEFINED (unknown
+ *         exception number or memory allocation error) or
+ *         SYSINFO_VAL_FUNCTION_DATA (in that case the
+ *         generated data should be freed within the
+ *         sysinfo request context).
+ *
+ */
+static sysinfo_return_t get_stats_exception(const char *name, bool dry_run)
+{
+	/* Initially no return value */
+	sysinfo_return_t ret;
+	ret.tag = SYSINFO_VAL_UNDEFINED;
+	
+	/* Parse the exception number */
+	uint64_t excn;
+	if (str_uint64(name, NULL, 0, true, &excn) != EOK)
+		return ret;
+	
+#if IVT_FIRST > 0
+	if (excn < IVT_FIRST)
+		return ret;
+#endif
+	
+	if (excn >= IVT_ITEMS + IVT_FIRST)
+		return ret;
+	
+	if (dry_run) {
+		ret.tag = SYSINFO_VAL_FUNCTION_DATA;
+		ret.data.data = NULL;
+		ret.data.size = sizeof(stats_thread_t);
+	} else {
+		/* Update excn index for accessing exc_table */
+		excn -= IVT_FIRST;
+		
+		/* Allocate stats_exc_t structure */
+		stats_exc_t *stats_exception =
+		    (stats_exc_t *) malloc(sizeof(stats_exc_t), FRAME_ATOMIC);
+		if (stats_exception == NULL)
+			return ret;
+		
+		/* Messing with exception table, avoid deadlock */
+		irq_spinlock_lock(&exctbl_lock, true);
+		
+		/* Correct return value */
+		ret.tag = SYSINFO_VAL_FUNCTION_DATA;
+		ret.data.data = (void *) stats_exception;
+		ret.data.size = sizeof(stats_exc_t);
+		
+		stats_exception->id = excn;
+		str_cpy(stats_exception->desc, EXC_NAME_BUFLEN, exc_table[excn].name);
+		stats_exception->cycles = exc_table[excn].cycles;
+		stats_exception->count = exc_table[excn].count;
+		
+		irq_spinlock_unlock(&exctbl_lock, true);
+	}
+	
+	return ret;
+}
+
 /** Get physical memory statistics
  *
@@ -651,6 +763,8 @@
 	sysinfo_set_item_fn_data("system.tasks", NULL, get_stats_tasks);
 	sysinfo_set_item_fn_data("system.threads", NULL, get_stats_threads);
+	sysinfo_set_item_fn_data("system.exceptions", NULL, get_stats_exceptions);
 	sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task);
 	sysinfo_set_subtree_fn("system.threads", NULL, get_stats_thread);
+	sysinfo_set_subtree_fn("system.exceptions", NULL, get_stats_exception);
 }
 
Index: uspace/app/top/screen.c
===================================================================
--- uspace/app/top/screen.c	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ uspace/app/top/screen.c	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -325,4 +325,41 @@
 }
 
+static inline void print_exc_head(void)
+{
+	screen_style_inverted();
+	printf("  ID                     Desc    Count   Cycles");
+	screen_newline();
+	screen_style_normal();
+}
+
+static inline void print_exc(data_t *data)
+{
+	ipcarg_t cols;
+	ipcarg_t rows;
+	screen_get_size(&cols, &rows);
+	
+	ipcarg_t col;
+	ipcarg_t row;
+	screen_get_pos(&col, &row);
+	
+	size_t i;
+	for (i = 0; (i < data->exceptions_count) && (row < rows); i++, row++) {
+		uint64_t cycles;
+		char suffix;
+		
+		order_suffix(data->exceptions[i].cycles, &cycles, &suffix);
+		printf("%8u %20s %8" PRIu64 " %8" PRIu64 "%c",
+		     data->exceptions[i].id, data->exceptions[i].desc,
+		     data->exceptions[i].count, cycles, suffix);
+		
+		screen_newline();
+	}
+	
+	while (row < rows) {
+		screen_newline();
+		row++;
+	}
+}
+
 void print_data(data_t *data)
 {
@@ -338,10 +375,17 @@
 	screen_newline();
 	
-	if (operation_type == OP_IPC) {
+	switch (operation_type) {
+	case OP_TASKS:
+		print_task_head();
+		print_tasks(data);
+		break;
+	case OP_IPC:
 		print_ipc_head();
 		print_ipc(data);
-	} else {
-		print_task_head();
-		print_tasks(data);
+		break;
+	case OP_EXC:
+		print_exc_head();
+		print_exc(data);
+		break;
 	}
 	
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ uspace/app/top/top.c	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -115,4 +115,8 @@
 		return "Cannot get threads";
 	
+	target->exceptions = stats_get_exceptions(&(target->exceptions_count));
+	if (target->exceptions == NULL)
+		return "Cannot get exceptions";
+	
 	/* Get physical memory */
 	target->physmem = stats_get_physmem();
@@ -231,4 +235,7 @@
 	if (target->threads != NULL)
 		free(target->threads);
+	
+	if (target->exceptions != NULL)
+		free(target->exceptions);
 	
 	if (target->physmem != NULL)
@@ -285,4 +292,8 @@
 				operation_type = OP_TASKS;
 				break;
+			case 'e':
+				print_warning("Showing exception statistics");
+				operation_type = OP_EXC;
+				break;
 			default:
 				print_warning("Unknown command: %c", c);
Index: uspace/app/top/top.h
===================================================================
--- uspace/app/top/top.h	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ uspace/app/top/top.h	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -46,4 +46,5 @@
 #define OP_TASKS  1
 #define OP_IPC    2
+#define OP_EXC    3
 
 extern int operation_type;
@@ -89,4 +90,7 @@
 	stats_thread_t *threads;
 	
+	size_t exceptions_count;
+	stats_exc_t *exceptions;
+	
 	stats_physmem_t *physmem;
 } data_t;
Index: uspace/lib/c/generic/stats.c
===================================================================
--- uspace/lib/c/generic/stats.c	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ uspace/lib/c/generic/stats.c	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -184,4 +184,48 @@
 }
 
+/** Get exception statistics.
+ *
+ * @param count Number of records returned.
+ *
+ * @return Array of stats_exc_t structures.
+ *         If non-NULL then it should be eventually freed
+ *         by free().
+ *
+ */
+stats_exc_t *stats_get_exceptions(size_t *count)
+{
+	size_t size = 0;
+	stats_exc_t *stats_exceptions =
+	    (stats_exc_t *) sysinfo_get_data("system.exceptions", &size);
+	
+	assert((size % sizeof(stats_exc_t)) == 0);
+	
+	*count = size / sizeof(stats_exc_t);
+	return stats_exceptions;
+}
+
+/** Get single exception statistics
+ *
+ * @param excn Exception number we are interested in.
+ *
+ * @return Pointer to the stats_exc_t structure.
+ *         If non-NULL then it should be eventually freed
+ *         by free().
+ *
+ */
+stats_exc_t *stats_get_exception(unsigned int excn)
+{
+	char name[SYSINFO_STATS_MAX_PATH];
+	snprintf(name, SYSINFO_STATS_MAX_PATH, "system.exceptionss.%u", excn);
+	
+	size_t size = 0;
+	stats_exc_t *stats_exception =
+	    (stats_exc_t *) sysinfo_get_data(name, &size);
+	
+	assert((size == sizeof(stats_exc_t)) || (size == 0));
+	
+	return stats_exception;
+}
+
 /** Get system load
  *
Index: uspace/lib/c/include/stats.h
===================================================================
--- uspace/lib/c/include/stats.h	(revision 1113c9e130ee0cf71775a520394a8c7b73e1cf1e)
+++ uspace/lib/c/include/stats.h	(revision 8eec3c82a9d04f56cd45c25f1e2466f94a863763)
@@ -53,4 +53,7 @@
 extern stats_thread_t *stats_get_thread(thread_id_t);
 
+extern stats_exc_t *stats_get_exceptions(size_t *);
+extern stats_exc_t *stats_get_exception(unsigned int);
+
 extern void stats_print_load_fragment(load_t, unsigned int);
 extern const char *thread_get_state(state_t);
