Index: abi/include/abi/sysinfo.h
===================================================================
--- abi/include/abi/sysinfo.h	(revision ad211c849e7c6874c1c3f6ce9695684e0420bd95)
+++ abi/include/abi/sysinfo.h	(revision a6302aeae3f6b03e65410b4c2b6091d819fe88d5)
@@ -125,4 +125,12 @@
 } stats_thread_t;
 
+/** Statistics about a single IPC connection
+ *
+ */
+typedef struct {
+	task_id_t caller;  /**< Source task ID */
+	task_id_t callee;  /**< Target task ID */
+} stats_ipcc_t;
+
 /** Statistics about a single exception
  *
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision ad211c849e7c6874c1c3f6ce9695684e0420bd95)
+++ kernel/generic/src/sysinfo/stats.c	(revision a6302aeae3f6b03e65410b4c2b6091d819fe88d5)
@@ -69,4 +69,12 @@
 #define LOAD_INTERVAL  5
 
+/** IPC connections statistics state */
+typedef struct {
+	bool counting;
+	size_t count;
+	size_t i;
+	stats_ipcc_t *data;
+} ipccs_state_t;
+
 /** Fixed-point representation of
  *
@@ -371,4 +379,118 @@
 
 	return ((void *) stats_threads);
+}
+
+/** Produce IPC connection statistics
+ *
+ * Summarize IPC connection information into IPC connection statistics.
+ *
+ * @param cap Phone capability.
+ * @param arg State variable.
+ *
+ */
+static bool produce_stats_ipcc_cb(cap_t *cap, void *arg)
+{
+	phone_t *phone = cap->kobject->phone;
+	ipccs_state_t *state = (ipccs_state_t *) arg;
+
+	if (state->counting) {
+		/*
+		 * Simply update the number of entries
+		 * in case we are in the counting mode.
+		 */
+
+		state->count++;
+		return true;
+	}
+
+	/* We are in the gathering mode */
+
+	if ((state->data == NULL) || (state->i >= state->count)) {
+		/*
+		 * Do nothing if we have no buffer
+		 * to store the data to (meaning we are
+		 * in a dry run) or the buffer is already
+		 * full.
+		 */
+
+		return true;
+	}
+
+	mutex_lock(&phone->lock);
+
+	if (phone->state == IPC_PHONE_CONNECTED) {
+		state->data[state->i].caller = phone->caller->taskid;
+		state->data[state->i].callee = phone->callee->task->taskid;
+		state->i++;
+	}
+
+	mutex_unlock(&phone->lock);
+
+	return true;
+}
+
+/** Get IPC connections 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.
+ * @param data    Unused.
+ *
+ * @return Data containing several stats_ipccs_t structures.
+ *         If the return value is not NULL, it should be freed
+ *         in the context of the sysinfo request.
+ *
+ */
+static void *get_stats_ipccs(struct sysinfo_item *item, size_t *size,
+    bool dry_run, void *data)
+{
+	/* Messing with tasks structures, avoid deadlock */
+	irq_spinlock_lock(&tasks_lock, true);
+
+	ipccs_state_t state = {
+		.counting = true,
+		.count = 0,
+		.i = 0,
+		.data = NULL
+	};
+
+	/* Compute the number of IPC connections */
+	task_t *task = task_first();
+	while (task != NULL) {
+		task_hold(task);
+		irq_spinlock_unlock(&tasks_lock, true);
+
+		caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE,
+		    produce_stats_ipcc_cb, &state);
+
+		irq_spinlock_lock(&tasks_lock, true);
+
+		task = task_next(task);
+	}
+
+	state.counting = false;
+	*size = sizeof(stats_ipcc_t) * state.count;
+
+	if (!dry_run)
+		state.data = (stats_ipcc_t *) malloc(*size);
+
+	/* Gather the statistics for each task */
+	task = task_first();
+	while (task != NULL) {
+		/* We already hold a reference to the task */
+		irq_spinlock_unlock(&tasks_lock, true);
+
+		caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE,
+		    produce_stats_ipcc_cb, &state);
+
+		irq_spinlock_lock(&tasks_lock, true);
+		task_release(task);
+
+		task = task_next(task);
+	}
+
+	irq_spinlock_unlock(&tasks_lock, true);
+
+	return ((void *) state.data);
 }
 
@@ -754,4 +876,5 @@
 	sysinfo_set_item_gen_data("system.tasks", NULL, get_stats_tasks, NULL);
 	sysinfo_set_item_gen_data("system.threads", NULL, get_stats_threads, NULL);
