Index: uspace/app/stats/stats.c
===================================================================
--- uspace/app/stats/stats.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/app/stats/stats.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -38,5 +38,4 @@
 #include <stdio.h>
 #include <task.h>
-#include <thread.h>
 #include <stats.h>
 #include <errno.h>
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/app/top/top.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -39,5 +39,4 @@
 #include <stdlib.h>
 #include <task.h>
-#include <thread.h>
 #include <sys/time.h>
 #include <errno.h>
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -102,4 +102,11 @@
 	if (dev->speed >= USB_SPEED_HIGH ||
 	    ep->transfer_type != USB_TRANSFER_INTERRUPT) {
+
+		// XXX: According to the spec, the interval should be
+		//      from [1, 16]. However, in QEMU, we get 0 here
+		//      (a QEMU bug?).
+		if (xhci_ep->interval == 0)
+			xhci_ep->interval = 8;
+
 		xhci_ep->interval = 1 << (xhci_ep->interval - 1);
 	}
Index: uspace/drv/nic/virtio-net/virtio-net.c
===================================================================
--- uspace/drv/nic/virtio-net/virtio-net.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/drv/nic/virtio-net/virtio-net.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -70,116 +70,4 @@
 };
 
-/** Allocate DMA buffers
- *
- * @param buffers[in]  Number of buffers to allocate.
- * @param size[in]     Size of each buffer.
- * @param write[in]    True if the buffers are writable by the driver, false
- *                     otherwise.
- * @param buf[out]     Output array holding virtual addresses of the allocated
- *                     buffers.
- * @param buf_p[out]   Output array holding physical addresses of the allocated
- *                     buffers.
- *
- * The buffers can be deallocated by virtio_net_teardown_bufs().
- *
- * @return  EOK on success or error code.
- */
-static errno_t virtio_net_setup_bufs(unsigned int buffers, size_t size,
-    bool write, void *buf[], uintptr_t buf_p[])
-{
-	/*
-	 * Allocate all buffers at once in one large chunk.
-	 */
-	void *virt = AS_AREA_ANY;
-	uintptr_t phys;
-	errno_t rc = dmamem_map_anonymous(buffers * size, 0,
-	    write ? AS_AREA_WRITE : AS_AREA_READ, 0, &phys, &virt);
-	if (rc != EOK)
-		return rc;
-
-	ddf_msg(LVL_NOTE, "DMA buffers: %p-%p", virt, virt + buffers * size);
-
-	/*
-	 * Calculate addresses of the individual buffers for easy access.
-	 */
-	for (unsigned i = 0; i < buffers; i++) {
-		buf[i] = virt + i * size;
-		buf_p[i] = phys + i * size;
-	}
-
-	return EOK;
-}
-
-/** Deallocate DMA buffers
- *
- * @param buf[in]  Array holding the virtual addresses of the DMA buffers
- *                 previously allocated by virtio_net_setup_bufs().
- */
-static void virtio_net_teardown_bufs(void *buf[])
-{
-	if (buf[0]) {
-		dmamem_unmap_anonymous(buf[0]);
-		buf[0] = NULL;
-	}
-}
-
-/** Create free descriptor list from the unused VIRTIO descriptors
- *
- * @param vdev[in]   VIRTIO device for which the free list will be created.
- * @param num[in]    Index of the virtqueue for which the free list will be
- *                   created.
- * @param size[in]   Number of descriptors on the free list. The free list will
- *                   contain descriptors starting from 0 to \a size - 1.
- * @param head[out]  Variable that will hold the VIRTIO descriptor at the head
- *                   of the free list.
- */
-static void virtio_net_create_desc_free_list(virtio_dev_t *vdev, uint16_t num,
-    uint16_t size, uint16_t *head)
-{
-	for (unsigned i = 0; i < size; i++) {
-		virtio_virtq_desc_set(vdev, num, i, 0, 0,
-		    VIRTQ_DESC_F_NEXT, (i + 1 == size) ? -1U : i + 1);
-	}
-	*head = 0;
-}
-
-/** Allocate a descriptor from the free list
- *
- * @param vdev[in]      VIRTIO device with the free list.
- * @param num[in]       Index of the virtqueue with free list.
- * @param head[in,out]  Head of the free list.
- *
- * @return  Allocated descriptor or 0xFFFF if the list is empty.
- */
-static uint16_t virtio_net_alloc_desc(virtio_dev_t *vdev, uint16_t num,
-    uint16_t *head)
-{
-	virtq_t *q = &vdev->queues[num];
-	fibril_mutex_lock(&q->lock);
-	uint16_t descno = *head;
-	if (descno != (uint16_t) -1U)
-		*head = virtio_virtq_desc_get_next(vdev, num, descno);
-	fibril_mutex_unlock(&q->lock);
-	return descno;
-}
-
-/** Free a descriptor into the free list
- *
- * @param vdev[in]      VIRTIO device with the free list.
- * @param num[in]       Index of the virtqueue with free list.
- * @param head[in,out]  Head of the free list.
- * @param descno[in]    The freed descriptor.
- */
-static void virtio_net_free_desc(virtio_dev_t *vdev, uint16_t num,
-    uint16_t *head, uint16_t descno)
-{
-	virtq_t *q = &vdev->queues[num];
-	fibril_mutex_lock(&q->lock);
-	virtio_virtq_desc_set(vdev, num, descno, 0, 0, VIRTQ_DESC_F_NEXT,
-	    *head);
-	*head = descno;
-	fibril_mutex_unlock(&q->lock);
-}
-
 static void virtio_net_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
 {
@@ -214,10 +102,10 @@
 
 	while (virtio_virtq_consume_used(vdev, TX_QUEUE_1, &descno, &len)) {
-		virtio_net_free_desc(vdev, TX_QUEUE_1,
-		    &virtio_net->tx_free_head, descno);
+		virtio_free_desc(vdev, TX_QUEUE_1, &virtio_net->tx_free_head,
+		    descno);
 	}
 	while (virtio_virtq_consume_used(vdev, CT_QUEUE_1, &descno, &len)) {
-		virtio_net_free_desc(vdev, CT_QUEUE_1,
-		    &virtio_net->ct_free_head, descno);
+		virtio_free_desc(vdev, CT_QUEUE_1, &virtio_net->ct_free_head,
+		    descno);
 	}
 }
