diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 82d41b6..45498a2 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -13,8 +13,8 @@ CSCOPE = cscope
 TAGS = ctags
 
 OBJS	+= 8250-serial.o
-OBJS	+= blk-virtio.o
-OBJS	+= console-virtio.o
+OBJS	+= virtio-blk.o
+OBJS	+= virtio-console.o
 OBJS	+= cpuid.o
 OBJS	+= read-write.o
 OBJS	+= disk-image.o
diff --git a/tools/kvm/blk-virtio.c b/tools/kvm/blk-virtio.c
deleted file mode 100644
index 2eb9734..0000000
--- a/tools/kvm/blk-virtio.c
+++ /dev/null
@@ -1,293 +0,0 @@
-#include "kvm/blk-virtio.h"
-
-#include "kvm/virtio_pci.h"
-
-#include "kvm/disk-image.h"
-#include "kvm/virtio.h"
-#include "kvm/ioport.h"
-#include "kvm/util.h"
-#include "kvm/kvm.h"
-#include "kvm/pci.h"
-
-#include <linux/virtio_ring.h>
-#include <linux/virtio_blk.h>
-#include <inttypes.h>
-#include <assert.h>
-
-#define VIRTIO_BLK_IRQ		14
-
-#define NUM_VIRT_QUEUES		1
-
-#define VIRTIO_BLK_QUEUE_SIZE	128
-
-struct blk_device {
-	struct virtio_blk_config	blk_config;
-	uint32_t			host_features;
-	uint32_t			guest_features;
-	uint16_t			config_vector;
-	uint8_t				status;
-
-	/* virtio queue */
-	uint16_t			queue_selector;
-
-	struct virt_queue		virt_queues[NUM_VIRT_QUEUES];
-};
-
-#define DISK_SEG_MAX	126
-
-static struct blk_device blk_device = {
-	.blk_config		= (struct virtio_blk_config) {
-		/* VIRTIO_BLK_F_SEG_MAX */
-		.seg_max		= DISK_SEG_MAX,
-	},
-	/*
-	 * Note we don't set VIRTIO_BLK_F_GEOMETRY here so the
-	 * node kernel will compute disk geometry by own, the
-	 * same applies to VIRTIO_BLK_F_BLK_SIZE
-	 */
-	.host_features		= (1UL << VIRTIO_BLK_F_SEG_MAX),
-};
-
-static bool virtio_blk_config_in(void *data, unsigned long offset, int size, uint32_t count)
-{
-	uint8_t *config_space = (uint8_t *) &blk_device.blk_config;
-
-	if (size != 1 || count != 1)
-		return false;
-
-	ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]);
-
-	return true;
-}
-
-static bool blk_virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
-{
-	unsigned long offset;
-
-	offset		= port - IOPORT_VIRTIO_BLK;
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, blk_device.host_features);
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-		return false;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, blk_device.virt_queues[blk_device.queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTIO_BLK_QUEUE_SIZE);
-		break;
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		return false;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, blk_device.status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, 0x1);
-		kvm__irq_line(self, VIRTIO_BLK_IRQ, 0);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		ioport__write16(data, blk_device.config_vector);
-		break;
-	default:
-		return virtio_blk_config_in(data, offset, size, count);
-	};
-
-	return true;
-}
-
-static bool blk_virtio_request(struct kvm *self, struct virt_queue *queue)
-{
-	struct vring_used_elem *used_elem;
-	struct virtio_blk_outhdr *req;
-	uint16_t desc_block_last;
-	struct vring_desc *desc;
-	uint16_t desc_status;
-	uint16_t desc_block;
-	uint32_t block_len;
-	uint32_t block_cnt;
-	uint16_t desc_hdr;
-	uint8_t *status;
-	void *block;
-	int err;
-	int err_cnt;
-
-	/* header */
-	desc_hdr		= virt_queue__pop(queue);
-
-	if (desc_hdr >= queue->vring.num) {
-		warning("fatal I/O error");
-		return false;
-	}
-
-	desc			= virt_queue__get_desc(queue, desc_hdr);
-	assert(!(desc->flags & VRING_DESC_F_INDIRECT));
-
-	req			= guest_flat_to_host(self, desc->addr);
-
-	/* status */
-	desc_status		= desc_hdr;
-
-	do {
-		desc_block_last	= desc_status;
-		desc_status	= virt_queue__get_desc(queue, desc_status)->next;
-
-		if (desc_status >= queue->vring.num) {
-			warning("fatal I/O error");
-			return false;
-		}
-
-		desc		= virt_queue__get_desc(queue, desc_status);
-		assert(!(desc->flags & VRING_DESC_F_INDIRECT));
-
-	} while (desc->flags & VRING_DESC_F_NEXT);
-
-	status			= guest_flat_to_host(self, desc->addr);
-
-	/* block */
-	desc_block		= desc_hdr;
-	block_cnt		= 0;
-	err_cnt			= 0;
-
-	do {
-		desc_block	= virt_queue__get_desc(queue, desc_block)->next;
-
-		desc		= virt_queue__get_desc(queue, desc_block);
-		assert(!(desc->flags & VRING_DESC_F_INDIRECT));
-
-		block		= guest_flat_to_host(self, desc->addr);
-		block_len	= desc->len;
-
-		switch (req->type) {
-		case VIRTIO_BLK_T_IN:
-			err	= disk_image__read_sector(self->disk_image, req->sector, block, block_len);
-			break;
-		case VIRTIO_BLK_T_OUT:
-			err	= disk_image__write_sector(self->disk_image, req->sector, block, block_len);
-			break;
-		default:
-			warning("request type %d", req->type);
-			err	= -1;
-		}
-
-		if (err)
-			err_cnt++;
-
-		req->sector	+= block_len >> SECTOR_SHIFT;
-		block_cnt	+= block_len;
-
-		if (desc_block == desc_block_last)
-			break;
-
-		if (desc_block >= queue->vring.num) {
-			warning("fatal I/O error");
-			return false;
-		}
-
-	} while (true);
-
-	*status			= err_cnt ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
-
-	used_elem		= virt_queue__get_used_elem(queue);
-	used_elem->id		= desc_hdr;
-	used_elem->len		= block_cnt;
-
-	return true;
-}
-
-static bool blk_virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
-{
-	unsigned long offset;
-
-	offset		= port - IOPORT_VIRTIO_BLK;
-
-	switch (offset) {
-	case VIRTIO_PCI_GUEST_FEATURES:
-		blk_device.guest_features	= ioport__read32(data);
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		void *p;
-
-		queue			= &blk_device.virt_queues[blk_device.queue_selector];
-
-		queue->pfn		= ioport__read32(data);
-
-		p			= guest_flat_to_host(self, queue->pfn << 12);
-
-		vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 4096);
-
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		blk_device.queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		struct virt_queue *queue;
-		uint16_t queue_index;
-
-		queue_index		= ioport__read16(data);
-
-		queue			= &blk_device.virt_queues[queue_index];
-
-		while (queue->vring.avail->idx != queue->last_avail_idx) {
-			if (!blk_virtio_request(self, queue))
-				return false;
-		}
-		kvm__irq_line(self, VIRTIO_BLK_IRQ, 1);
-
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		blk_device.status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		blk_device.config_vector	= VIRTIO_MSI_NO_VECTOR;
-		break;
-	case VIRTIO_MSI_QUEUE_VECTOR:
-		break;
-	default:
-		return false;
-	};
-
-	return true;
-}
-
-static struct ioport_operations blk_virtio_io_ops = {
-	.io_in		= blk_virtio_in,
-	.io_out		= blk_virtio_out,
-};
-
-#define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
-#define PCI_DEVICE_ID_VIRTIO_BLK		0x1001
-#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
-#define PCI_SUBSYSTEM_ID_VIRTIO_BLK		0x0002
-
-static struct pci_device_header blk_virtio_pci_device = {
-	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-	.device_id		= PCI_DEVICE_ID_VIRTIO_BLK,
-	.header_type		= PCI_HEADER_TYPE_NORMAL,
-	.revision_id		= 0,
-	.class			= 0x010000,
-	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-	.subsys_id		= PCI_SUBSYSTEM_ID_VIRTIO_BLK,
-	.bar[0]			= IOPORT_VIRTIO_BLK | PCI_BASE_ADDRESS_SPACE_IO,
-	.irq_pin		= 1,
-	.irq_line		= VIRTIO_BLK_IRQ,
-};
-
-#define PCI_VIRTIO_BLK_DEVNUM 1
-
-void blk_virtio__init(struct kvm *self)
-{
-	if (!self->disk_image)
-		return;
-
-	blk_device.blk_config.capacity = self->disk_image->size / SECTOR_SIZE;
-
-	pci__register(&blk_virtio_pci_device, PCI_VIRTIO_BLK_DEVNUM);
-
-	ioport__register(IOPORT_VIRTIO_BLK, &blk_virtio_io_ops, IOPORT_VIRTIO_BLK_SIZE);
-}
diff --git a/tools/kvm/console-virtio.c b/tools/kvm/console-virtio.c
deleted file mode 100644
index 3926536..0000000
--- a/tools/kvm/console-virtio.c
+++ /dev/null
@@ -1,218 +0,0 @@
-#include "kvm/console-virtio.h"
-#include "kvm/virtio_pci.h"
-#include "kvm/disk-image.h"
-#include "kvm/virtio.h"
-#include "kvm/ioport.h"
-#include "kvm/util.h"
-#include "kvm/term.h"
-#include "kvm/kvm.h"
-#include "kvm/pci.h"
-
-#include <linux/virtio_console.h>
-#include <linux/virtio_ring.h>
-#include <linux/virtio_blk.h>
-
-#include <sys/uio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <inttypes.h>
-#include <termios.h>
-#include <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#define VIRTIO_CONSOLE_IRQ		14
-#define VIRTIO_CONSOLE_QUEUE_SIZE	128
-#define VIRTIO_CONSOLE_NUM_QUEUES	2
-#define VIRTIO_CONSOLE_RX_QUEUE		0
-#define VIRTIO_CONSOLE_TX_QUEUE		1
-#define PCI_VIRTIO_CONSOLE_DEVNUM	2
-
-struct console_device {
-	struct virt_queue		vqs[VIRTIO_CONSOLE_NUM_QUEUES];
-	struct virtio_console_config	console_config;
-	uint32_t			host_features;
-	uint32_t			guest_features;
-	uint16_t			config_vector;
-	uint8_t				status;
-	uint16_t			queue_selector;
-};
-
-static struct console_device console_device = {
-	.console_config = {
-		.cols		= 80,
-		.rows		= 24,
-		.max_nr_ports	= 1,
-	},
-
-	.host_features		= 0,
-};
-
-/*
- * Interrupts are injected for hvc0 only.
- */
-void virtio_console__inject_interrupt(struct kvm *self)
-{
-	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
-	struct virt_queue *vq;
-	uint16_t out, in;
-	uint16_t head;
-	int len;
-
-	vq = &console_device.vqs[VIRTIO_CONSOLE_RX_QUEUE];
-
-	if (term_readable(CONSOLE_VIRTIO) && virt_queue__available(vq)) {
-		head = virt_queue__get_iov(vq, iov, &out, &in, self);
-		len = term_getc_iov(CONSOLE_VIRTIO, iov, in);
-		virt_queue__set_used_elem(vq, head, len);
-		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1);
-	}
-}
-
-static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count)
-{
-	uint8_t *config_space = (uint8_t *) &console_device.console_config;
-
-	if (size != 1 || count != 1)
-		return false;
-
-	if ((offset - VIRTIO_PCI_CONFIG_NOMSI) > sizeof(struct virtio_console_config))
-		error("config offset is too big: %li", offset - VIRTIO_PCI_CONFIG_NOMSI);
-
-	ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]);
-
-	return true;
-}
-
-static bool virtio_console_pci_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
-{
-	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, console_device.host_features);
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-		return false;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, console_device.vqs[console_device.queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTIO_CONSOLE_QUEUE_SIZE);
-		break;
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		return false;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, console_device.status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, 0x1);
-		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 0);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		ioport__write16(data, console_device.config_vector);
-		break;
-	default:
-		return virtio_console_pci_io_device_specific_in(data, offset, size, count);
-	};
-
-	return true;
-}
-
-static void virtio_console_handle_callback(struct kvm *self, uint16_t queue_index)
-{
-	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
-	struct virt_queue *vq;
-	uint16_t out, in;
-	uint16_t head;
-	uint32_t len;
-
-	vq = &console_device.vqs[queue_index];
-
-	if (queue_index == VIRTIO_CONSOLE_TX_QUEUE) {
-
-		while (virt_queue__available(vq)) {
-			head = virt_queue__get_iov(vq, iov, &out, &in, self);
-			len = term_putc_iov(CONSOLE_VIRTIO, iov, out);
-			virt_queue__set_used_elem(vq, head, len);
-		}
-
-		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1);
-	}
-}
-
-static bool virtio_console_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
-{
-	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
-
-	switch (offset) {
-	case VIRTIO_PCI_GUEST_FEATURES:
-		console_device.guest_features	= ioport__read32(data);
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		void *p;
-
-		assert(console_device.queue_selector < VIRTIO_CONSOLE_NUM_QUEUES);
-
-		queue		= &console_device.vqs[console_device.queue_selector];
-		queue->pfn	= ioport__read32(data);
-		p		= guest_flat_to_host(self, queue->pfn << 12);
-
-		vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, 4096);
-
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		console_device.queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		uint16_t queue_index;
-		queue_index	= ioport__read16(data);
-		virtio_console_handle_callback(self, queue_index);
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		console_device.status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		console_device.config_vector	= VIRTIO_MSI_NO_VECTOR;
-		break;
-	case VIRTIO_MSI_QUEUE_VECTOR:
-		break;
-	default:
-		return false;
-	};
-
-	return true;
-}
-
-static struct ioport_operations virtio_console_io_ops = {
-	.io_in	= virtio_console_pci_io_in,
-	.io_out	= virtio_console_pci_io_out,
-};
-
-#define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
-#define PCI_DEVICE_ID_VIRTIO_CONSOLE		0x1002
-#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
-#define PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE		0x0003
-
-static struct pci_device_header virtio_console_pci_device = {
-	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-	.device_id		= PCI_DEVICE_ID_VIRTIO_CONSOLE,
-	.header_type		= PCI_HEADER_TYPE_NORMAL,
-	.revision_id		= 0,
-	.class			= (0x07 << 8) | (0x80 << 4) | (0x0 << 0),
-	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-	.subsys_id		= PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE,
-	.bar[0]			= IOPORT_VIRTIO_CONSOLE | PCI_BASE_ADDRESS_SPACE_IO,
-	.irq_pin		= 3,
-	.irq_line		= VIRTIO_CONSOLE_IRQ,
-};
-
-void virtio_console__init(struct kvm *self)
-{
-	pci__register(&virtio_console_pci_device, PCI_VIRTIO_CONSOLE_DEVNUM);
-	ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE);
-}
diff --git a/tools/kvm/include/kvm/blk-virtio.h b/tools/kvm/include/kvm/blk-virtio.h
deleted file mode 100644
index 02f39df..0000000
--- a/tools/kvm/include/kvm/blk-virtio.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef KVM__BLK_VIRTIO_H
-#define KVM__BLK_VIRTIO_H
-
-struct kvm;
-
-void blk_virtio__init(struct kvm *self);
-
-#endif /* KVM__BLK_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/console-virtio.h b/tools/kvm/include/kvm/console-virtio.h
deleted file mode 100644
index d2e5d19..0000000
--- a/tools/kvm/include/kvm/console-virtio.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef KVM__CONSOLE_VIRTIO_H
-#define KVM__CONSOLE_VIRTIO_H
-
-struct kvm;
-
-void virtio_console__init(struct kvm *self);
-void virtio_console__inject_interrupt(struct kvm *self);
-
-#endif /* KVM__CONSOLE_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-blk.h b/tools/kvm/include/kvm/virtio-blk.h
new file mode 100644
index 0000000..f82bbc7
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-blk.h
@@ -0,0 +1,8 @@
+#ifndef KVM__BLK_VIRTIO_H
+#define KVM__BLK_VIRTIO_H
+
+struct kvm;
+
+void virtio_blk__init(struct kvm *self);
+
+#endif /* KVM__BLK_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-console.h b/tools/kvm/include/kvm/virtio-console.h
new file mode 100644
index 0000000..d2e5d19
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-console.h
@@ -0,0 +1,9 @@
+#ifndef KVM__CONSOLE_VIRTIO_H
+#define KVM__CONSOLE_VIRTIO_H
+
+struct kvm;
+
+void virtio_console__init(struct kvm *self);
+void virtio_console__inject_interrupt(struct kvm *self);
+
+#endif /* KVM__CONSOLE_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-pci.h b/tools/kvm/include/kvm/virtio-pci.h
new file mode 100644
index 0000000..8098090
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-pci.h
@@ -0,0 +1,59 @@
+/*
+ * Virtio PCI driver
+ *
+ * This module allows virtio devices to be used over a virtual PCI device.
+ * This can be used with QEMU based VMMs like KVM or Xen.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori  <aliguori@us.ibm.com>
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ */
+
+#ifndef _LINUX_VIRTIO_PCI_H
+#define _LINUX_VIRTIO_PCI_H
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES	0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES	4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN		8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM		12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL		14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY		16
+
+/* An 8-bit device status register.  */
+#define VIRTIO_PCI_STATUS		18
+
+/* An 8-bit r/o interrupt status register.  Reading the value will return the
+ * current contents of the ISR and will also clear it.  This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR			19
+
+/* MSI-X registers: only enabled if MSI-X is enabled. */
+/* A 16-bit vector for configuration changes. */
+#define VIRTIO_MSI_CONFIG_VECTOR        20
+
+/* A 16-bit vector for selected queue notifications. */
+#define VIRTIO_MSI_QUEUE_VECTOR         22
+
+/* Vector value used to disable MSI for queue */
+#define VIRTIO_MSI_NO_VECTOR            0xffff
+
+/* Config space size */
+#define VIRTIO_PCI_CONFIG_NOMSI         20
+#define VIRTIO_PCI_CONFIG_MSI           24
+
+#endif /* _LINUX_VIRTIO_PCI_H */
diff --git a/tools/kvm/include/kvm/virtio_pci.h b/tools/kvm/include/kvm/virtio_pci.h
deleted file mode 100644
index 8098090..0000000
--- a/tools/kvm/include/kvm/virtio_pci.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Virtio PCI driver
- *
- * This module allows virtio devices to be used over a virtual PCI device.
- * This can be used with QEMU based VMMs like KVM or Xen.
- *
- * Copyright IBM Corp. 2007
- *
- * Authors:
- *  Anthony Liguori  <aliguori@us.ibm.com>
- *
- * This header is BSD licensed so anyone can use the definitions to implement
- * compatible drivers/servers.
- */
-
-#ifndef _LINUX_VIRTIO_PCI_H
-#define _LINUX_VIRTIO_PCI_H
-
-/* A 32-bit r/o bitmask of the features supported by the host */
-#define VIRTIO_PCI_HOST_FEATURES	0
-
-/* A 32-bit r/w bitmask of features activated by the guest */
-#define VIRTIO_PCI_GUEST_FEATURES	4
-
-/* A 32-bit r/w PFN for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_PFN		8
-
-/* A 16-bit r/o queue size for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_NUM		12
-
-/* A 16-bit r/w queue selector */
-#define VIRTIO_PCI_QUEUE_SEL		14
-
-/* A 16-bit r/w queue notifier */
-#define VIRTIO_PCI_QUEUE_NOTIFY		16
-
-/* An 8-bit device status register.  */
-#define VIRTIO_PCI_STATUS		18
-
-/* An 8-bit r/o interrupt status register.  Reading the value will return the
- * current contents of the ISR and will also clear it.  This is effectively
- * a read-and-acknowledge. */
-#define VIRTIO_PCI_ISR			19
-
-/* MSI-X registers: only enabled if MSI-X is enabled. */
-/* A 16-bit vector for configuration changes. */
-#define VIRTIO_MSI_CONFIG_VECTOR        20
-
-/* A 16-bit vector for selected queue notifications. */
-#define VIRTIO_MSI_QUEUE_VECTOR         22
-
-/* Vector value used to disable MSI for queue */
-#define VIRTIO_MSI_NO_VECTOR            0xffff
-
-/* Config space size */
-#define VIRTIO_PCI_CONFIG_NOMSI         20
-#define VIRTIO_PCI_CONFIG_MSI           24
-
-#endif /* _LINUX_VIRTIO_PCI_H */
diff --git a/tools/kvm/main.c b/tools/kvm/main.c
index d8f0c09..7401f6f 100644
--- a/tools/kvm/main.c
+++ b/tools/kvm/main.c
@@ -1,8 +1,8 @@
 #include "kvm/kvm.h"
 
 #include "kvm/8250-serial.h"
