diff --git a/tools/kvm/hw/rtc.c b/tools/kvm/hw/rtc.c
index 6735e82..146f660 100644
--- a/tools/kvm/hw/rtc.c
+++ b/tools/kvm/hw/rtc.c
@@ -19,7 +19,7 @@ static inline unsigned char bin2bcd(unsigned val)
 	return ((val / 10) << 4) + val % 10;
 }
 
-static bool cmos_ram_data_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool cmos_ram_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	struct tm *tm;
 	time_t ti;
@@ -52,7 +52,7 @@ static bool cmos_ram_data_in(struct kvm *kvm, u16 port, void *data, int size, u3
 	return true;
 }
 
-static bool cmos_ram_data_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool cmos_ram_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
@@ -62,7 +62,7 @@ static struct ioport_operations cmos_ram_data_ioport_ops = {
 	.io_in		= cmos_ram_data_in,
 };
 
-static bool cmos_ram_index_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool cmos_ram_index_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	u8 value;
 
@@ -82,6 +82,6 @@ static struct ioport_operations cmos_ram_index_ioport_ops = {
 void rtc__init(void)
 {
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1);
-	ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1);
+	ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+	ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
 }
diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
index beebbba..1199264 100644
--- a/tools/kvm/hw/serial.c
+++ b/tools/kvm/hw/serial.c
@@ -164,7 +164,7 @@ static struct serial8250_device *find_device(u16 port)
 	return NULL;
 }
 
-static bool serial8250_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	struct serial8250_device *dev;
 	u16 offset;
@@ -252,7 +252,7 @@ out_unlock:
 	return ret;
 }
 
-static bool serial8250_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	struct serial8250_device *dev;
 	u16 offset;
@@ -339,7 +339,7 @@ static struct ioport_operations serial8250_ops = {
 
 static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
 {
-	ioport__register(dev->iobase, &serial8250_ops, 8);
+	ioport__register(dev->iobase, &serial8250_ops, 8, NULL);
 	kvm__irq_line(kvm, dev->irq, 0);
 }
 
diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
index 6ab07ee..ec4788c 100644
--- a/tools/kvm/hw/vesa.c
+++ b/tools/kvm/hw/vesa.c
@@ -26,12 +26,12 @@
 
 static char videomem[VESA_MEM_SIZE];
 
-static bool vesa_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
 
-static bool vesa_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
@@ -75,7 +75,7 @@ void vesa__init(struct kvm *kvm)
 
 	pci__register(&vesa_pci_device, dev);
 
-	ioport__register(IOPORT_VESA, &vesa_io_ops, IOPORT_VESA_SIZE);
+	ioport__register(IOPORT_VESA, &vesa_io_ops, IOPORT_VESA_SIZE, NULL);
 
 	kvm__register_mmio(VESA_MEM_ADDR, VESA_MEM_SIZE, &vesa_mmio_callback);
 
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
index 8253938..67b4a6f 100644
--- a/tools/kvm/include/kvm/ioport.h
+++ b/tools/kvm/include/kvm/ioport.h
@@ -1,6 +1,8 @@
 #ifndef KVM__IOPORT_H
 #define KVM__IOPORT_H
 
+#include "kvm/rbtree-interval.h"
+
 #include <stdbool.h>
 #include <asm/types.h>
 #include <linux/types.h>
@@ -22,14 +24,20 @@
 
 struct kvm;
 
+struct ioport {
+	struct rb_int_node		node;
+	struct ioport_operations	*ops;
+	void				*priv;
+};
+
 struct ioport_operations {
-	bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
-	bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
+	bool (*io_in)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count);
+	bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count);
 };
 
 void ioport__setup_legacy(void);
 
-void ioport__register(u16 port, struct ioport_operations *ops, int count);
+void ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
 
 static inline u8 ioport__read8(u8 *data)
 {
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
index 1f13960..92ad152 100644
--- a/tools/kvm/ioport.c
+++ b/tools/kvm/ioport.c
@@ -2,7 +2,6 @@
 
 #include "kvm/kvm.h"
 #include "kvm/util.h"
-#include "kvm/rbtree-interval.h"
 
 #include <linux/kvm.h>	/* for KVM_EXIT_* */
 #include <linux/types.h>
@@ -13,17 +12,12 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#define ioport_node(n) rb_entry(n, struct ioport_entry, node)
-
-struct ioport_entry {
-	struct rb_int_node		node;
-	struct ioport_operations	*ops;
-};
+#define ioport_node(n) rb_entry(n, struct ioport, node)
 
 static struct rb_root ioport_tree = RB_ROOT;
 bool ioport_debug;
 
-static struct ioport_entry *ioport_search(struct rb_root *root, u64 addr)
+static struct ioport *ioport_search(struct rb_root *root, u64 addr)
 {
 	struct rb_int_node *node;
 
@@ -34,12 +28,12 @@ static struct ioport_entry *ioport_search(struct rb_root *root, u64 addr)
 	return ioport_node(node);
 }
 
-static int ioport_insert(struct rb_root *root, struct ioport_entry *data)
+static int ioport_insert(struct rb_root *root, struct ioport *data)
 {
 	return rb_int_insert(root, &data->node);
 }
 
-static bool debug_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	exit(EXIT_SUCCESS);
 }