+	sysinfo_set_item_gen_data("system.ipccs", NULL, get_stats_ipccs, NULL);
 	sysinfo_set_item_gen_data("system.exceptions", NULL, get_stats_exceptions, NULL);
 	sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task, NULL);
Index: uspace/app/stats/stats.c
===================================================================
--- uspace/app/stats/stats.c	(revision ad211c849e7c6874c1c3f6ce9695684e0420bd95)
+++ uspace/app/stats/stats.c	(revision a6302aeae3f6b03e65410b4c2b6091d819fe88d5)
@@ -52,4 +52,13 @@
 #define MINUTE  60
 
+typedef enum {
+	LIST_TASKS,
+	LIST_THREADS,
+	LIST_IPCCS,
+	LIST_CPUS,
+	LIST_LOAD,
+	LIST_UPTIME
+} list_toggle_t;
+
 static void list_tasks(void)
 {
@@ -65,6 +74,5 @@
 	    " [kcycles] [name\n");
 
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		uint64_t resmem;
 		uint64_t virtmem;
@@ -103,6 +111,5 @@
 	printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n");
 
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		if ((all) || (stats_threads[i].task_id == task_id)) {
 			uint64_t ucycles, kcycles;
@@ -130,4 +137,26 @@
 }
 
+static void list_ipccs(task_id_t task_id, bool all)
+{
+	size_t count;
+	stats_ipcc_t *stats_ipccs = stats_get_ipccs(&count);
+
+	if (stats_ipccs == NULL) {
+		fprintf(stderr, "%s: Unable to get IPC connections\n", NAME);
+		return;
+	}
+
+	printf("[caller] [callee]\n");
+
+	for (size_t i = 0; i < count; i++) {
+		if ((all) || (stats_ipccs[i].caller == task_id)) {
+			printf("%-8" PRIu64 " %-8" PRIu64 "\n",
+			    stats_ipccs[i].caller, stats_ipccs[i].callee);
+		}
+	}
+
+	free(stats_ipccs);
+}
+
 static void list_cpus(void)
 {
@@ -142,6 +171,5 @@
 	printf("[id] [MHz     ] [busy cycles] [idle cycles]\n");
 
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		printf("%-4u ", cpus[i].id);
 		if (cpus[i].active) {
@@ -174,6 +202,5 @@
 	printf("%s: Load average: ", NAME);
 
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		if (i > 0)
 			printf(" ");
@@ -200,5 +227,5 @@
 {
 	printf(
-	    "Usage: %s [-t task_id] [-a] [-c] [-l] [-u]\n"
+	    "Usage: %s [-t task_id] [-i task_id] [-at] [-ai] [-c] [-l] [-u]\n"
 	    "\n"
 	    "Options:\n"
@@ -207,7 +234,15 @@
 	    "\t\tList threads of the given task\n"
 	    "\n"
-	    "\t-a\n"
-	    "\t--all\n"
+	    "\t-i task_id\n"
+	    "\t--ipcc=task_id\n"
+	    "\t\tList IPC connections of the given task\n"
+	    "\n"
+	    "\t-at\n"
+	    "\t--all-threads\n"
 	    "\t\tList all threads\n"
+	    "\n"
+	    "\t-ai\n"
+	    "\t--all-ipccs\n"
+	    "\t\tList all IPC connections\n"
 	    "\n"
 	    "\t-c\n"
@@ -233,15 +268,9 @@
 int main(int argc, char *argv[])
 {
-	bool toggle_tasks = true;
-	bool toggle_threads = false;
+	list_toggle_t list_toggle = LIST_TASKS;
 	bool toggle_all = false;
-	bool toggle_cpus = false;
-	bool toggle_load = false;
-	bool toggle_uptime = false;
-
 	task_id_t task_id = 0;
 
-	int i;
-	for (i = 1; i < argc; i++) {
+	for (int i = 1; i < argc; i++) {
 		int off;
 
@@ -252,20 +281,35 @@
 		}
 
+		/* All IPC connections */
+		if ((off = arg_parse_short_long(argv[i], "-ai", "--all-ipccs")) != -1) {
+			list_toggle = LIST_IPCCS;
+			toggle_all = true;
+			continue;
+		}
+
 		/* All threads */
-		if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
-			toggle_tasks = false;
-			toggle_threads = true;
+		if ((off = arg_parse_short_long(argv[i], "-at", "--all-threads")) != -1) {
+			list_toggle = LIST_THREADS;
 			toggle_all = true;
 			continue;
 		}
 
-		/* CPUs */
-		if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
-			toggle_tasks = false;
-			toggle_cpus = true;
-			continue;
-		}
-
-		/* Threads */
+		/* IPC connections */
+		if ((off = arg_parse_short_long(argv[i], "-i", "--ipcc=")) != -1) {
+			// TODO: Support for 64b range
+			int tmp;
+			errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off);
+			if (ret != EOK) {
+				printf("%s: Malformed task id '%s'\n", NAME, argv[i]);
+				return -1;
+			}
+
+			task_id = tmp;
+
+			list_toggle = LIST_IPCCS;
+			continue;
+		}
+
+		/* Tasks */
 		if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
 			// TODO: Support for 64b range
@@ -273,5 +317,5 @@
 			errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off);
 			if (ret != EOK) {
-				printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
+				printf("%s: Malformed task id '%s'\n", NAME, argv[i]);
 				return -1;
 			}
@@ -279,6 +323,11 @@
 			task_id = tmp;
 
-			toggle_tasks = false;
-			toggle_threads = true;
+			list_toggle = LIST_THREADS;
+			continue;
+		}
+
+		/* CPUs */
+		if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
+			list_toggle = LIST_CPUS;
 			continue;
 		}
@@ -286,6 +335,5 @@
 		/* Load */
 		if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
-			toggle_tasks = false;
-			toggle_load = true;
+			list_toggle = LIST_LOAD;
 			continue;
 		}