@@ -345,13 +233,13 @@
 	 * Setup DMA buffers
 	 */
-	rc = virtio_net_setup_bufs(RX_BUFFERS, RX_BUF_SIZE, false,
+	rc = virtio_setup_dma_bufs(RX_BUFFERS, RX_BUF_SIZE, false,
 	    virtio_net->rx_buf, virtio_net->rx_buf_p);
 	if (rc != EOK)
 		goto fail;
-	rc = virtio_net_setup_bufs(TX_BUFFERS, TX_BUF_SIZE, true,
+	rc = virtio_setup_dma_bufs(TX_BUFFERS, TX_BUF_SIZE, true,
 	    virtio_net->tx_buf, virtio_net->tx_buf_p);
 	if (rc != EOK)
 		goto fail;
-	rc = virtio_net_setup_bufs(CT_BUFFERS, CT_BUF_SIZE, true,
+	rc = virtio_setup_dma_bufs(CT_BUFFERS, CT_BUF_SIZE, true,
 	    virtio_net->ct_buf, virtio_net->ct_buf_p);
 	if (rc != EOK)
@@ -379,7 +267,7 @@
 	 * Put all TX and CT buffers on a free list
 	 */
-	virtio_net_create_desc_free_list(vdev, TX_QUEUE_1, TX_BUFFERS,
+	virtio_create_desc_free_list(vdev, TX_QUEUE_1, TX_BUFFERS,
 	    &virtio_net->tx_free_head);
-	virtio_net_create_desc_free_list(vdev, CT_QUEUE_1, CT_BUFFERS,
+	virtio_create_desc_free_list(vdev, CT_QUEUE_1, CT_BUFFERS,
 	    &virtio_net->ct_free_head);
 
@@ -414,7 +302,7 @@
 
 fail:
-	virtio_net_teardown_bufs(virtio_net->rx_buf);
-	virtio_net_teardown_bufs(virtio_net->tx_buf);
-	virtio_net_teardown_bufs(virtio_net->ct_buf);
+	virtio_teardown_dma_bufs(virtio_net->rx_buf);
+	virtio_teardown_dma_bufs(virtio_net->tx_buf);
+	virtio_teardown_dma_bufs(virtio_net->ct_buf);
 
 	virtio_device_setup_fail(vdev);
@@ -428,7 +316,7 @@
 	virtio_net_t *virtio_net = (virtio_net_t *) nic_get_specific(nic);
 
-	virtio_net_teardown_bufs(virtio_net->rx_buf);
-	virtio_net_teardown_bufs(virtio_net->tx_buf);
-	virtio_net_teardown_bufs(virtio_net->ct_buf);
+	virtio_teardown_dma_bufs(virtio_net->rx_buf);
+	virtio_teardown_dma_bufs(virtio_net->tx_buf);
+	virtio_teardown_dma_bufs(virtio_net->ct_buf);
 
 	virtio_device_setup_fail(&virtio_net->virtio_dev);
@@ -446,5 +334,5 @@
 	}
 
-	uint16_t descno = virtio_net_alloc_desc(vdev, TX_QUEUE_1,
+	uint16_t descno = virtio_alloc_desc(vdev, TX_QUEUE_1,
 	    &virtio_net->tx_free_head);
 	if (descno == (uint16_t) -1U) {
Index: uspace/lib/c/generic/async/ports.c
===================================================================
--- uspace/lib/c/generic/async/ports.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/generic/async/ports.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -35,5 +35,4 @@
 #include <ipc/irq.h>
 #include <ipc/event.h>
-#include <futex.h>
 #include <fibril.h>
 #include <adt/hash_table.h>
Index: uspace/lib/c/generic/async/server.c
===================================================================
--- uspace/lib/c/generic/async/server.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/generic/async/server.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -122,4 +122,6 @@
 #include "../private/fibril.h"
 
+#define DPRINTF(...)  ((void) 0)
+
 /** Async framework global futex */
 futex_t async_futex = FUTEX_INITIALIZER;
@@ -132,5 +134,4 @@
 	link_t link;
 
-	cap_call_handle_t chandle;
 	ipc_call_t call;
 } msg_t;
@@ -164,7 +165,4 @@
 	list_t msg_queue;
 
-	/** Identification of the opening call. */
-	cap_call_handle_t chandle;
-
 	/** Call data of the opening call. */
 	ipc_call_t call;
@@ -179,4 +177,10 @@
 	void *data;
 } connection_t;
+
+/* Member of notification_t::msg_list. */
+typedef struct {
+	link_t link;
+	ipc_call_t calldata;
+} notification_msg_t;
 
 /* Notification data */
@@ -197,17 +201,6 @@
 	void *arg;
 
-	/** Data of the most recent notification. */
-	ipc_call_t calldata;
-
-	/**
-	 * How many notifications with this `imethod` arrived since it was last
-	 * handled. If `count` > 1, `calldata` only holds the data for the most
-	 * recent such notification, all the older data being lost.
-	 *
-	 * `async_spawn_notification_handler()` can be used to increase the
-	 * number of notifications that can be processed simultaneously,
-	 * reducing the likelihood of losing them when the handler blocks.
-	 */
-	long count;
+	/** List of arrived notifications. */
+	list_t msg_list;
 } notification_t;
 
@@ -249,4 +242,8 @@
 static LIST_INITIALIZE(notification_queue);
 static FIBRIL_SEMAPHORE_INITIALIZE(notification_semaphore, 0);
+
+static LIST_INITIALIZE(notification_freelist);
+static long notification_freelist_total = 0;
+static long notification_freelist_used = 0;
 
 static sysarg_t notification_avail = 0;
@@ -412,5 +409,5 @@
 	client_t *client = async_client_get(fibril_connection->in_task_id, true);
 	if (!client) {
-		ipc_answer_0(fibril_connection->chandle, ENOMEM);
+		ipc_answer_0(fibril_connection->call.cap_handle, ENOMEM);
 		return 0;
 	}
@@ -421,5 +418,5 @@
 	 * Call the connection handler function.
 	 */
-	fibril_connection->handler(fibril_connection->chandle,
+	fibril_connection->handler(fibril_connection->call.cap_handle,
 	    &fibril_connection->call, fibril_connection->data);
 
@@ -448,5 +445,5 @@
 
 		list_remove(&msg->link);
-		ipc_answer_0(msg->chandle, EHANGUP);
+		ipc_answer_0(msg->call.cap_handle, EHANGUP);
 		free(msg);
 	}
@@ -471,9 +468,8 @@
  * @param in_task_id     Identification of the incoming connection.
  * @param in_phone_hash  Identification of the incoming connection.
- * @param chandle        Handle of the opening IPC_M_CONNECT_ME_TO call.
- *                       If chandle is CAP_NIL, the connection was opened by
- *                       accepting the IPC_M_CONNECT_TO_ME call and this
- *                       function is called directly by the server.
- * @param call           Call data of the opening call.
+ * @param call           Call data of the opening call. If call is NULL,
+ *                       the connection was opened by accepting the
+ *                       IPC_M_CONNECT_TO_ME call and this function is
+ *                       called directly by the server.
  * @param handler        Connection handler.
  * @param data           Client argument to pass to the connection handler.
@@ -483,11 +479,10 @@
  */
 static fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
-    cap_call_handle_t chandle, ipc_call_t *call, async_port_handler_t handler,
-    void *data)
+    ipc_call_t *call, async_port_handler_t handler, void *data)
 {
 	connection_t *conn = malloc(sizeof(*conn));
 	if (!conn) {
-		if (chandle != CAP_NIL)
-			ipc_answer_0(chandle, ENOMEM);
+		if (call)
+			ipc_answer_0(call->cap_handle, ENOMEM);
 
 		return (uintptr_t) NULL;
@@ -497,5 +492,4 @@
 	conn->in_phone_hash = in_phone_hash;
 	list_initialize(&conn->msg_queue);
-	conn->chandle = chandle;
 	conn->close_chandle = CAP_NIL;
 	conn->handler = handler;
@@ -504,4 +498,6 @@
 	if (call)
 		conn->call = *call;
+	else
+		conn->call.cap_handle = CAP_NIL;
 
 	/* We will activate the fibril ASAP */
@@ -512,6 +508,6 @@
 		free(conn);
 
-		if (chandle != CAP_NIL)
-			ipc_answer_0(chandle, ENOMEM);
+		if (call)
+			ipc_answer_0(call->cap_handle, ENOMEM);
 
 		return (uintptr_t) NULL;
@@ -568,5 +564,5 @@
 	sysarg_t phone_hash = IPC_GET_ARG5(answer);
 	fid_t fid = async_new_connection(answer.in_task_id, phone_hash,
-	    CAP_NIL, NULL, handler, data);
+	    NULL, handler, data);
 	if (fid == (uintptr_t) NULL)
 		return ENOMEM;
@@ -637,6 +633,5 @@
  * timeouts are unregistered.
  *
- * @param chandle  Handle of the incoming call.
- * @param call     Data of the incoming call.
+ * @param call Data of the incoming call.
  *
  * @return False if the call doesn't match any connection.
@@ -644,5 +639,5 @@
  *
  */
-static bool route_call(cap_call_handle_t chandle, ipc_call_t *call)
+static bool route_call(ipc_call_t *call)
 {
 	assert(call);
@@ -667,10 +662,9 @@
 	}
 
-	msg->chandle = chandle;
 	msg->call = *call;
 	list_append(&msg->link, &conn->msg_queue);
 
 	if (IPC_GET_IMETHOD(*call) == IPC_M_PHONE_HUNGUP)
-		conn->close_chandle = chandle;
+		conn->close_chandle = call->cap_handle;
 
 	/* If the connection fibril is waiting for an event, activate it */
@@ -709,20 +703,34 @@
 		notification_t *notification = list_get_instance(
 		    list_first(&notification_queue), notification_t, qlink);
-		list_remove(&notification->qlink);
 
 		async_notification_handler_t handler = notification->handler;
 		void *arg = notification->arg;
-		ipc_call_t calldata = notification->calldata;
-		long count = notification->count;
-
-		notification->count = 0;
+
+		notification_msg_t *m = list_pop(&notification->msg_list,
+		    notification_msg_t, link);
+		assert(m);
+		ipc_call_t calldata = m->calldata;
+
+		notification_freelist_used--;
+
+		if (notification_freelist_total > 64 &&
+		    notification_freelist_total > 2 * notification_freelist_used) {
+			/* Going to free the structure if we have too much. */
+			notification_freelist_total--;
+		} else {
+			/* Otherwise add to freelist. */
+			list_append(&m->link, &notification_freelist);
+			m = NULL;
+		}
+
+		if (list_empty(&notification->msg_list))
+			list_remove(&notification->qlink);
 
 		futex_unlock(&notification_futex);
-
-		// FIXME: Pass count to the handler. It might be important.
-		(void) count;
 
 		if (handler)
 			handler(&calldata, arg);
+
+		free(m);
 	}
 
@@ -760,4 +768,19 @@
 	futex_lock(&notification_futex);
 
+	notification_msg_t *m = list_pop(&notification_freelist,
+	    notification_msg_t, link);
+
+	if (!m) {
+		futex_unlock(&notification_futex);
+		m = malloc(sizeof(notification_msg_t));
+		if (!m) {
+			DPRINTF("Out of memory.\n");
+			abort();
+		}
+
+		futex_lock(&notification_futex);
+		notification_freelist_total++;
+	}
+
 	ht_link_t *link = hash_table_find(&notification_hash_table,
 	    &IPC_GET_IMETHOD(*call));
@@ -765,5 +788,7 @@
 		/* Invalid notification. */
 		// TODO: Make sure this can't happen and turn it into assert.
+		notification_freelist_total--;
 		futex_unlock(&notification_futex);
+		free(m);
 		return;
 	}