@@ -48,12 +42,12 @@ static struct ioport_operations debug_ops = {
 	.io_out		= debug_io_out,
 };
 
-static bool dummy_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
 
-static bool dummy_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
@@ -67,9 +61,9 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
 	.io_out		= dummy_io_out,
 };
 
-void ioport__register(u16 port, struct ioport_operations *ops, int count)
+void ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
 {
-	struct ioport_entry *entry;
+	struct ioport *entry;
 
 	entry = ioport_search(&ioport_tree, port);
 	if (entry) {
@@ -81,9 +75,10 @@ void ioport__register(u16 port, struct ioport_operations *ops, int count)
 	if (entry == NULL)
 		die("Failed allocating new ioport entry");
 
-	*entry = (struct ioport_entry) {
+	*entry = (struct ioport) {
 		.node	= RB_INT_INIT(port, port + count),
 		.ops	= ops,
+		.priv	= param,
 	};
 
 	ioport_insert(&ioport_tree, entry);
@@ -105,30 +100,26 @@ static void ioport_error(u16 port, void *data, int direction, int size, u32 coun
 bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
 {
 	struct ioport_operations *ops;
-	bool ret;
-	struct ioport_entry *entry;
+	bool ret = false;
+	struct ioport *entry;
 
 	entry = ioport_search(&ioport_tree, port);
 	if (!entry)
 		goto error;
 
-	ops = entry->ops;
+	ops	= entry->ops;
 
 	if (direction == KVM_EXIT_IO_IN) {
-		if (!ops->io_in)
-			goto error;
-
-		ret = ops->io_in(kvm, port, data, size, count);
-		if (!ret)
-			goto error;
+		if (ops->io_in)
+			ret = ops->io_in(entry, kvm, port, data, size, count);
 	} else {
-		if (!ops->io_out)
-			goto error;
-
-		ret = ops->io_out(kvm, port, data, size, count);
-		if (!ret)
-			goto error;
+		if (ops->io_out)
+			ret = ops->io_out(entry, kvm, port, data, size, count);
 	}
+
+	if (!ret)
+		goto error;
+
 	return true;
 error:
 	if (ioport_debug)
@@ -140,29 +131,29 @@ error:
 void ioport__setup_legacy(void)
 {
 	/* 0x0020 - 0x003F - 8259A PIC 1 */
-	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2);
+	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
 
 	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
-	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4);
+	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
 
 	/* PORT 0060-006F - KEYBOARD CONTROLLER 804x (8041, 8042) (or PPI (8255) on PC,XT) */
-	ioport__register(0x0060, &dummy_read_write_ioport_ops, 2);
-	ioport__register(0x0064, &dummy_read_write_ioport_ops, 1);
+	ioport__register(0x0060, &dummy_read_write_ioport_ops, 2, NULL);
+	ioport__register(0x0064, &dummy_read_write_ioport_ops, 1, NULL);
 
 	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
-	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2);
+	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
 
 	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
 	   internal debugging purposes.  */
-	ioport__register(IOPORT_DBG, &debug_ops, 1);
+	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
 
 	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
-	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1);
+	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
 
 	/* 0x00F0 - 0x00FF - Math co-processor */
-	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2);
+	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
 
 	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
-	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1);
-	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1);
+	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
+	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
 }
diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c
index d4fbeab8..a1ad8ba 100644
--- a/tools/kvm/pci.c
+++ b/tools/kvm/pci.c
@@ -21,7 +21,7 @@ static void *pci_config_address_ptr(u16 port)
 	return base + offset;
 }
 
-static bool pci_config_address_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	void *p = pci_config_address_ptr(port);
 
@@ -30,7 +30,7 @@ static bool pci_config_address_out(struct kvm *kvm, u16 port, void *data, int si
 	return true;
 }
 
-static bool pci_config_address_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	void *p = pci_config_address_ptr(port);
 
@@ -44,7 +44,7 @@ static struct ioport_operations pci_config_address_ops = {
 	.io_out		= pci_config_address_out,
 };
 
-static bool pci_config_data_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	return true;
 }
@@ -67,7 +67,7 @@ static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_numbe
 	return dev != NULL;
 }
 
-static bool pci_config_data_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long start;
 	u8 dev_num;
@@ -110,6 +110,6 @@ void pci__register(struct pci_device_header *dev, u8 dev_num)
 
 void pci__init(void)
 {
-	ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4);
-	ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4);
+	ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
+	ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
 }
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
index e307592..c441089 100644
--- a/tools/kvm/virtio/9p.c
+++ b/tools/kvm/virtio/9p.c
@@ -91,7 +91,7 @@ static bool virtio_p9_dev_in(void *data, unsigned long offset, int size, u32 cou
 	return true;
 }
 