@@ -293,24 +341,29 @@
 		/* Uptime */
 		if ((off = arg_parse_short_long(argv[i], "-u", "--uptime")) != -1) {
-			toggle_tasks = false;
-			toggle_uptime = true;
-			continue;
-		}
-	}
-
-	if (toggle_tasks)
+			list_toggle = LIST_UPTIME;
+			continue;
+		}
+	}
+
+	switch (list_toggle) {
+	case LIST_TASKS:
 		list_tasks();
-
-	if (toggle_threads)
+		break;
+	case LIST_THREADS:
 		list_threads(task_id, toggle_all);
-
-	if (toggle_cpus)
+		break;
+	case LIST_IPCCS:
+		list_ipccs(task_id, toggle_all);
+		break;
+	case LIST_CPUS:
 		list_cpus();
-
-	if (toggle_load)
+		break;
+	case LIST_LOAD:
 		print_load();
-
-	if (toggle_uptime)
+		break;
+	case LIST_UPTIME:
 		print_uptime();
+		break;
+	}
 
 	return 0;
Index: uspace/lib/c/generic/stats.c
===================================================================
--- uspace/lib/c/generic/stats.c	(revision ad211c849e7c6874c1c3f6ce9695684e0420bd95)
+++ uspace/lib/c/generic/stats.c	(revision a6302aeae3f6b03e65410b4c2b6091d819fe88d5)
@@ -184,4 +184,30 @@
 }
 
+/** Get IPC connections statistics.
+ *
+ * @param count Number of records returned.
+ *
+ * @return Array of stats_ipcc_t structures.
+ *         If non-NULL then it should be eventually freed
+ *         by free().
+ *
+ */
+stats_ipcc_t *stats_get_ipccs(size_t *count)
+{
+	size_t size = 0;
+	stats_ipcc_t *stats_ipccs =
+	    (stats_ipcc_t *) sysinfo_get_data("system.ipccs", &size);
+
+	if ((size % sizeof(stats_ipcc_t)) != 0) {
+		if (stats_ipccs != NULL)
+			free(stats_ipccs);
+		*count = 0;
+		return NULL;
+	}
+
+	*count = size / sizeof(stats_ipcc_t);
+	return stats_ipccs;
+}
+
 /** Get exception statistics.
  *
Index: uspace/lib/c/include/stats.h
===================================================================
--- uspace/lib/c/include/stats.h	(revision ad211c849e7c6874c1c3f6ce9695684e0420bd95)
+++ uspace/lib/c/include/stats.h	(revision a6302aeae3f6b03e65410b4c2b6091d819fe88d5)
@@ -52,4 +52,5 @@
 
 extern stats_thread_t *stats_get_threads(size_t *);
+extern stats_ipcc_t *stats_get_ipccs(size_t *);
 
 extern stats_exc_t *stats_get_exceptions(size_t *);