@@ -772,14 +797,11 @@
 	    hash_table_get_inst(link, notification_t, htlink);
 
-	notification->count++;
-	notification->calldata = *call;
-
-	if (link_in_use(&notification->qlink)) {
-		/* Notification already queued. */
-		futex_unlock(&notification_futex);
-		return;
-	}
-
-	list_append(&notification->qlink, &notification_queue);
+	notification_freelist_used++;
+	m->calldata = *call;
+	list_append(&m->link, &notification->msg_list);
+
+	if (!link_in_use(&notification->qlink))
+		list_append(&notification->qlink, &notification_queue);
+
 	futex_unlock(&notification_futex);
 
@@ -802,4 +824,6 @@
 	notification->handler = handler;
 	notification->arg = arg;
+
+	list_initialize(&notification->msg_list);
 
 	fid_t fib = 0;
@@ -1011,5 +1035,5 @@
 	list_remove(&msg->link);
 
-	cap_call_handle_t chandle = msg->chandle;
+	cap_call_handle_t chandle = msg->call.cap_handle;
 	*call = msg->call;
 	free(msg);
@@ -1058,9 +1082,8 @@
  * Otherwise the call is routed to its connection fibril.
  *
- * @param chandle  Handle of the incoming call.
- * @param call     Data of the incoming call.
- *
- */
-static void handle_call(cap_call_handle_t chandle, ipc_call_t *call)
+ * @param call Data of the incoming call.
+ *
+ */
+static void handle_call(ipc_call_t *call)
 {
 	assert(call);
@@ -1069,5 +1092,5 @@
 		return;
 
-	if (chandle == CAP_NIL) {
+	if (call->cap_handle == CAP_NIL) {
 		if (call->flags & IPC_CALL_NOTIF) {
 			/* Kernel notification */
@@ -1087,15 +1110,15 @@
 		    async_get_port_handler(iface, 0, &data);
 
-		async_new_connection(call->in_task_id, in_phone_hash, chandle,
-		    call, handler, data);
+		async_new_connection(call->in_task_id, in_phone_hash, call,
+		    handler, data);
 		return;
 	}
 
 	/* Try to route the call through the connection hash table */
-	if (route_call(chandle, call))
+	if (route_call(call))
 		return;
 
 	/* Unknown call from unknown phone - hang it up */
-	ipc_answer_0(chandle, EHANGUP);
+	ipc_answer_0(call->cap_handle, EHANGUP);
 }
 
@@ -1178,5 +1201,5 @@
 
 		assert(rc == EOK);
-		handle_call(call.cap_handle, &call);
+		handle_call(&call);
 	}
 
@@ -1847,5 +1870,5 @@
 }
 