-static bool virtio_p9_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_p9_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset;
 	bool ret = true;
@@ -579,7 +579,7 @@ static void virtio_p9_do_io(struct kvm *kvm, void *param)
 	}
 }
 
-static bool virtio_p9_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset;
 	bool ret = true;
@@ -664,5 +664,5 @@ void virtio_9p__init(struct kvm *kvm, const char *root)
 	virtio_p9_pci_device.irq_line	= line;
 	pci__register(&virtio_p9_pci_device, dev);
 
-	ioport__register(IOPORT_VIRTIO_P9, &virtio_p9_io_ops, IOPORT_VIRTIO_P9_SIZE);
+	ioport__register(IOPORT_VIRTIO_P9, &virtio_p9_io_ops, IOPORT_VIRTIO_P9_SIZE, NULL);
 }
diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 25ce61f..5720c7f 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -73,7 +73,7 @@ static void virtio_blk_port2dev(u16 port, u16 base, u16 size, u16 *dev_idx, u16
 	*offset		= port - (base + *dev_idx * size);
 }
 
-static bool virtio_blk_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_blk_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	struct blk_dev *bdev;
 	u16 offset, dev_idx;
@@ -178,7 +178,7 @@ static void virtio_blk_do_io(struct kvm *kvm, void *param)
 	virt_queue__trigger_irq(vq, bdev->pci_hdr.irq_line, &bdev->isr, kvm);
 }
 
-static bool virtio_blk_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	struct blk_dev *bdev;
 	u16 offset, dev_idx;
@@ -318,7 +318,7 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 
 	pci__register(&bdev->pci_hdr, dev);
 
-	ioport__register(blk_dev_base_addr, &virtio_blk_io_ops, IOPORT_VIRTIO_BLK_SIZE);
+	ioport__register(blk_dev_base_addr, &virtio_blk_io_ops, IOPORT_VIRTIO_BLK_SIZE, NULL);
 }
 
 void virtio_blk__init_all(struct kvm *kvm)
diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
index affff0b..614f0d2 100644
--- a/tools/kvm/virtio/console.c
+++ b/tools/kvm/virtio/console.c
@@ -111,7 +111,7 @@ static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long o
 	return true;
 }
 
-static bool virtio_console_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_console_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
 	bool ret = true;
@@ -179,7 +179,7 @@ static void virtio_console_handle_callback(struct kvm *kvm, void *param)
 
 }
 
-static bool virtio_console_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset = port - IOPORT_VIRTIO_CONSOLE;
 	bool ret = true;
@@ -250,5 +250,5 @@ void virtio_console__init(struct kvm *kvm)
 	virtio_console_pci_device.irq_pin	= pin;
 	virtio_console_pci_device.irq_line	= line;
 	pci__register(&virtio_console_pci_device, dev);
-	ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE);
+	ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE, NULL);
 }
diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
index 649bc0f..014205b 100644
--- a/tools/kvm/virtio/net.c
+++ b/tools/kvm/virtio/net.c
@@ -164,7 +164,7 @@ static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offse
 	return true;
 }
 
-static bool virtio_net_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_net_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long	offset	= port - IOPORT_VIRTIO_NET;
 	bool		ret	= true;
@@ -228,7 +228,7 @@ static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
 	}
 }
 
-static bool virtio_net_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_net_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long	offset		= port - IOPORT_VIRTIO_NET;
 	bool		ret		= true;
@@ -394,7 +394,7 @@ void virtio_net__init(const struct virtio_net_parameters *params)
 		pci_header.irq_pin	= pin;
 		pci_header.irq_line	= line;
 		pci__register(&pci_header, dev);
-		ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE);
+		ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE, NULL);
 
 		virtio_net__io_thread_init(params->kvm);
 	}
diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c
index 9bd0098..a553f6b 100644
--- a/tools/kvm/virtio/rng.c
+++ b/tools/kvm/virtio/rng.c
@@ -48,7 +48,7 @@ struct rng_dev {
 
 static struct rng_dev rdev;
 
-static bool virtio_rng_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_rng_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset;
 	bool ret = true;
@@ -111,7 +111,7 @@ static void virtio_rng_do_io(struct kvm *kvm, void *param)
 	}
 }
 
-static bool virtio_rng_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
 {
 	unsigned long offset;
 	bool ret = true;
@@ -179,5 +179,5 @@ void virtio_rng__init(struct kvm *kvm)
 	virtio_rng_pci_device.irq_line	= line;
 	pci__register(&virtio_rng_pci_device, dev);
 
-	ioport__register(IOPORT_VIRTIO_RNG, &virtio_rng_io_ops, IOPORT_VIRTIO_RNG_SIZE);
+	ioport__register(IOPORT_VIRTIO_RNG, &virtio_rng_io_ops, IOPORT_VIRTIO_RNG_SIZE, NULL);
 }