-#include "kvm/blk-virtio.h"
-#include "kvm/console-virtio.h"
+#include "kvm/virtio-blk.h"
+#include "kvm/virtio-console.h"
 #include "kvm/disk-image.h"
 #include "kvm/util.h"
 #include "kvm/pci.h"
@@ -145,7 +145,7 @@ int main(int argc, char *argv[])
 
 	pci__init();
 
-	blk_virtio__init(kvm);
+	virtio_blk__init(kvm);
 
 	virtio_console__init(kvm);
 
diff --git a/tools/kvm/virtio-blk.c b/tools/kvm/virtio-blk.c
new file mode 100644
index 0000000..a41d5ac
--- /dev/null
+++ b/tools/kvm/virtio-blk.c
@@ -0,0 +1,293 @@
+#include "kvm/virtio-blk.h"
+
+#include "kvm/virtio-pci.h"
+
+#include "kvm/disk-image.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#define VIRTIO_BLK_IRQ		14
+
+#define NUM_VIRT_QUEUES		1
+
+#define VIRTIO_BLK_QUEUE_SIZE	128
+
+struct blk_device {
+	struct virtio_blk_config	blk_config;
+	uint32_t			host_features;
+	uint32_t			guest_features;
+	uint16_t			config_vector;
+	uint8_t				status;
+
+	/* virtio queue */
+	uint16_t			queue_selector;
+
+	struct virt_queue		virt_queues[NUM_VIRT_QUEUES];
+};
+
+#define DISK_SEG_MAX	126
+
+static struct blk_device blk_device = {
+	.blk_config		= (struct virtio_blk_config) {
+		/* VIRTIO_BLK_F_SEG_MAX */
+		.seg_max		= DISK_SEG_MAX,
+	},
+	/*
+	 * Note we don't set VIRTIO_BLK_F_GEOMETRY here so the
+	 * node kernel will compute disk geometry by own, the
+	 * same applies to VIRTIO_BLK_F_BLK_SIZE
+	 */
+	.host_features		= (1UL << VIRTIO_BLK_F_SEG_MAX),
+};
+
+static bool virtio_blk_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count)
+{
+	uint8_t *config_space = (uint8_t *) &blk_device.blk_config;
+
+	if (size != 1 || count != 1)
+		return false;
+
+	ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]);
+
+	return true;
+}
+
+static bool virtio_blk_pci_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+	unsigned long offset;
+
+	offset		= port - IOPORT_VIRTIO_BLK;
+
+	switch (offset) {
+	case VIRTIO_PCI_HOST_FEATURES:
+		ioport__write32(data, blk_device.host_features);
+		break;
+	case VIRTIO_PCI_GUEST_FEATURES:
+		return false;
+	case VIRTIO_PCI_QUEUE_PFN:
+		ioport__write32(data, blk_device.virt_queues[blk_device.queue_selector].pfn);
+		break;
+	case VIRTIO_PCI_QUEUE_NUM:
+		ioport__write16(data, VIRTIO_BLK_QUEUE_SIZE);
+		break;
+	case VIRTIO_PCI_QUEUE_SEL:
+	case VIRTIO_PCI_QUEUE_NOTIFY:
+		return false;
+	case VIRTIO_PCI_STATUS:
+		ioport__write8(data, blk_device.status);
+		break;
+	case VIRTIO_PCI_ISR:
+		ioport__write8(data, 0x1);
+		kvm__irq_line(self, VIRTIO_BLK_IRQ, 0);
+		break;
+	case VIRTIO_MSI_CONFIG_VECTOR:
+		ioport__write16(data, blk_device.config_vector);
+		break;
+	default:
+		return virtio_blk_pci_io_device_specific_in(data, offset, size, count);
+	};
+
+	return true;
+}
+
+static bool virtio_blk_request(struct kvm *self, struct virt_queue *queue)
+{
+	struct vring_used_elem *used_elem;
+	struct virtio_blk_outhdr *req;
+	uint16_t desc_block_last;
+	struct vring_desc *desc;
+	uint16_t desc_status;
+	uint16_t desc_block;
+	uint32_t block_len;
+	uint32_t block_cnt;
+	uint16_t desc_hdr;
+	uint8_t *status;
+	void *block;
+	int err;
+	int err_cnt;
+
+	/* header */
+	desc_hdr		= virt_queue__pop(queue);
+
+	if (desc_hdr >= queue->vring.num) {
+		warning("fatal I/O error");
+		return false;
+	}
+
+	desc			= virt_queue__get_desc(queue, desc_hdr);
+	assert(!(desc->flags & VRING_DESC_F_INDIRECT));
+
+	req			= guest_flat_to_host(self, desc->addr);
+
+	/* status */
+	desc_status		= desc_hdr;
+
+	do {
+		desc_block_last	= desc_status;
+		desc_status	= virt_queue__get_desc(queue, desc_status)->next;
+
+		if (desc_status >= queue->vring.num) {
+			warning("fatal I/O error");
+			return false;
+		}
+
+		desc		= virt_queue__get_desc(queue, desc_status);
+		assert(!(desc->flags & VRING_DESC_F_INDIRECT));
+
+	} while (desc->flags & VRING_DESC_F_NEXT);
+
+	status			= guest_flat_to_host(self, desc->addr);
+
+	/* block */
+	desc_block		= desc_hdr;
+	block_cnt		= 0;
+	err_cnt			= 0;
+
+	do {
+		desc_block	= virt_queue__get_desc(queue, desc_block)->next;
+
+		desc		= virt_queue__get_desc(queue, desc_block);
+		assert(!(desc->flags & VRING_DESC_F_INDIRECT));
+
+		block		= guest_flat_to_host(self, desc->addr);
+		block_len	= desc->len;
+
+		switch (req->type) {
+		case VIRTIO_BLK_T_IN:
+			err	= disk_image__read_sector(self->disk_image, req->sector, block, block_len);
+			break;
+		case VIRTIO_BLK_T_OUT:
+			err	= disk_image__write_sector(self->disk_image, req->sector, block, block_len);
+			break;
+		default:
+			warning("request type %d", req->type);
+			err	= -1;
+		}
+
+		if (err)
+			err_cnt++;
+
+		req->sector	+= block_len >> SECTOR_SHIFT;
+		block_cnt	+= block_len;
+
+		if (desc_block == desc_block_last)
+			break;
+
+		if (desc_block >= queue->vring.num) {
+			warning("fatal I/O error");
+			return false;
+		}
+
+	} while (true);
+
+	*status			= err_cnt ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
+
+	used_elem		= virt_queue__get_used_elem(queue);
+	used_elem->id		= desc_hdr;
+	used_elem->len		= block_cnt;
+
+	return true;
+}
+
+static bool virtio_blk_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+	unsigned long offset;
+
+	offset		= port - IOPORT_VIRTIO_BLK;
+
+	switch (offset) {
+	case VIRTIO_PCI_GUEST_FEATURES:
+		blk_device.guest_features	= ioport__read32(data);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN: {
+		struct virt_queue *queue;
+		void *p;
+
+		queue			= &blk_device.virt_queues[blk_device.queue_selector];
+
+		queue->pfn		= ioport__read32(data);
+
+		p			= guest_flat_to_host(self, queue->pfn << 12);
+
+		vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 4096);
+
+		break;
+	}
+	case VIRTIO_PCI_QUEUE_SEL:
+		blk_device.queue_selector	= ioport__read16(data);
+		break;
+	case VIRTIO_PCI_QUEUE_NOTIFY: {
+		struct virt_queue *queue;
+		uint16_t queue_index;
+
+		queue_index		= ioport__read16(data);
+
+		queue			= &blk_device.virt_queues[queue_index];
+
+		while (queue->vring.avail->idx != queue->last_avail_idx) {
+			if (!virtio_blk_request(self, queue))
+				return false;
+		}
+		kvm__irq_line(self, VIRTIO_BLK_IRQ, 1);
+
+		break;
+	}
+	case VIRTIO_PCI_STATUS:
+		blk_device.status		= ioport__read8(data);
+		break;
+	case VIRTIO_MSI_CONFIG_VECTOR:
+		blk_device.config_vector	= VIRTIO_MSI_NO_VECTOR;
+		break;
+	case VIRTIO_MSI_QUEUE_VECTOR:
+		break;
+	default:
+		return false;
+	};
+
+	return true;
+}
+
+static struct ioport_operations virtio_blk_io_ops = {
+	.io_in		= virtio_blk_pci_io_in,
+	.io_out		= virtio_blk_pci_io_out,
+};
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
+#define PCI_DEVICE_ID_VIRTIO_BLK		0x1001
+#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
+#define PCI_SUBSYSTEM_ID_VIRTIO_BLK		0x0002
+
+static struct pci_device_header virtio_blk_pci_device = {
+	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
+	.device_id		= PCI_DEVICE_ID_VIRTIO_BLK,
+	.header_type		= PCI_HEADER_TYPE_NORMAL,
+	.revision_id		= 0,
+	.class			= 0x010000,
+	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+	.subsys_id		= PCI_SUBSYSTEM_ID_VIRTIO_BLK,
+	.bar[0]			= IOPORT_VIRTIO_BLK | PCI_BASE_ADDRESS_SPACE_IO,
+	.irq_pin		= 1,
+	.irq_line		= VIRTIO_BLK_IRQ,
+};
+
+#define PCI_VIRTIO_BLK_DEVNUM 1
+
+void virtio_blk__init(struct kvm *self)
+{
+	if (!self->disk_image)
+		return;
+
+	blk_device.blk_config.capacity = self->disk_image->size / SECTOR_SIZE;
+
+	pci__register(&virtio_blk_pci_device, PCI_VIRTIO_BLK_DEVNUM);
+
+	ioport__register(IOPORT_VIRTIO_BLK, &virtio_blk_io_ops, IOPORT_VIRTIO_BLK_SIZE);
+}
diff --git a/tools/kvm/virtio-console.c b/tools/kvm/virtio-console.c
new file mode 100644
index 0000000..fd79c61
--- /dev/null
+++ b/tools/kvm/virtio-console.c
@@ -0,0 +1,218 @@
+#include "kvm/virtio-console.h"
+#include "kvm/virtio-pci.h"
+#include "kvm/disk-image.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+
+#include <linux/virtio_console.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <termios.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define VIRTIO_CONSOLE_IRQ		14
+#define VIRTIO_CONSOLE_QUEUE_SIZE	128
+#define VIRTIO_CONSOLE_NUM_QUEUES	2
+#define VIRTIO_CONSOLE_RX_QUEUE		0
+#define VIRTIO_CONSOLE_TX_QUEUE		1
+#define PCI_VIRTIO_CONSOLE_DEVNUM	2
+
+struct console_device {
+	struct virt_queue		vqs[VIRTIO_CONSOLE_NUM_QUEUES];
+	struct virtio_console_config	console_config;
+	uint32_t			host_features;
+	uint32_t			guest_features;
+	uint16_t			config_vector;
+	uint8_t				status;
+	uint16_t			queue_selector;
+};
+
+static struct console_device console_device = {
+	.console_config = {
+		.cols		= 80,
+		.rows		= 24,
+		.max_nr_ports	= 1,
+	},
+
+	.host_features		= 0,
+};
+
+/*
+ * Interrupts are injected for hvc0 only.
+ */
+void virtio_console__inject_interrupt(struct kvm *self)
+{
+	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+	struct virt_queue *vq;
+	uint16_t out, in;
+	uint16_t head;
+	int len;
+
+	vq = &console_device.vqs[VIRTIO_CONSOLE_RX_QUEUE];
+
+	if (term_readable(CONSOLE_VIRTIO) && virt_queue__available(vq)) {
+		head = virt_queue__get_iov(vq, iov, &out, &in, self);
+		len = term_getc_iov(CONSOLE_VIRTIO, iov, in);
+		virt_queue__set_used_elem(vq, head, len);
+		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1);
+	}
+}
+
+static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count)
+{
+	uint8_t *config_space = (uint8_t *) &console_device.console_config;
+
+	if (size != 1 || count != 1)
+		return false;
+
+	if ((offset - VIRTIO_PCI_CONFIG_NOMSI) > sizeof(struct virtio_console_config))
+		error("config offset is too big: %li", offset - VIRTIO_PCI_CONFIG_NOMSI);
+
+	ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]);
+
+	return true;
+}
+
+static bool virtio_console_pci_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
+
+	switch (offset) {
+	case VIRTIO_PCI_HOST_FEATURES:
+		ioport__write32(data, console_device.host_features);
+		break;
+	case VIRTIO_PCI_GUEST_FEATURES:
+		return false;
+	case VIRTIO_PCI_QUEUE_PFN:
+		ioport__write32(data, console_device.vqs[console_device.queue_selector].pfn);
+		break;
+	case VIRTIO_PCI_QUEUE_NUM:
+		ioport__write16(data, VIRTIO_CONSOLE_QUEUE_SIZE);
+		break;
+	case VIRTIO_PCI_QUEUE_SEL:
+	case VIRTIO_PCI_QUEUE_NOTIFY:
+		return false;
+	case VIRTIO_PCI_STATUS:
+		ioport__write8(data, console_device.status);
+		break;
+	case VIRTIO_PCI_ISR:
+		ioport__write8(data, 0x1);
+		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 0);
+		break;
+	case VIRTIO_MSI_CONFIG_VECTOR:
+		ioport__write16(data, console_device.config_vector);
+		break;
+	default:
+		return virtio_console_pci_io_device_specific_in(data, offset, size, count);
+	};
+
+	return true;
+}
+
+static void virtio_console_handle_callback(struct kvm *self, uint16_t queue_index)
+{
+	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+	struct virt_queue *vq;
+	uint16_t out, in;
+	uint16_t head;
+	uint32_t len;
+
+	vq = &console_device.vqs[queue_index];
+
+	if (queue_index == VIRTIO_CONSOLE_TX_QUEUE) {
+
+		while (virt_queue__available(vq)) {
+			head = virt_queue__get_iov(vq, iov, &out, &in, self);
+			len = term_putc_iov(CONSOLE_VIRTIO, iov, out);
+			virt_queue__set_used_elem(vq, head, len);
+		}
+
+		kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1);
+	}
+}
+
+static bool virtio_console_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
+
+	switch (offset) {
+	case VIRTIO_PCI_GUEST_FEATURES:
+		console_device.guest_features	= ioport__read32(data);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN: {
+		struct virt_queue *queue;
+		void *p;
+
+		assert(console_device.queue_selector < VIRTIO_CONSOLE_NUM_QUEUES);
+
+		queue		= &console_device.vqs[console_device.queue_selector];
+		queue->pfn	= ioport__read32(data);
+		p		= guest_flat_to_host(self, queue->pfn << 12);
+
+		vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, 4096);
+
+		break;
+	}
+	case VIRTIO_PCI_QUEUE_SEL:
+		console_device.queue_selector	= ioport__read16(data);
+		break;
+	case VIRTIO_PCI_QUEUE_NOTIFY: {
+		uint16_t queue_index;
+		queue_index	= ioport__read16(data);
+		virtio_console_handle_callback(self, queue_index);
+		break;
+	}
+	case VIRTIO_PCI_STATUS:
+		console_device.status		= ioport__read8(data);
+		break;
+	case VIRTIO_MSI_CONFIG_VECTOR:
+		console_device.config_vector	= VIRTIO_MSI_NO_VECTOR;
+		break;
+	case VIRTIO_MSI_QUEUE_VECTOR:
+		break;
+	default:
+		return false;
+	};
+
+	return true;
+}
+
+static struct ioport_operations virtio_console_io_ops = {
+	.io_in	= virtio_console_pci_io_in,
+	.io_out	= virtio_console_pci_io_out,
+};
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
+#define PCI_DEVICE_ID_VIRTIO_CONSOLE		0x1002
+#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
+#define PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE		0x0003
+
+static struct pci_device_header virtio_console_pci_device = {
+	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
+	.device_id		= PCI_DEVICE_ID_VIRTIO_CONSOLE,
+	.header_type		= PCI_HEADER_TYPE_NORMAL,
+	.revision_id		= 0,
+	.class			= (0x07 << 8) | (0x80 << 4) | (0x0 << 0),
+	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+	.subsys_id		= PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE,
+	.bar[0]			= IOPORT_VIRTIO_CONSOLE | PCI_BASE_ADDRESS_SPACE_IO,
+	.irq_pin		= 3,
+	.irq_line		= VIRTIO_CONSOLE_IRQ,
+};
+
+void virtio_console__init(struct kvm *self)
+{
+	pci__register(&virtio_console_pci_device, PCI_VIRTIO_CONSOLE_DEVNUM);
+	ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE);
+}