-_Noreturn void async_manager(void)
+__noreturn void async_manager(void)
 {
 	futex_lock(&async_futex);
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/generic/fibril_synch.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -44,6 +44,10 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <io/kio.h>
+
 #include "private/async.h"
 #include "private/fibril.h"
+
+static fibril_local bool deadlocked = false;
 
 static void optimize_execution_power(void)
@@ -62,4 +66,10 @@
 {
 	fibril_t *f = (fibril_t *) fibril_get_id();
+
+	if (deadlocked) {
+		kio_printf("Deadlock detected while printing deadlock. Aborting.\n");
+		abort();
+	}
+	deadlocked = true;
 
 	printf("Deadlock detected.\n");
Index: uspace/lib/c/generic/ubsan.c
===================================================================
--- uspace/lib/c/generic/ubsan.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/generic/ubsan.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -98,4 +98,5 @@
 #endif
 void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
+void __ubsan_handle_builtin_unreachable(struct unreachable_data *data);
 
 static void print_loc(const char *func, struct source_location *loc)
@@ -107,5 +108,5 @@
 		f += sizeof(func_prefix);
 
-	PRINTF("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
+	PRINTF("####### Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
 	    f, loc->file_name, loc->line, loc->column);
 }
@@ -115,4 +116,6 @@
 {
 	print_loc(__func__, &data->loc);
+	PRINTF("Type: %s, alignment: %lu, type_check_kind: %hhu\n",
+	    data->type->type_name, data->alignment, data->type_check_kind);
 	ubsan_panic();
 }
@@ -219,2 +222,9 @@
 	ubsan_panic();
 }
+
+void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/include/async.h	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -51,4 +51,6 @@
 #include <abi/cap.h>
 
+#include <_bits/__noreturn.h>
+
 typedef sysarg_t aid_t;
 typedef sysarg_t port_id_t;
@@ -108,5 +110,5 @@
 typedef struct async_exch async_exch_t;
 
-extern _Noreturn void async_manager(void);
+extern __noreturn void async_manager(void);
 
 #define async_get_call(data) \
Index: uspace/lib/c/include/futex.h
===================================================================
--- uspace/lib/c/include/futex.h	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/include/futex.h	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -45,5 +45,5 @@
 	atomic_t val;
 #ifdef CONFIG_DEBUG_FUTEX
-	_Atomic void *owner;
+	void *owner;
 #endif
 } futex_t;
Index: uspace/lib/c/include/setjmp.h
===================================================================
--- uspace/lib/c/include/setjmp.h	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/c/include/setjmp.h	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -35,12 +35,13 @@
 
 #include <libarch/fibril_context.h>
+#include <_bits/__noreturn.h>
 
 typedef context_t jmp_buf[1];
 
 extern int __setjmp(jmp_buf) __attribute__((returns_twice));
-extern _Noreturn void __longjmp(jmp_buf, int);
+extern __noreturn void __longjmp(jmp_buf, int);
 
 #define setjmp __setjmp
-extern _Noreturn void longjmp(jmp_buf, int);
+extern __noreturn void longjmp(jmp_buf, int);
 
 #endif
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/drv/generic/remote_usb.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -77,15 +77,19 @@
 		return EBADMEM;
 
-	usb_device_desc_t tmp_desc;
+	sysarg_t address, depth, speed, handle, iface;
 
 	const errno_t ret = async_req_1_5(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_MY_DESCRIPTION,
-	    (sysarg_t *) &tmp_desc.address,
-	    (sysarg_t *) &tmp_desc.depth,
-	    (sysarg_t *) &tmp_desc.speed,
-	    &tmp_desc.handle,
-	    (sysarg_t *) &tmp_desc.iface);
-	if (ret == EOK && desc)
-		*desc = tmp_desc;
+	    IPC_M_USB_GET_MY_DESCRIPTION, &address, &depth, &speed, &handle,
+	    &iface);
+	if (ret == EOK && desc) {
+		*desc = (usb_device_desc_t) {
+			.address = address,
+			.depth = depth,
+			.speed = speed,
+			.handle = handle,
+			.iface = iface,
+		};
+	}
+
 	return ret;
 }
Index: uspace/lib/softfloat/common.c
===================================================================
--- uspace/lib/softfloat/common.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/softfloat/common.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -252,5 +252,5 @@
 	int j;
 	for (j = 0; j < 32; j += 8) {
-		if (i & (0xFF << (24 - j))) {
+		if (i & (0xFFu << (24 - j))) {
 			return (j + count_zeroes8(i >> (24 - j)));
 		}
Index: uspace/lib/usb/include/usb/request.h
===================================================================
--- uspace/lib/usb/include/usb/request.h	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/usb/include/usb/request.h	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -75,13 +75,4 @@
 #define USB_SETUP_PACKET_SIZE 8
 
-/** Device request setup packet.
- * The setup packet describes the request.
- */
-typedef struct {
-	/** Request type.
-	 * The type combines transfer direction, request type and
-	 * intended recipient.
-	 */
-	uint8_t request_type;
 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7)
 #define SETUP_REQUEST_TYPE_HOST_TO_DEVICE (0 << 7)
@@ -94,21 +85,34 @@
     (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f))
 
-	/** Request identification. */
-	uint8_t request;
-	/** Main parameter to the request. */
-	union __attribute__((packed)) {
-		uint16_t value;
-		/* FIXME: add #ifdefs according to host endianness */
-		struct __attribute__((packed)) {
-			uint8_t value_low;
-			uint8_t value_high;
+/** Device request setup packet.
+ * The setup packet describes the request.
+ */
+typedef union {
+	struct __attribute__((packed)) {
+		/** Request type.
+		 * The type combines transfer direction, request type and
+		 * intended recipient.
+		 */
+		uint8_t request_type;
+
+		/** Request identification. */
+		uint8_t request;
+		/** Main parameter to the request. */
+		union __attribute__((packed)) {
+			uint16_t value;
+			/* FIXME: add #ifdefs according to host endianness */
+			struct __attribute__((packed)) {
+				uint8_t value_low;
+				uint8_t value_high;
+			};
 		};
+		/** Auxiliary parameter to the request.
+		 * Typically, it is offset to something.
+		 */
+		uint16_t index;
+		/** Length of extra data. */
+		uint16_t length;
 	};
-	/** Auxiliary parameter to the request.
-	 * Typically, it is offset to something.
-	 */
-	uint16_t index;
-	/** Length of extra data. */
-	uint16_t length;
+	uint64_t raw;
 } __attribute__((packed)) usb_device_request_setup_packet_t;
 
Index: uspace/lib/usbhost/src/usb2_bus.c
===================================================================
--- uspace/lib/usbhost/src/usb2_bus.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/usbhost/src/usb2_bus.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -142,5 +142,5 @@
 	usb_log_debug("Device(%d): Setting USB address.", address);
 	err = bus_device_send_batch_sync(dev, usb2_default_target, USB_DIRECTION_OUT,
-	    NULL, 0, *(uint64_t *)&set_address, "set address", NULL);
+	    NULL, 0, set_address.raw, "set address", NULL);
 	if (err) {
 		usb_log_error("Device(%d): Failed to set new address: %s.",
Index: uspace/lib/virtio/virtio-pci.h
===================================================================
--- uspace/lib/virtio/virtio-pci.h	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/virtio/virtio-pci.h	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -181,4 +181,8 @@
 } virtio_dev_t;
 
+extern errno_t virtio_setup_dma_bufs(unsigned int, size_t, bool, void *[],
+    uintptr_t []);
+extern void virtio_teardown_dma_bufs(void *[]);
+
 extern void virtio_virtq_desc_set(virtio_dev_t *vdev, uint16_t, uint16_t,
     uint64_t, uint32_t, uint16_t, uint16_t);
@@ -186,4 +190,9 @@
     uint16_t);
 
+extern void virtio_create_desc_free_list(virtio_dev_t *, uint16_t, uint16_t,
+    uint16_t *);
+extern uint16_t virtio_alloc_desc(virtio_dev_t *, uint16_t, uint16_t *);
+extern void virtio_free_desc(virtio_dev_t *, uint16_t, uint16_t *, uint16_t);
+
 extern void virtio_virtq_produce_available(virtio_dev_t *, uint16_t, uint16_t);
 extern bool virtio_virtq_consume_used(virtio_dev_t *, uint16_t, uint16_t *,
Index: uspace/lib/virtio/virtio.c
===================================================================
--- uspace/lib/virtio/virtio.c	(revision 1a9174e79190398c1f016ea605a18f97e673cafb)
+++ uspace/lib/virtio/virtio.c	(revision d3b2ffaddcda1e7c3db7a9f643033e62c4c947a0)
@@ -39,4 +39,58 @@
 #include <libarch/barrier.h>
 
+/** Allocate DMA buffers
+ *
+ * @param buffers[in]  Number of buffers to allocate.
+ * @param size[in]     Size of each buffer.
+ * @param write[in]    True if the buffers are writable by the driver, false
+ *                     otherwise.
+ * @param buf[out]     Output array holding virtual addresses of the allocated
+ *                     buffers.
+ * @param buf_p[out]   Output array holding physical addresses of the allocated
+ *                     buffers.
+ *
+ * The buffers can be deallocated by virtio_net_teardown_bufs().
+ *
+ * @return  EOK on success or error code.
+ */
+errno_t virtio_setup_dma_bufs(unsigned int buffers, size_t size,
+    bool write, void *buf[], uintptr_t buf_p[])
+{
+	/*
+	 * Allocate all buffers at once in one large chunk.
+	 */
+	void *virt = AS_AREA_ANY;
+	uintptr_t phys;
+	errno_t rc = dmamem_map_anonymous(buffers * size, 0,
+	    write ? AS_AREA_WRITE : AS_AREA_READ, 0, &phys, &virt);
+	if (rc != EOK)
+		return rc;
+
+	ddf_msg(LVL_NOTE, "DMA buffers: %p-%p", virt, virt + buffers * size);
+
+	/*
+	 * Calculate addresses of the individual buffers for easy access.
+	 */
+	for (unsigned i = 0; i < buffers; i++) {
+		buf[i] = virt + i * size;
+		buf_p[i] = phys + i * size;
+	}
+
+	return EOK;
+}
+
+/** Deallocate DMA buffers
+ *
+ * @param buf[in]  Array holding the virtual addresses of the DMA buffers
+ *                 previously allocated by virtio_net_setup_bufs().
+ */
+extern void virtio_teardown_dma_bufs(void *buf[])
+{
+	if (buf[0]) {
+		dmamem_unmap_anonymous(buf[0]);
+		buf[0] = NULL;
+	}
+}
+
 void virtio_virtq_desc_set(virtio_dev_t *vdev, uint16_t num, uint16_t descno,
     uint64_t addr, uint32_t len, uint16_t flags, uint16_t next)
@@ -57,4 +111,62 @@
 	return pio_read_le16(&d->next);
 }
+
+/** Create free descriptor list from the unused VIRTIO descriptors
+ *
+ * @param vdev[in]   VIRTIO device for which the free list will be created.
+ * @param num[in]    Index of the virtqueue for which the free list will be
+ *                   created.
+ * @param size[in]   Number of descriptors on the free list. The free list will
+ *                   contain descriptors starting from 0 to \a size - 1.
+ * @param head[out]  Variable that will hold the VIRTIO descriptor at the head
+ *                   of the free list.
+ */
+void virtio_create_desc_free_list(virtio_dev_t *vdev, uint16_t num,
+    uint16_t size, uint16_t *head)
+{
+	for (unsigned i = 0; i < size; i++) {
+		virtio_virtq_desc_set(vdev, num, i, 0, 0,
+		    VIRTQ_DESC_F_NEXT, (i + 1 == size) ? -1U : i + 1);
+	}
+	*head = 0;
+}
+
+/** Allocate a descriptor from the free list
+ *
+ * @param vdev[in]      VIRTIO device with the free list.
+ * @param num[in]       Index of the virtqueue with free list.
+ * @param head[in,out]  Head of the free list.
+ *
+ * @return  Allocated descriptor or 0xFFFF if the list is empty.
+ */
+uint16_t virtio_alloc_desc(virtio_dev_t *vdev, uint16_t num, uint16_t *head)
+{
+	virtq_t *q = &vdev->queues[num];
+	fibril_mutex_lock(&q->lock);
+	uint16_t descno = *head;
+	if (descno != (uint16_t) -1U)
+		*head = virtio_virtq_desc_get_next(vdev, num, descno);
+	fibril_mutex_unlock(&q->lock);
+	return descno;
+}
+
+/** Free a descriptor into the free list
+ *
+ * @param vdev[in]      VIRTIO device with the free list.
+ * @param num[in]       Index of the virtqueue with free list.
+ * @param head[in,out]  Head of the free list.
+ * @param descno[in]    The freed descriptor.
+ */
+void virtio_free_desc(virtio_dev_t *vdev, uint16_t num, uint16_t *head,
+    uint16_t descno)
+{
+	virtq_t *q = &vdev->queues[num];
+	fibril_mutex_lock(&q->lock);
+	virtio_virtq_desc_set(vdev, num, descno, 0, 0, VIRTQ_DESC_F_NEXT,
+	    *head);
+	*head = descno;
+	fibril_mutex_unlock(&q->lock);
+}
+
 
 void virtio_virtq_produce_available(virtio_dev_t *vdev, uint16_t num,
