All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] kvm tools: Seperate virtio-pci layer
@ 2011-08-22 12:58 Sasha Levin
  2011-08-22 12:58 ` [PATCH 2/6] kvm tools: Seperate virtio-pci layer out of virtio-rng Sasha Levin
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

This patch builds a virtio-pci layer which can be used by virtio
devices as a layer to interact with virtio-pci. The purpose of the
patch is to seperate the common virtio-pci layer from being replicated
in all virtio devices.

The new layer provides a callback interface to receive information about
virtio events.

This allows us to share the entire functionality of virtio-pci throughout all
virtio devices, for example - we don't need to implement MSI-X for each device
and can just do it once for virtio-pci.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/Makefile                 |    1 +
 tools/kvm/include/kvm/ioport.h     |    1 +
 tools/kvm/include/kvm/virtio-pci.h |   51 ++++++++
 tools/kvm/virtio/pci.c             |  231 ++++++++++++++++++++++++++++++++++++
 4 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 tools/kvm/include/kvm/virtio-pci.h
 create mode 100644 tools/kvm/virtio/pci.c

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 316c2c9..669386f 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -52,6 +52,7 @@ OBJS	+= virtio/core.o
 OBJS	+= virtio/net.o
 OBJS	+= virtio/rng.o
 OBJS    += virtio/balloon.o
+OBJS	+= virtio/pci.o
 OBJS	+= disk/blk.o
 OBJS	+= disk/qcow.o
 OBJS	+= disk/raw.o
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
index 45c3856..5b857dd 100644
--- a/tools/kvm/include/kvm/ioport.h
+++ b/tools/kvm/include/kvm/ioport.h
@@ -4,6 +4,7 @@
 #include "kvm/rbtree-interval.h"
 
 #include <stdbool.h>
+#include <limits.h>
 #include <asm/types.h>
 #include <linux/types.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..4524a7f
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-pci.h
@@ -0,0 +1,51 @@
+#ifndef KVM__VIRTIO_PCI_H
+#define KVM__VIRTIO_PCI_H
+
+#include "kvm/pci.h"
+
+#include <linux/types.h>
+
+#define VIRTIO_PCI_MAX_VQ 3
+
+struct kvm;
+
+struct virtio_pci_ops {
+	void (*set_config)(struct kvm *kvm, void *dev, u8 data, u32 offset);
+	u8 (*get_config)(struct kvm *kvm, void *dev, u32 offset);
+
+	u32 (*get_host_features)(struct kvm *kvm, void *dev);
+	void (*set_guest_features)(struct kvm *kvm, void *dev, u32 features);
+
+	int (*init_vq)(struct kvm *kvm, void *dev, u32 vq, u32 pfn);
+	int (*notify_vq)(struct kvm *kvm, void *dev, u32 vq);
+	int (*get_pfn_vq)(struct kvm *kvm, void *dev, u32 vq);
+	int (*get_size_vq)(struct kvm *kvm, void *dev, u32 vq);
+};
+
+struct virtio_pci {
+	struct pci_device_header pci_hdr;
+	struct virtio_pci_ops	ops;
+	void			*dev;
+
+	u16			base_addr;
+	u8			status;
+	u8			isr;
+
+	/* MSI-X */
+	u16			config_vector;
+	u32			config_gsi;
+	u32			vq_vector[VIRTIO_PCI_MAX_VQ];
+	u32			gsis[VIRTIO_PCI_MAX_VQ];
+	u32			msix_io_block;
+	int			msix_enabled;
+
+	/* virtio queue */
+	u16			queue_selector;
+};
+
+int virtio_pci__init(struct kvm *kvm, struct virtio_pci *vpci, void *dev,
+			int device_id, int subsys_id);
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq);
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci);
+
+#endif
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
new file mode 100644
index 0000000..6d086fa
--- /dev/null
+++ b/tools/kvm/virtio/pci.c
@@ -0,0 +1,231 @@
+#include "kvm/virtio-pci.h"
+
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/irq.h"
+#include "kvm/virtio.h"
+
+#include <linux/virtio_pci.h>
+#include <string.h>
+
+static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_pci *vpci, u16 port,
+					void *data, int size, int offset)
+{
+	u32 config_offset;
+	int type = virtio__get_dev_specific_field(offset - 20, vpci->msix_enabled,
+							0, &config_offset);
+	if (type == VIRTIO_PCI_O_MSIX) {
+		switch (offset) {
+		case VIRTIO_MSI_CONFIG_VECTOR:
+			ioport__write16(data, vpci->config_vector);
+			break;
+		case VIRTIO_MSI_QUEUE_VECTOR:
+			ioport__write16(data, vpci->vq_vector[vpci->queue_selector]);
+			break;
+		};
+
+		return true;
+	} else if (type == VIRTIO_PCI_O_CONFIG) {
+		u8 cfg;
+
+		cfg = vpci->ops.get_config(kvm, vpci->dev, config_offset);
+		ioport__write8(data, cfg);
+		return true;
+	}
+
+	return false;
+}
+
+static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	unsigned long offset;
+	bool ret = true;
+	struct virtio_pci *vpci;
+	u32 val;
+
+	vpci = ioport->priv;
+	offset = port - vpci->base_addr;
+
+	switch (offset) {
+	case VIRTIO_PCI_HOST_FEATURES:
+		val = vpci->ops.get_host_features(kvm, vpci->dev);
+		ioport__write32(data, val);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN:
+		val = vpci->ops.get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
+		ioport__write32(data, val);
+		break;
+	case VIRTIO_PCI_QUEUE_NUM:
+		val = vpci->ops.get_size_vq(kvm, vpci->dev, vpci->queue_selector);
+		ioport__write32(data, val);
+		break;
+		break;
+	case VIRTIO_PCI_STATUS:
+		ioport__write8(data, vpci->status);
+		break;
+	case VIRTIO_PCI_ISR:
+		ioport__write8(data, vpci->isr);
+		kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
+		vpci->isr = VIRTIO_IRQ_LOW;
+		break;
+	default:
+		ret = virtio_pci__specific_io_in(kvm, vpci, port, data, size, offset);
+		break;
+	};
+
+	return ret;
+}
+
+static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_pci *vpci, u16 port,
+					void *data, int size, int offset)
+{
+	u32 config_offset, gsi, vec;
+	int type = virtio__get_dev_specific_field(offset - 20, vpci->msix_enabled,
+							0, &config_offset);
+	if (type == VIRTIO_PCI_O_MSIX) {
+		switch (offset) {
+		case VIRTIO_MSI_CONFIG_VECTOR:
+			vec = vpci->config_vector = ioport__read16(data);
+
+			gsi = irq__add_msix_route(kvm,
+						  vpci->pci_hdr.msix.table[vec].low,
+						  vpci->pci_hdr.msix.table[vec].high,
+						  vpci->pci_hdr.msix.table[vec].data);
+
+			vpci->config_gsi = gsi;
+			break;
+		case VIRTIO_MSI_QUEUE_VECTOR: {
+			vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
+
+			gsi = irq__add_msix_route(kvm,
+						  vpci->pci_hdr.msix.table[vec].low,
+						  vpci->pci_hdr.msix.table[vec].high,
+						  vpci->pci_hdr.msix.table[vec].data);
+			vpci->gsis[vpci->queue_selector] = gsi;
+			break;
+		}
+		};
+
+		return true;
+	} else if (type == VIRTIO_PCI_O_CONFIG) {
+		vpci->ops.set_config(kvm, vpci->dev, *(u8 *)data, config_offset);
+
+		return true;
+	}
+
+	return false;
+}
+
+static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	unsigned long offset;
+	bool ret = true;
+	struct virtio_pci *vpci;
+	u32 val;
+
+	vpci = ioport->priv;
+	offset = port - vpci->base_addr;
+
+	switch (offset) {
+	case VIRTIO_PCI_GUEST_FEATURES:
+		val = ioport__read32(data);
+		vpci->ops.set_guest_features(kvm, vpci, val);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN:
+		val = ioport__read32(data);
+		vpci->ops.init_vq(kvm, vpci->dev, vpci->queue_selector, val);
+		break;
+	case VIRTIO_PCI_QUEUE_SEL:
+		vpci->queue_selector	= ioport__read16(data);
+		break;
+	case VIRTIO_PCI_QUEUE_NOTIFY:
+		val			= ioport__read16(data);
+		vpci->ops.notify_vq(kvm, vpci->dev, val);
+		break;
+	case VIRTIO_PCI_STATUS:
+		vpci->status		= ioport__read8(data);
+		break;
+	default:
+		ret = virtio_pci__specific_io_out(kvm, vpci, port, data, size, offset);
+		break;
+	};
+
+	return ret;
+}
+
+static struct ioport_operations virtio_pci__io_ops = {
+	.io_in	= virtio_pci__io_in,
+	.io_out	= virtio_pci__io_out,
+};
+
+static void callback_mmio(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+{
+	struct virtio_pci *vpci = ptr;
+	void *table = &vpci->pci_hdr.msix.table;
+
+	vpci->msix_enabled = 1;
+	if (is_write)
+		memcpy(table + addr - vpci->msix_io_block, data, len);
+	else
+		memcpy(data, table + addr - vpci->msix_io_block, len);
+}
+
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq)
+{
+	kvm__irq_line(kvm, vpci->gsis[vq], VIRTIO_IRQ_HIGH);
+
+	return 0;
+}
+
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci)
+{
+	kvm__irq_line(kvm, vpci->config_gsi, VIRTIO_IRQ_HIGH);
+
+	return 0;
+}
+
+int virtio_pci__init(struct kvm *kvm, struct virtio_pci *vpci, void *dev,
+			int device_id, int subsys_id)
+{
+	u8 pin, line, ndev;
+
+	vpci->dev = dev;
+	vpci->msix_io_block = pci_get_io_space_block();
+
+	vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vpci);
+	kvm__register_mmio(kvm, vpci->msix_io_block, 0x100, callback_mmio, vpci);
+
+	vpci->pci_hdr = (struct pci_device_header) {
+		.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
+		.device_id		= device_id,
+		.header_type		= PCI_HEADER_TYPE_NORMAL,
+		.revision_id		= 0,
+		.class			= 0x010000,
+		.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+		.subsys_id		= subsys_id,
+		.bar[0]			= vpci->base_addr | PCI_BASE_ADDRESS_SPACE_IO,
+		.bar[1]			= vpci->msix_io_block |
+					PCI_BASE_ADDRESS_SPACE_MEMORY |
+					PCI_BASE_ADDRESS_MEM_TYPE_64,
+		/* bar[2] is the continuation of bar[1] for 64bit addressing */
+		.bar[2]			= 0,
+		.status			= PCI_STATUS_CAP_LIST,
+		.capabilities		= (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
+	};
+
+	vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
+	vpci->pci_hdr.msix.next = 0;
+	vpci->pci_hdr.msix.table_size = (VIRTIO_PCI_MAX_VQ + 1) | PCI_MSIX_FLAGS_ENABLE;
+	vpci->pci_hdr.msix.table_offset = 1; /* Use BAR 1 */
+	vpci->config_vector = 0;
+
+	if (irq__register_device(VIRTIO_ID_RNG, &ndev, &pin, &line) < 0)
+		return -1;
+
+	vpci->pci_hdr.irq_pin	= pin;
+	vpci->pci_hdr.irq_line	= line;
+	pci__register(&vpci->pci_hdr, ndev);
+
+	return 0;
+}
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/6] kvm tools: Seperate virtio-pci layer out of virtio-rng
  2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
@ 2011-08-22 12:58 ` Sasha Levin
  2011-08-22 12:58 ` [PATCH 3/6] kvm tools: Seperate virtio-pci layer out of virtio-net Sasha Levin
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/virtio/rng.c |  254 ++++++++++++++----------------------------------
 1 files changed, 74 insertions(+), 180 deletions(-)

diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c
index 93258f6..5bea56c 100644
--- a/tools/kvm/virtio/rng.c
+++ b/tools/kvm/virtio/rng.c
@@ -2,16 +2,13 @@
 
 #include "kvm/virtio-pci-dev.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 "kvm/threadpool.h"
-#include "kvm/irq.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_rng.h>
@@ -21,6 +18,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pthread.h>
+#include <linux/kernel.h>
 
 #define NUM_VIRT_QUEUES		1
 #define VIRTIO_RNG_QUEUE_SIZE	128
@@ -32,68 +30,39 @@ struct rng_dev_job {
 };
 
 struct rng_dev {
-	struct pci_device_header pci_hdr;
 	struct list_head	list;
+	struct virtio_pci	vpci;
 
-	u16			base_addr;
-	u8			status;
-	u8			isr;
-	u16			config_vector;
 	int			fd;
-	u32			vq_vector[NUM_VIRT_QUEUES];
-	u32			msix_io_block;
 	int			compat_id;
 
 	/* virtio queue */
-	u16			queue_selector;
 	struct virt_queue	vqs[NUM_VIRT_QUEUES];
 	struct rng_dev_job	jobs[NUM_VIRT_QUEUES];
 };
 
 static LIST_HEAD(rdevs);
 
-static bool virtio_rng_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
 {
-	unsigned long offset;
-	bool ret = true;
-	struct rng_dev *rdev;
+	/* Unused */
+}
 
-	rdev = ioport->priv;
-	offset = port - rdev->base_addr;
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-	case VIRTIO_PCI_GUEST_FEATURES:
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		ret		= false;
-		break;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, rdev->vqs[rdev->queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTIO_RNG_QUEUE_SIZE);
-		break;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, rdev->status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, rdev->isr);
-		kvm__irq_line(kvm, rdev->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
-		rdev->isr = VIRTIO_IRQ_LOW;
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		ioport__write16(data, rdev->config_vector);
-		break;
-	case VIRTIO_MSI_QUEUE_VECTOR:
-		ioport__write16(data, rdev->vq_vector[rdev->queue_selector]);
-		break;
-	default:
-		ret		= false;
-		break;
-	};
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	/* Unused */
+	return 0;
+}
 
-	return ret;
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	/* Unused */
+	return 0;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	/* Unused */
 }
 
 static bool virtio_rng_do_io_request(struct kvm *kvm, struct rng_dev *rdev, struct virt_queue *queue)
@@ -119,171 +88,96 @@ static void virtio_rng_do_io(struct kvm *kvm, void *param)
 	while (virt_queue__available(vq))
 		virtio_rng_do_io_request(kvm, rdev, vq);
 
-	kvm__irq_line(kvm, rdev->pci_hdr.irq_line, VIRTIO_IRQ_HIGH);
+	virtio_pci__signal_vq(kvm, &rdev->vpci, vq - rdev->vqs);
 }
 
-static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
 {
-	unsigned long offset;
-	bool ret = true;
-	struct rng_dev *rdev;
+	struct rng_dev *rdev = dev;
+	struct virt_queue *queue;
+	struct rng_dev_job *job;
+	void *p;
+	struct ioevent ioevent;
 
-	rdev = ioport->priv;
-	offset = port - rdev->base_addr;
+	compat__remove_message(rdev->compat_id);
 
-	switch (offset) {
-	case VIRTIO_PCI_GUEST_FEATURES:
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		struct rng_dev_job *job;
-		void *p;
+	queue			= &rdev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
 
-		compat__remove_message(rdev->compat_id);
+	job = &rdev->jobs[vq];
 
-		queue			= &rdev->vqs[rdev->queue_selector];
-		queue->pfn		= ioport__read32(data);
-		p			= guest_pfn_to_host(kvm, queue->pfn);
+	vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
 
-		job = &rdev->jobs[rdev->queue_selector];
+	*job		= (struct rng_dev_job) {
+		.vq		= queue,
+		.rdev		= rdev,
+	};
 
-		vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+	ioevent = (struct ioevent) {
+		.io_addr	= rdev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= virtio_rng_do_io,
+		.fn_ptr		= &rdev->jobs[vq],
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
+	};
 
-		*job			= (struct rng_dev_job) {
-			.vq			= queue,
-			.rdev			= rdev,
-		};
+	ioeventfd__add_event(&ioevent);
 
-		thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
+	thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
 
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		rdev->queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		u16 queue_index;
-		queue_index		= ioport__read16(data);
-		thread_pool__do_job(&rdev->jobs[queue_index].job_id);
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		rdev->status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		rdev->config_vector	= ioport__read16(data);
-		break;
-	case VIRTIO_MSI_QUEUE_VECTOR: {
-		u32 gsi;
-		u32 vec;
-
-		vec = rdev->vq_vector[rdev->queue_selector] = ioport__read16(data);
-
-		gsi = irq__add_msix_route(kvm,
-					  rdev->pci_hdr.msix.table[vec].low,
-					  rdev->pci_hdr.msix.table[vec].high,
-					  rdev->pci_hdr.msix.table[vec].data);
-		rdev->pci_hdr.irq_line = gsi;
-		break;
-	}
-	default:
-		ret			= false;
-		break;
-	};
-
-	return ret;
+	return 0;
 }
 
-static struct ioport_operations virtio_rng_io_ops = {
-	.io_in				= virtio_rng_pci_io_in,
-	.io_out				= virtio_rng_pci_io_out,
-};
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct rng_dev *rdev = dev;
+
+	thread_pool__do_job(&rdev->jobs[vq].job_id);
 
-static void ioevent_callback(struct kvm *kvm, void *param)
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
 {
-	struct rng_dev_job *job = param;
+	struct rng_dev *rdev = dev;
 
-	thread_pool__do_job(&job->job_id);
+	return rdev->vqs[vq].pfn;
 }
 
-static void callback_mmio(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
 {
-	struct rng_dev *rdev = ptr;
-	void *table = &rdev->pci_hdr.msix.table;
-	if (is_write)
-		memcpy(table + addr - rdev->msix_io_block, data, len);
-	else
-		memcpy(data, table + addr - rdev->msix_io_block, len);
+	return VIRTIO_RNG_QUEUE_SIZE;
 }
 
 void virtio_rng__init(struct kvm *kvm)
 {
-	u8 pin, line, dev, i;
-	u16 rdev_base_addr;
 	struct rng_dev *rdev;
-	struct ioevent ioevent;
 
 	rdev = malloc(sizeof(*rdev));
 	if (rdev == NULL)
 		return;
 
-	rdev->msix_io_block = pci_get_io_space_block();
-
-	rdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_rng_io_ops, IOPORT_SIZE, rdev);
-	kvm__register_mmio(kvm, rdev->msix_io_block, 0x100, callback_mmio, rdev);
-
-	rdev->pci_hdr = (struct pci_device_header) {
-		.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-		.device_id		= PCI_DEVICE_ID_VIRTIO_RNG,
-		.header_type		= PCI_HEADER_TYPE_NORMAL,
-		.revision_id		= 0,
-		.class			= 0x010000,
-		.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-		.subsys_id		= VIRTIO_ID_RNG,
-		.bar[0]			= rdev_base_addr | PCI_BASE_ADDRESS_SPACE_IO,
-		.bar[1]			= rdev->msix_io_block |
-					PCI_BASE_ADDRESS_SPACE_MEMORY |
-					PCI_BASE_ADDRESS_MEM_TYPE_64,
-		/* bar[2] is the continuation of bar[1] for 64bit addressing */
-		.bar[2]			= 0,
-		.status			= PCI_STATUS_CAP_LIST,
-		.capabilities		= (void *)&rdev->pci_hdr.msix - (void *)&rdev->pci_hdr,
-	};
-
-	rdev->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
-	rdev->pci_hdr.msix.next = 0;
-	rdev->pci_hdr.msix.table_size = (NUM_VIRT_QUEUES + 1) | PCI_MSIX_FLAGS_ENABLE;
-	rdev->pci_hdr.msix.table_offset = 1; /* Use BAR 1 */
-
-	rdev->config_vector = 0;
-	rdev->base_addr = rdev_base_addr;
 	rdev->fd = open("/dev/urandom", O_RDONLY);
 	if (rdev->fd < 0)
 		die("Failed initializing RNG");
 
-	if (irq__register_device(VIRTIO_ID_RNG, &dev, &pin, &line) < 0)
-		return;
-
-	rdev->pci_hdr.irq_pin	= pin;
-	rdev->pci_hdr.irq_line	= line;
-	pci__register(&rdev->pci_hdr, dev);
+	virtio_pci__init(kvm, &rdev->vpci, rdev, PCI_DEVICE_ID_VIRTIO_RNG, VIRTIO_ID_RNG);
+	rdev->vpci.ops = (struct virtio_pci_ops) {
+		.set_config		= set_config,
+		.get_config		= get_config,
+		.get_host_features	= get_host_features,
+		.set_guest_features	= set_guest_features,
+		.init_vq		= init_vq,
+		.notify_vq		= notify_vq,
+		.get_pfn_vq		= get_pfn_vq,
+		.get_size_vq		= get_size_vq,
+	};
 
 	list_add_tail(&rdev->list, &rdevs);
 
-	for (i = 0; i < NUM_VIRT_QUEUES; i++) {
-		ioevent = (struct ioevent) {
-			.io_addr		= rdev_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-			.io_len			= sizeof(u16),
-			.fn			= ioevent_callback,
-			.fn_ptr			= &rdev->jobs[i],
-			.datamatch		= i,
-			.fn_kvm			= kvm,
-			.fd			= eventfd(0, 0),
-		};
-
-		ioeventfd__add_event(&ioevent);
-	}
-
 	rdev->compat_id = compat__add_message("virtio-rng device was not detected",
 						"While you have requested a virtio-rng device, "
 						"the guest kernel didn't seem to detect it.\n"
@@ -298,7 +192,7 @@ void virtio_rng__delete_all(struct kvm *kvm)
 
 		rdev = list_first_entry(&rdevs, struct rng_dev, list);
 		list_del(&rdev->list);
-		ioeventfd__del_event(rdev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 0);
+		ioeventfd__del_event(rdev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 0);
 		free(rdev);
 	}
 }
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/6] kvm tools: Seperate virtio-pci layer out of virtio-net
  2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
  2011-08-22 12:58 ` [PATCH 2/6] kvm tools: Seperate virtio-pci layer out of virtio-rng Sasha Levin
@ 2011-08-22 12:58 ` Sasha Levin
  2011-08-22 12:58 ` [PATCH 4/6] kvm tools: Seperate virtio-pci layer out of virtio-balloon Sasha Levin
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/virtio/net.c |  344 ++++++++++++++----------------------------------
 1 files changed, 100 insertions(+), 244 deletions(-)

diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
index aa4536b..6247642 100644
--- a/tools/kvm/virtio/net.c
+++ b/tools/kvm/virtio/net.c
@@ -1,19 +1,19 @@
 #include "kvm/virtio-pci-dev.h"
 #include "kvm/virtio-net.h"
 #include "kvm/virtio.h"
-#include "kvm/ioport.h"
 #include "kvm/types.h"
 #include "kvm/mutex.h"
 #include "kvm/util.h"
 #include "kvm/kvm.h"
-#include "kvm/pci.h"
 #include "kvm/irq.h"
 #include "kvm/uip.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_net.h>
 #include <linux/if_tun.h>
+#include <linux/types.h>
 
 #include <arpa/inet.h>
 #include <net/if.h>
@@ -32,18 +32,10 @@
 #define VIRTIO_NET_RX_QUEUE		0
 #define VIRTIO_NET_TX_QUEUE		1
 
-static struct pci_device_header pci_header = {
-	.vendor_id			= PCI_VENDOR_ID_REDHAT_QUMRANET,
-	.device_id			= PCI_DEVICE_ID_VIRTIO_NET,
-	.header_type			= PCI_HEADER_TYPE_NORMAL,
-	.revision_id			= 0,
-	.class				= 0x020000,
-	.subsys_vendor_id		= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-	.subsys_id			= VIRTIO_ID_NET,
-};
-
 struct net_dev;
 
+extern struct kvm *kvm;
+
 struct net_dev_operations {
 	int (*rx)(struct iovec *iov, u16 in, struct net_dev *ndev);
 	int (*tx)(struct iovec *iov, u16 in, struct net_dev *ndev);
@@ -51,21 +43,12 @@ struct net_dev_operations {
 
 struct net_dev {
 	pthread_mutex_t			mutex;
+	struct virtio_pci		vpci;
 
 	struct virt_queue		vqs[VIRTIO_NET_NUM_QUEUES];
 	struct virtio_net_config	config;
-	u32				host_features;
-	u32				guest_features;
-	u16				config_vector;
-	u8				status;
-	u8				isr;
-	u16				queue_selector;
-	u16				base_addr;
-	u32				vq_vector[VIRTIO_NET_NUM_QUEUES];
-	u32				gsis[VIRTIO_NET_NUM_QUEUES];
-	u32				msix_io_block;
+	u32				features;
 	int				compat_id;
-	bool				msix_enabled;
 
 	pthread_t			io_rx_thread;
 	pthread_mutex_t			io_rx_lock;
@@ -90,14 +73,6 @@ static struct net_dev ndev = {
 	.config = {
 		.status			= VIRTIO_NET_S_LINK_UP,
 	},
-	.host_features			= 1UL << VIRTIO_NET_F_MAC
-					| 1UL << VIRTIO_NET_F_CSUM
-					| 1UL << VIRTIO_NET_F_HOST_UFO
-					| 1UL << VIRTIO_NET_F_HOST_TSO4
-					| 1UL << VIRTIO_NET_F_HOST_TSO6
-					| 1UL << VIRTIO_NET_F_GUEST_UFO
-					| 1UL << VIRTIO_NET_F_GUEST_TSO4
-					| 1UL << VIRTIO_NET_F_GUEST_TSO6,
 	.info = {
 		.buf_nr			= 20,
 	}
@@ -131,7 +106,7 @@ static void *virtio_net_rx_thread(void *p)
 			virt_queue__set_used_elem(vq, head, len);
 
 			/* We should interrupt guest right now, otherwise latency is huge. */
-			kvm__irq_trigger(kvm, ndev.gsis[VIRTIO_NET_RX_QUEUE]);
+			virtio_pci__signal_vq(kvm, &ndev.vpci, VIRTIO_NET_RX_QUEUE);
 		}
 
 	}
@@ -168,7 +143,7 @@ static void *virtio_net_tx_thread(void *p)
 			virt_queue__set_used_elem(vq, head, len);
 		}
 
-		kvm__irq_trigger(kvm, ndev.gsis[VIRTIO_NET_TX_QUEUE]);
+		virtio_pci__signal_vq(kvm, &ndev.vpci, VIRTIO_NET_TX_QUEUE);
 	}
 
 	pthread_exit(NULL);
@@ -177,112 +152,6 @@ static void *virtio_net_tx_thread(void *p)
 
 }
 
-static bool virtio_net_pci_io_device_specific_out(struct kvm *kvm, void *data,
-							unsigned long offset, int size)
-{
-	u8 *config_space = (u8 *)&ndev.config;
-	int type;
-	u32 config_offset;
-
-	type = virtio__get_dev_specific_field(offset - 20, ndev.msix_enabled, 0, &config_offset);
-	if (type == VIRTIO_PCI_O_MSIX) {
-		if (offset == VIRTIO_MSI_CONFIG_VECTOR) {
-			ndev.config_vector	= ioport__read16(data);
-		} else {
-			u32 gsi;
-			u32 vec;
-
-			vec = ndev.vq_vector[ndev.queue_selector] = ioport__read16(data);
-
-			gsi = irq__add_msix_route(kvm,
-						  pci_header.msix.table[vec].low,
-						  pci_header.msix.table[vec].high,
-						  pci_header.msix.table[vec].data);
-
-			ndev.gsis[ndev.queue_selector] = gsi;
-		}
-		return true;
-	}
-
-	if (size != 1)
-		return false;
-
-	if ((config_offset) > sizeof(struct virtio_net_config))
-		pr_error("config offset is too big: %u", config_offset);
-
-	config_space[config_offset] = *(u8 *)data;
-
-	return true;
-}
-
-static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offset, int size)
-{
-	u8 *config_space = (u8 *)&ndev.config;
-	int type;
-	u32 config_offset;
-
-	type = virtio__get_dev_specific_field(offset - 20, ndev.msix_enabled, 0, &config_offset);
-	if (type == VIRTIO_PCI_O_MSIX) {
-		if (offset == VIRTIO_MSI_CONFIG_VECTOR)
-			ioport__write16(data, ndev.config_vector);
-		else
-			ioport__write16(data, ndev.vq_vector[ndev.queue_selector]);
-
-		return true;
-	}
-
-	if (size != 1)
-		return false;
-
-	if ((config_offset) > sizeof(struct virtio_net_config))
-		pr_error("config offset is too big: %u", config_offset);
-
-	ioport__write8(data, config_space[config_offset]);
-
-	return true;
-}
-
-static bool virtio_net_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
-{
-	unsigned long	offset	= port - ndev.base_addr;
-	bool		ret	= true;
-
-	mutex_lock(&ndev.mutex);
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, ndev.host_features);
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-		ret = false;
-		break;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, ndev.vqs[ndev.queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTIO_NET_QUEUE_SIZE);
-		break;
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		ret = false;
-		break;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, ndev.status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, ndev.isr);
-		kvm__irq_line(kvm, pci_header.irq_line, VIRTIO_IRQ_LOW);
-		ndev.isr = VIRTIO_IRQ_LOW;
-		break;
-	default:
-		ret = virtio_net_pci_io_device_specific_in(data, offset, size);
-	};
-
-	mutex_unlock(&ndev.mutex);
-
-	return ret;
-}
-
 static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
 {
 	switch (queue_index) {
@@ -301,76 +170,11 @@ static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
 	}
 }
 
-static bool virtio_net_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
-{
-	unsigned long	offset		= port - ndev.base_addr;
-	bool		ret		= true;
-
-	mutex_lock(&ndev.mutex);
-
-	switch (offset) {
-	case VIRTIO_PCI_GUEST_FEATURES:
-		ndev.guest_features	= ioport__read32(data);
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		void *p;
-
-		assert(ndev.queue_selector < VIRTIO_NET_NUM_QUEUES);
-
-		compat__remove_message(ndev.compat_id);
-
-		queue			= &ndev.vqs[ndev.queue_selector];
-		queue->pfn		= ioport__read32(data);
-		p			= guest_pfn_to_host(kvm, queue->pfn);
-
-		vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
-
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		ndev.queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		u16 queue_index;
-
-		queue_index		= ioport__read16(data);
-		virtio_net_handle_callback(kvm, queue_index);
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		ndev.status		= ioport__read8(data);
-		break;
-	default:
-		ret = virtio_net_pci_io_device_specific_out(kvm, data, offset, size);
-	};
-
-	mutex_unlock(&ndev.mutex);
-
-	return ret;
-}
-
 static void ioevent_callback(struct kvm *kvm, void *param)
 {
 	virtio_net_handle_callback(kvm, (u64)(long)param);
 }
 
-static struct ioport_operations virtio_net_io_ops = {
-	.io_in	= virtio_net_pci_io_in,
-	.io_out	= virtio_net_pci_io_out,
-};
-
-static void callback_mmio(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
-{
-	void *table = pci_header.msix.table;
-	if (is_write)
-		memcpy(table + addr - ndev.msix_io_block, data, len);
-	else
-		memcpy(data, table + addr - ndev.msix_io_block, len);
-
-	ndev.msix_enabled = 1;
-}
-
 static bool virtio_net__tap_init(const struct virtio_net_parameters *params)
 {
 	int sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -495,22 +299,91 @@ static struct net_dev_operations uip_ops = {
 	.tx	= uip_ops_tx,
 };
 
-void virtio_net__init(const struct virtio_net_parameters *params)
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct net_dev *ndev = dev;
+
+	((u8 *)(&ndev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct net_dev *ndev = dev;
+
+	return ((u8 *)(&ndev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1UL << VIRTIO_NET_F_MAC
+		| 1UL << VIRTIO_NET_F_CSUM
+		| 1UL << VIRTIO_NET_F_HOST_UFO
+		| 1UL << VIRTIO_NET_F_HOST_TSO4
+		| 1UL << VIRTIO_NET_F_HOST_TSO6
+		| 1UL << VIRTIO_NET_F_GUEST_UFO
+		| 1UL << VIRTIO_NET_F_GUEST_TSO4
+		| 1UL << VIRTIO_NET_F_GUEST_TSO6;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct net_dev *ndev = dev;
+
+	ndev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
 {
+	struct net_dev *ndev = dev;
+	struct virt_queue *queue;
+	void *p;
 	struct ioevent ioevent;
-	u8 dev, line, pin;
-	u16 net_base_addr;
-	int i;
 
-	if (irq__register_device(VIRTIO_ID_NET, &dev, &pin, &line) < 0)
-		return;
+	compat__remove_message(ndev->compat_id);
+
+	queue			= &ndev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	ioevent = (struct ioevent) {
+		.io_addr	= ndev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= ioevent_callback,
+		.fn_ptr		= (void *)(u64)vq,
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
+	};
+
+	ioeventfd__add_event(&ioevent);
+
+	return 0;
+}
 
-	pci_header.irq_pin  = pin;
-	pci_header.irq_line = line;
-	net_base_addr	    = ioport__register(IOPORT_EMPTY, &virtio_net_io_ops, IOPORT_SIZE, NULL);
-	pci_header.bar[0]   = net_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
-	ndev.base_addr	    = net_base_addr;
-	pci__register(&pci_header, dev);
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	virtio_net_handle_callback(kvm, vq);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct net_dev *ndev = dev;
+
+	return ndev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_NET_QUEUE_SIZE;
+}
+
+void virtio_net__init(const struct virtio_net_parameters *params)
+{
+	int i;
 
 	for (i = 0 ; i < 6 ; i++) {
 		ndev.config.mac[i]		= params->guest_mac[i];
@@ -530,37 +403,20 @@ void virtio_net__init(const struct virtio_net_parameters *params)
 		ndev.ops = &uip_ops;
 	}
 
-	ndev.msix_io_block = pci_get_io_space_block();
-	kvm__register_mmio(params->kvm, ndev.msix_io_block, 0x100, callback_mmio, NULL);
-	pci_header.bar[1]	= ndev.msix_io_block |
-				PCI_BASE_ADDRESS_SPACE_MEMORY |
-				PCI_BASE_ADDRESS_MEM_TYPE_64;
-	/* bar[2] is the continuation of bar[1] for 64bit addressing */
-	pci_header.bar[2]	= 0;
-	pci_header.status	= PCI_STATUS_CAP_LIST;
-	pci_header.capabilities	= (void *)&pci_header.msix - (void *)&pci_header;
-
-	pci_header.msix.cap = PCI_CAP_ID_MSIX;
-	pci_header.msix.next = 0;
-	pci_header.msix.table_size = (VIRTIO_NET_NUM_QUEUES + 1) | PCI_MSIX_FLAGS_ENABLE;
-	pci_header.msix.table_offset = 1; /* Use BAR 1 */
+	virtio_pci__init(kvm, &ndev.vpci, &ndev, PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET);
+	ndev.vpci.ops = (struct virtio_pci_ops) {
+		.set_config		= set_config,
+		.get_config		= get_config,
+		.get_host_features	= get_host_features,
+		.set_guest_features	= set_guest_features,
+		.init_vq		= init_vq,
+		.notify_vq		= notify_vq,
+		.get_pfn_vq		= get_pfn_vq,
+		.get_size_vq		= get_size_vq,
+	};
 
 	virtio_net__io_thread_init(params->kvm);
 
-	for (i = 0; i < VIRTIO_NET_NUM_QUEUES; i++) {
-		ioevent = (struct ioevent) {
-			.io_addr	= net_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-			.io_len		= sizeof(u16),
-			.fn		= ioevent_callback,
-			.datamatch	= i,
-			.fn_ptr		= (void *)(long)i,
-			.fn_kvm		= params->kvm,
-			.fd		= eventfd(0, 0),
-		};
-
-		ioeventfd__add_event(&ioevent);
-	}
-
 	ndev.compat_id = compat__add_message("virtio-net device was not detected",
 						"While you have requested a virtio-net device, "
 						"the guest kernel didn't seem to detect it.\n"
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/6] kvm tools: Seperate virtio-pci layer out of virtio-balloon
  2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
  2011-08-22 12:58 ` [PATCH 2/6] kvm tools: Seperate virtio-pci layer out of virtio-rng Sasha Levin
  2011-08-22 12:58 ` [PATCH 3/6] kvm tools: Seperate virtio-pci layer out of virtio-net Sasha Levin
@ 2011-08-22 12:58 ` Sasha Levin
  2011-08-22 12:58 ` [PATCH 5/6] kvm tools: Seperate virtio-pci layer out of virtio-9p Sasha Levin
  2011-08-22 12:58 ` [PATCH 6/6] kvm tools: Seperate virtio-pci layer out of virtio-blk Sasha Levin
  4 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/virtio/balloon.c |  267 ++++++++++++++++----------------------------
 1 files changed, 97 insertions(+), 170 deletions(-)

diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
index 7f3fe65..6b93121 100644
--- a/tools/kvm/virtio/balloon.c
+++ b/tools/kvm/virtio/balloon.c
@@ -2,24 +2,24 @@
 
 #include "kvm/virtio-pci-dev.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 "kvm/threadpool.h"
-#include "kvm/irq.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_balloon.h>
 
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <pthread.h>
 
 #define NUM_VIRT_QUEUES		3
@@ -29,17 +29,12 @@
 #define VIRTIO_BLN_STATS	2
 
 struct bln_dev {
-	struct pci_device_header pci_hdr;
 	struct list_head	list;
+	struct virtio_pci	vpci;
 
-	u16			base_addr;
-	u8			status;
-	u8			isr;
-	u16			config_vector;
-	u32			host_features;
+	u32			features;
 
 	/* virtio queue */
-	u16			queue_selector;
 	struct virt_queue	vqs[NUM_VIRT_QUEUES];
 	struct thread_pool__job	jobs[NUM_VIRT_QUEUES];
 
@@ -56,68 +51,6 @@ struct bln_dev {
 static struct bln_dev bdev;
 extern struct kvm *kvm;
 
-static bool virtio_bln_dev_in(void *data, unsigned long offset, int size)
-{
-	u8 *config_space = (u8 *) &bdev.config;
-
-	if (size != 1)
-		return false;
-
-	ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
-
-	return true;
-}
-
-static bool virtio_bln_dev_out(void *data, unsigned long offset, int size)
-{
-	u8 *config_space = (u8 *) &bdev.config;
-
-	if (size != 1)
-		return false;
-
-	config_space[offset - VIRTIO_MSI_CONFIG_VECTOR] = *(u8 *)data;
-
-	return true;
-}
-
-static bool virtio_bln_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
-{
-	unsigned long offset;
-	bool ret = true;
-
-	offset = port - bdev.base_addr;
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, bdev.host_features);
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		ret		= false;
-		break;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, bdev.vqs[bdev.queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTIO_BLN_QUEUE_SIZE);
-		break;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, bdev.status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, bdev.isr);
-		kvm__irq_line(kvm, bdev.pci_hdr.irq_line, VIRTIO_IRQ_LOW);
-		bdev.isr = VIRTIO_IRQ_LOW;
-		break;
-	default:
-		ret = virtio_bln_dev_in(data, offset, size);
-		break;
-	};
-
-	return ret;
-}
-
 static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
 {
 	struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
@@ -182,13 +115,13 @@ static void virtio_bln_do_io(struct kvm *kvm, void *param)
 
 	if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
 		virtio_bln_do_stat_request(kvm, &bdev, vq);
-		virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
+		virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
 		return;
 	}
 
 	while (virt_queue__available(vq)) {
 		virtio_bln_do_io_request(kvm, &bdev, vq);
-		virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
+		virtio_pci__signal_vq(kvm, &bdev.vpci, vq - bdev.vqs);
 	}
 }
 
@@ -197,82 +130,13 @@ static void ioevent_callback(struct kvm *kvm, void *param)
 	thread_pool__do_job(param);
 }
 
-static bool virtio_bln_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
-{
-	unsigned long offset;
-	bool ret = true;
-	struct ioevent ioevent;
-
-	offset = port - bdev.base_addr;
-
-	switch (offset) {
-	case VIRTIO_MSI_QUEUE_VECTOR:
-	case VIRTIO_PCI_GUEST_FEATURES:
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		void *p;
-
-		compat__remove_message(bdev.compat_id);
-
-		queue			= &bdev.vqs[bdev.queue_selector];
-		queue->pfn		= ioport__read32(data);
-		p			= guest_pfn_to_host(kvm, queue->pfn);
-
-		vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
-
-		thread_pool__init_job(&bdev.jobs[bdev.queue_selector], kvm, virtio_bln_do_io, queue);
-
-		ioevent = (struct ioevent) {
-			.io_addr		= bdev.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-			.io_len			= sizeof(u16),
-			.fn			= ioevent_callback,
-			.fn_ptr			= &bdev.jobs[bdev.queue_selector],
-			.datamatch		= bdev.queue_selector,
-			.fn_kvm			= kvm,
-			.fd			= eventfd(0, 0),
-		};
-
-		ioeventfd__add_event(&ioevent);
-
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		bdev.queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		u16 queue_index;
-		queue_index		= ioport__read16(data);
-		thread_pool__do_job(&bdev.jobs[queue_index]);
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		bdev.status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		bdev.config_vector	= VIRTIO_MSI_NO_VECTOR;
-		break;
-	default:
-		ret = virtio_bln_dev_out(data, offset, size);
-		break;
-	};
-
-	return ret;
-}
-
-static struct ioport_operations virtio_bln_io_ops = {
-	.io_in				= virtio_bln_pci_io_in,
-	.io_out				= virtio_bln_pci_io_out,
-};
-
 static int virtio_bln__collect_stats(void)
 {
 	u64 tmp;
 
 	virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
 				  sizeof(struct virtio_balloon_stat));
-	virt_queue__trigger_irq(&bdev.vqs[VIRTIO_BLN_STATS], bdev.pci_hdr.irq_line,
-				&bdev.isr, kvm);
+	virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
 
 	if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
 		return -EFAULT;
@@ -332,44 +196,107 @@ static void handle_sigmem(int sig)
 	}
 
 	/* Notify that the configuration space has changed */
-	bdev.isr = VIRTIO_PCI_ISR_CONFIG;
-	kvm__irq_line(kvm, bdev.pci_hdr.irq_line, 1);
+	virtio_pci__signal_config(kvm, &bdev.vpci);
 }
 
-void virtio_bln__init(struct kvm *kvm)
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
 {
-	u8 pin, line, dev;
-	u16 bdev_base_addr;
+	struct bln_dev *bdev = dev;
 
-	signal(SIGKVMADDMEM, handle_sigmem);
-	signal(SIGKVMDELMEM, handle_sigmem);
-	signal(SIGKVMMEMSTAT, handle_sigmem);
+	((u8 *)(&bdev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct bln_dev *bdev = dev;
 
-	bdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_bln_io_ops, IOPORT_SIZE, &bdev);
-
-	bdev.pci_hdr = (struct pci_device_header) {
-		.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-		.device_id		= PCI_DEVICE_ID_VIRTIO_BLN,
-		.header_type		= PCI_HEADER_TYPE_NORMAL,
-		.revision_id		= 0,
-		.class			= 0x010000,
-		.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-		.subsys_id		= VIRTIO_ID_BALLOON,
-		.bar[0]			= bdev_base_addr | PCI_BASE_ADDRESS_SPACE_IO,
+	return ((u8 *)(&bdev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1 << VIRTIO_BALLOON_F_STATS_VQ;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct bln_dev *bdev = dev;
+
+	bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct bln_dev *bdev = dev;
+	struct virt_queue *queue;
+	void *p;
+	struct ioevent ioevent;
+
+	compat__remove_message(bdev->compat_id);
+
+	queue			= &bdev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	thread_pool__init_job(&bdev->jobs[vq], kvm, virtio_bln_do_io, queue);
+	vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	ioevent = (struct ioevent) {
+		.io_addr	= bdev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= ioevent_callback,
+		.fn_ptr		= &bdev->jobs[vq],
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
 	};
 
-	bdev.base_addr = bdev_base_addr;
+	ioeventfd__add_event(&ioevent);
 
-	if (irq__register_device(VIRTIO_ID_BALLOON, &dev, &pin, &line) < 0)
-		return;
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct bln_dev *bdev = dev;
+
+	thread_pool__do_job(&bdev->jobs[vq]);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct bln_dev *bdev = dev;
+
+	return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_BLN_QUEUE_SIZE;
+}
+
+void virtio_bln__init(struct kvm *kvm)
+{
+	signal(SIGKVMADDMEM, handle_sigmem);
+	signal(SIGKVMDELMEM, handle_sigmem);
+	signal(SIGKVMMEMSTAT, handle_sigmem);
 
-	bdev.pci_hdr.irq_pin	= pin;
-	bdev.pci_hdr.irq_line	= line;
-	bdev.host_features	= 1 << VIRTIO_BALLOON_F_STATS_VQ;
 	bdev.stat_waitfd	= eventfd(0, 0);
 	memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
 
-	pci__register(&bdev.pci_hdr, dev);
+	virtio_pci__init(kvm, &bdev.vpci, &bdev, PCI_DEVICE_ID_VIRTIO_BLN, VIRTIO_ID_BALLOON);
+	bdev.vpci.ops = (struct virtio_pci_ops) {
+		.set_config		= set_config,
+		.get_config		= get_config,
+		.get_host_features	= get_host_features,
+		.set_guest_features	= set_guest_features,
+		.init_vq		= init_vq,
+		.notify_vq		= notify_vq,
+		.get_pfn_vq		= get_pfn_vq,
+		.get_size_vq		= get_size_vq,
+	};
 
 	bdev.compat_id = compat__add_message("virtio-balloon device was not detected",
 						"While you have requested a virtio-balloon device, "
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/6] kvm tools: Seperate virtio-pci layer out of virtio-9p
  2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
                   ` (2 preceding siblings ...)
  2011-08-22 12:58 ` [PATCH 4/6] kvm tools: Seperate virtio-pci layer out of virtio-balloon Sasha Levin
@ 2011-08-22 12:58 ` Sasha Levin
  2011-08-22 12:58 ` [PATCH 6/6] kvm tools: Seperate virtio-pci layer out of virtio-blk Sasha Levin
  4 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/builtin-run.c           |    8 +-
 tools/kvm/include/kvm/virtio-9p.h |   16 ++--
 tools/kvm/virtio/9p.c             |  247 +++++++++++++++----------------------
 3 files changed, 111 insertions(+), 160 deletions(-)

diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index 501e0bf..00f9b25 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -106,7 +106,7 @@ static int img_name_parser(const struct option *opt, const char *arg, int unset)
 		char tmp[PATH_MAX];
 
 		if (realpath(arg, tmp) == 0 ||
-		    virtio_9p__init(kvm, tmp, "/dev/root") < 0)
+		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
 			die("Unable to initialize virtio 9p");
 		using_rootfs = 1;
 		return 0;
@@ -144,7 +144,7 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
 		tag_name++;
 	}
 	if (realpath(arg, tmp)) {
-		if (virtio_9p__init(kvm, tmp, tag_name) < 0)
+		if (virtio_9p__register(kvm, tmp, tag_name) < 0)
 			die("Unable to initialize virtio 9p");
 	} else
 		die("Failed resolving 9p path");
@@ -598,7 +598,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
 
 	if (!using_rootfs && !image_filename[0]) {
-		if (virtio_9p__init(kvm, "/", "/dev/root") < 0)
+		if (virtio_9p__register(kvm, "/", "/dev/root") < 0)
 			die("Unable to initialize virtio 9p");
 
 		using_rootfs = 1;
@@ -650,6 +650,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 	if (!network)
 		network = DEFAULT_NETWORK;
 
+	virtio_9p__init(kvm);
+
 	if (strncmp(network, "none", 4)) {
 		net_params.guest_ip = guest_ip;
 		net_params.host_ip = host_ip;
diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
index 70db831..7ce56b7 100644
--- a/tools/kvm/include/kvm/virtio-9p.h
+++ b/tools/kvm/include/kvm/virtio-9p.h
@@ -3,9 +3,11 @@
 #include "kvm/virtio.h"
 #include "kvm/pci.h"
 #include "kvm/threadpool.h"
+#include "kvm/virtio-pci.h"
 
 #include <sys/types.h>
 #include <dirent.h>
+#include <linux/list.h>
 
 #define NUM_VIRT_QUEUES		1
 #define VIRTQUEUE_NUM		128
@@ -38,21 +40,18 @@ struct p9_dev_job {
 };
 
 struct p9_dev {
-	u8			status;
-	u8			isr;
-	u16			config_vector;
-	u32			features;
+	struct list_head	list;
+	struct virtio_pci	vpci;
+	
 	struct virtio_9p_config	*config;
-	u16			base_addr;
 	int			compat_id;
+	u32			features;
 
 	/* virtio queue */
-	u16			queue_selector;
 	struct virt_queue	vqs[NUM_VIRT_QUEUES];
 	struct p9_dev_job	jobs[NUM_VIRT_QUEUES];
 	struct p9_fid		fids[VIRTIO_P9_MAX_FID];
 	char			root_dir[PATH_MAX];
-	struct pci_device_header pci_hdr;
 };
 
 struct p9_pdu {
@@ -67,7 +66,8 @@ struct p9_pdu {
 
 struct kvm;
 
-int virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name);
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name);
+int virtio_9p__init(struct kvm *kvm);
 int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
 int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
 
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
index 8a4fe73..e5c106a 100644
--- a/tools/kvm/virtio/9p.c
+++ b/tools/kvm/virtio/9p.c
@@ -19,6 +19,8 @@
 #include <linux/virtio_9p.h>
 #include <net/9p/9p.h>
 
+static LIST_HEAD(devs);
+
 /* Warning: Immediately use value returned from this function */
 static const char *rel_to_abs(struct p9_dev *p9dev,
 			      const char *path, char *abs_path)
@@ -28,62 +30,6 @@ static const char *rel_to_abs(struct p9_dev *p9dev,
 	return abs_path;
 }
 
-static bool virtio_p9_dev_in(struct p9_dev *p9dev, void *data,
-			     unsigned long offset,
-			     int size)
-{
-	u8 *config_space = (u8 *) p9dev->config;
-
-	if (size != 1)
-		return false;
-
-	ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
-
-	return true;
-}
-
-static bool virtio_p9_pci_io_in(struct ioport *ioport, struct kvm *kvm,
-				u16 port, void *data, int size)
-{
-	bool ret = true;
-	unsigned long offset;
-	struct p9_dev *p9dev = ioport->priv;
-
-
-	offset = port - p9dev->base_addr;
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, p9dev->features);
-		ret = true;
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-	case VIRTIO_PCI_QUEUE_SEL:
-	case VIRTIO_PCI_QUEUE_NOTIFY:
-		ret = false;
-		break;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, p9dev->vqs[p9dev->queue_selector].pfn);
-		break;
-	case VIRTIO_PCI_QUEUE_NUM:
-		ioport__write16(data, VIRTQUEUE_NUM);
-		break;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, p9dev->status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, p9dev->isr);
-		kvm__irq_line(kvm, p9dev->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
-		p9dev->isr = VIRTIO_IRQ_LOW;
-		break;
-	default:
-		ret = virtio_p9_dev_in(p9dev, data, offset, size);
-		break;
-	};
-
-	return ret;
-}
-
 static int omode2uflags(u8 mode)
 {
 	int ret = 0;
@@ -750,8 +696,7 @@ static void virtio_p9_do_io(struct kvm *kvm, void *param)
 
 	while (virt_queue__available(vq)) {
 		virtio_p9_do_io_request(kvm, job);
-		virt_queue__trigger_irq(vq, p9dev->pci_hdr.irq_line,
-					&p9dev->isr, kvm);
+		virtio_pci__signal_vq(kvm, &p9dev->vpci, vq - p9dev->vqs);
 	}
 }
 
@@ -762,90 +707,115 @@ static void ioevent_callback(struct kvm *kvm, void *param)
 	thread_pool__do_job(&job->job_id);
 }
 
-static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
-				 u16 port, void *data, int size)
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
 {
-	unsigned long offset;
-	bool ret = true;
-	struct p9_dev  *p9dev;
-	struct ioevent ioevent;
+	struct p9_dev *p9dev = dev;
 
-	p9dev = ioport->priv;
-	offset = port - p9dev->base_addr;
+	((u8 *)(p9dev->config))[offset] = data;
+}
 
-	switch (offset) {
-	case VIRTIO_MSI_QUEUE_VECTOR:
-	case VIRTIO_PCI_GUEST_FEATURES:
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		void *p;
-		struct p9_dev_job *job;
-		struct virt_queue *queue;
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct p9_dev *p9dev = dev;
 
-		compat__remove_message(p9dev->compat_id);
+	return ((u8 *)(p9dev->config))[offset];
+}
 
-		job			= &p9dev->jobs[p9dev->queue_selector];
-		queue			= &p9dev->vqs[p9dev->queue_selector];
-		queue->pfn		= ioport__read32(data);
-		p			= guest_pfn_to_host(kvm, queue->pfn);
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1 << VIRTIO_9P_MOUNT_TAG;
+}
 
-		vring_init(&queue->vring, VIRTQUEUE_NUM, p,
-			   VIRTIO_PCI_VRING_ALIGN);
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct p9_dev *p9dev = dev;
 
-		*job			= (struct p9_dev_job) {
-			.vq			= queue,
-			.p9dev			= p9dev,
-		};
-		thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
-
-		ioevent = (struct ioevent) {
-			.io_addr		= p9dev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-			.io_len			= sizeof(u16),
-			.fn			= ioevent_callback,
-			.datamatch		= p9dev->queue_selector,
-			.fn_ptr			= &p9dev->jobs[p9dev->queue_selector],
-			.fn_kvm			= kvm,
-			.fd			= eventfd(0, 0),
-		};
+	p9dev->features = features;
+}
 
-		ioeventfd__add_event(&ioevent);
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct p9_dev *p9dev = dev;
+	struct p9_dev_job *job;
+	struct virt_queue *queue;
+	void *p;
+	struct ioevent ioevent;
 
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		p9dev->queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		u16 queue_index;
-
-		queue_index		= ioport__read16(data);
-		thread_pool__do_job(&p9dev->jobs[queue_index].job_id);
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		p9dev->status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		p9dev->config_vector	= VIRTIO_MSI_NO_VECTOR;
-		break;
-	default:
-		ret			= false;
-		break;
+	compat__remove_message(p9dev->compat_id);
+
+	queue			= &p9dev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+	job			= &p9dev->jobs[vq];
+
+	vring_init(&queue->vring, VIRTQUEUE_NUM, p, VIRTIO_PCI_VRING_ALIGN);
+
+	*job			= (struct p9_dev_job) {
+		.vq			= queue,
+		.p9dev			= p9dev,
+	};
+	thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
+
+	ioevent = (struct ioevent) {
+		.io_addr	= p9dev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= ioevent_callback,
+		.fn_ptr		= &p9dev->jobs[vq],
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
 	};
 
-	return ret;
+	ioeventfd__add_event(&ioevent);
+
+	return 0;
 }
 
-static struct ioport_operations virtio_p9_io_ops = {
-	.io_in				= virtio_p9_pci_io_in,
-	.io_out				= virtio_p9_pci_io_out,
-};
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct p9_dev *p9dev = dev;
+
+	thread_pool__do_job(&p9dev->jobs[vq].job_id);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct p9_dev *p9dev = dev;
+
+	return p9dev->vqs[vq].pfn;
+}
 
-int virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name)
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTQUEUE_NUM;
+}
+
+int virtio_9p__init(struct kvm *kvm)
+{
+	struct p9_dev *p9dev;
+
+	list_for_each_entry(p9dev, &devs, list) {
+		virtio_pci__init(kvm, &p9dev->vpci, p9dev, PCI_DEVICE_ID_VIRTIO_P9, VIRTIO_ID_9P);
+		p9dev->vpci.ops = (struct virtio_pci_ops) {
+			.set_config		= set_config,
+			.get_config		= get_config,
+			.get_host_features	= get_host_features,
+			.set_guest_features	= set_guest_features,
+			.init_vq		= init_vq,
+			.notify_vq		= notify_vq,
+			.get_pfn_vq		= get_pfn_vq,
+			.get_size_vq		= get_size_vq,
+		};
+	}
+
+	return 0;
+}
+
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name)
 {
 	struct p9_dev *p9dev;
-	u8 pin, line, dev;
-	u16 p9_base_addr;
 	u32 i, root_len;
 	int err = 0;
 
@@ -878,30 +848,9 @@ int virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name)
 		goto free_p9dev_config;
 	}
 
-	memcpy(p9dev->config->tag, tag_name, strlen(tag_name));
-	p9dev->features |= 1 << VIRTIO_9P_MOUNT_TAG;
+	memcpy(&p9dev->config->tag, tag_name, strlen(tag_name));
 
-	err = irq__register_device(VIRTIO_ID_9P, &dev, &pin, &line);
-	if (err < 0)
-		goto free_p9dev_config;
-
-	p9_base_addr = ioport__register(IOPORT_EMPTY, &virtio_p9_io_ops, IOPORT_SIZE, p9dev);
-
-	p9dev->base_addr = p9_base_addr;
-
-	p9dev->pci_hdr = (struct pci_device_header) {
-		.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-		.device_id		= PCI_DEVICE_ID_VIRTIO_P9,
-		.header_type		= PCI_HEADER_TYPE_NORMAL,
-		.revision_id		= 0,
-		.class			= 0x010000,
-		.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-		.subsys_id		= VIRTIO_ID_9P,
-		.irq_pin		= pin,
-		.irq_line		= line,
-		.bar[0]			= p9_base_addr | PCI_BASE_ADDRESS_SPACE_IO,
-	};
-	pci__register(&p9dev->pci_hdr, dev);
+	list_add(&p9dev->list, &devs);
 
 	p9dev->compat_id = compat__add_message("virtio-9p device was not detected",
 						"While you have requested a virtio-9p device, "
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] kvm tools: Seperate virtio-pci layer out of virtio-blk
  2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
                   ` (3 preceding siblings ...)
  2011-08-22 12:58 ` [PATCH 5/6] kvm tools: Seperate virtio-pci layer out of virtio-9p Sasha Levin
@ 2011-08-22 12:58 ` Sasha Levin
  4 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-22 12:58 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/virtio/blk.c |  263 ++++++++++++++++--------------------------------
 1 files changed, 88 insertions(+), 175 deletions(-)

diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 2ccf585..2e047d7 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -1,10 +1,8 @@
 #include "kvm/virtio-blk.h"
 
 #include "kvm/virtio-pci-dev.h"
-#include "kvm/irq.h"
 #include "kvm/disk-image.h"
 #include "kvm/virtio.h"
-#include "kvm/ioport.h"
 #include "kvm/mutex.h"
 #include "kvm/util.h"
 #include "kvm/kvm.h"
@@ -12,10 +10,12 @@
 #include "kvm/threadpool.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_blk.h>
 
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <pthread.h>
@@ -41,88 +41,19 @@ struct blk_dev {
 	pthread_mutex_t			mutex;
 	struct list_head		list;
 
+	struct virtio_pci		vpci;
 	struct virtio_blk_config	blk_config;
 	struct disk_image		*disk;
-	u64				base_addr;
-	u32				host_features;
-	u32				guest_features;
-	u16				config_vector;
-	u8				status;
-	u8				isr;
 	int				compat_id;
-
-	/* virtio queue */
-	u16				queue_selector;
+	u32				features;
 
 	struct virt_queue		vqs[NUM_VIRT_QUEUES];
 	struct blk_dev_job		jobs[VIRTIO_BLK_QUEUE_SIZE];
 	u16				job_idx;
-	struct pci_device_header	pci_hdr;
 };
 
 static LIST_HEAD(bdevs);
 
-static bool virtio_blk_dev_in(struct blk_dev *bdev, void *data, unsigned long offset, int size)
-{
-	u8 *config_space = (u8 *) &bdev->blk_config;
-
-	if (size != 1)
-		return false;
-
-	ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
-
-	return true;
-}
-
-static bool virtio_blk_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
-{
-	struct blk_dev *bdev;
-	u16 offset;
-	bool ret = true;
-
-	bdev	= ioport->priv;
-	offset	= port - bdev->base_addr;
-
-	mutex_lock(&bdev->mutex);
-
-	switch (offset) {
-	case VIRTIO_PCI_HOST_FEATURES:
-		ioport__write32(data, bdev->host_features);
-		break;
-	case VIRTIO_PCI_GUEST_FEATURES:
-		ret		= false;
-		break;
-	case VIRTIO_PCI_QUEUE_PFN:
-		ioport__write32(data, bdev->vqs[bdev->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:
-		ret		= false;
-		break;
-	case VIRTIO_PCI_STATUS:
-		ioport__write8(data, bdev->status);
-		break;
-	case VIRTIO_PCI_ISR:
-		ioport__write8(data, bdev->isr);
-		kvm__irq_line(kvm, bdev->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
-		bdev->isr = VIRTIO_IRQ_LOW;
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		ioport__write16(data, bdev->config_vector);
-		break;
-	default:
-		ret = virtio_blk_dev_in(bdev, data, offset, size);
-		break;
-	};
-
-	mutex_unlock(&bdev->mutex);
-
-	return ret;
-}
-
 static void virtio_blk_do_io_request(struct kvm *kvm, void *param)
 {
 	struct virtio_blk_outhdr *req;
@@ -172,7 +103,7 @@ static void virtio_blk_do_io_request(struct kvm *kvm, void *param)
 	virt_queue__set_used_elem(queue, head, block_cnt);
 	mutex_unlock(&bdev->mutex);
 
-	virt_queue__trigger_irq(queue, bdev->pci_hdr.irq_line, &bdev->isr, kvm);
+	virtio_pci__signal_vq(kvm, &bdev->vpci, queue - bdev->vqs);
 }
 
 static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct blk_dev *bdev)
@@ -191,82 +122,93 @@ static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct blk_
 	}
 }
 
-static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+static void ioevent_callback(struct kvm *kvm, void *param)
 {
-	struct blk_dev *bdev;
-	u16 offset;
-	bool ret = true;
+	struct blk_dev *bdev = param;
 
-	bdev	= ioport->priv;
-	offset	= port - bdev->base_addr;
+	virtio_blk_do_io(kvm, &bdev->vqs[0], bdev);
+}
 
-	mutex_lock(&bdev->mutex);
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct blk_dev *bdev = dev;
 
-	switch (offset) {
-	case VIRTIO_PCI_GUEST_FEATURES:
-		bdev->guest_features	= ioport__read32(data);
-		break;
-	case VIRTIO_PCI_QUEUE_PFN: {
-		struct virt_queue *queue;
-		void *p;
+	((u8 *)(&bdev->blk_config))[offset] = data;
+}
 
-		compat__remove_message(bdev->compat_id);
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct blk_dev *bdev = dev;
 
-		queue			= &bdev->vqs[bdev->queue_selector];
-		queue->pfn		= ioport__read32(data);
-		p			= guest_pfn_to_host(kvm, queue->pfn);
+	return ((u8 *)(&bdev->blk_config))[offset];
+}
 
-		vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1UL << VIRTIO_BLK_F_SEG_MAX | 1UL << VIRTIO_BLK_F_FLUSH;
+}
 
-		break;
-	}
-	case VIRTIO_PCI_QUEUE_SEL:
-		bdev->queue_selector	= ioport__read16(data);
-		break;
-	case VIRTIO_PCI_QUEUE_NOTIFY: {
-		u16 queue_index;
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct blk_dev *bdev = dev;
 
-		queue_index		= ioport__read16(data);
-		virtio_blk_do_io(kvm, &bdev->vqs[queue_index], bdev);
+	bdev->features = features;
+}
 
-		break;
-	}
-	case VIRTIO_PCI_STATUS:
-		bdev->status		= ioport__read8(data);
-		break;
-	case VIRTIO_MSI_CONFIG_VECTOR:
-		bdev->config_vector	= VIRTIO_MSI_NO_VECTOR;
-		break;
-	case VIRTIO_MSI_QUEUE_VECTOR:
-		break;
-	default:
-		ret			= false;
-		break;
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct blk_dev *bdev = dev;
+	struct virt_queue *queue;
+	void *p;
+	struct ioevent ioevent;
+
+	compat__remove_message(bdev->compat_id);
+
+	queue			= &bdev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	ioevent = (struct ioevent) {
+		.io_addr	= bdev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= ioevent_callback,
+		.fn_ptr		= bdev,
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
 	};
 
-	mutex_unlock(&bdev->mutex);
+	ioeventfd__add_event(&ioevent);
 
-	return ret;
+	return 0;
 }
 
-static struct ioport_operations virtio_blk_io_ops = {
-	.io_in	= virtio_blk_pci_io_in,
-	.io_out	= virtio_blk_pci_io_out,
-};
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct blk_dev *bdev = dev;
 
-static void ioevent_callback(struct kvm *kvm, void *param)
+	virtio_blk_do_io(kvm, &bdev->vqs[vq], bdev);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
 {
-	struct blk_dev *bdev = param;
+	struct blk_dev *bdev = dev;
 
-	virtio_blk_do_io(kvm, &bdev->vqs[0], bdev);
+	return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_BLK_QUEUE_SIZE;
 }
 
 void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 {
-	u16 blk_dev_base_addr;
-	u8 dev, pin, line, i;
 	struct blk_dev *bdev;
-	struct ioevent ioevent;
 
 	if (!disk)
 		return;
@@ -275,57 +217,28 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 	if (bdev == NULL)
 		die("Failed allocating bdev");
 
-	blk_dev_base_addr	= ioport__register(IOPORT_EMPTY, &virtio_blk_io_ops, IOPORT_SIZE, bdev);
-
-	*bdev			= (struct blk_dev) {
-		.mutex				= PTHREAD_MUTEX_INITIALIZER,
-		.disk				= disk,
-		.base_addr			= blk_dev_base_addr,
-		.blk_config			= (struct virtio_blk_config) {
-			.capacity		= disk->size / SECTOR_SIZE,
-			.seg_max		= DISK_SEG_MAX,
-		},
-		.pci_hdr = (struct pci_device_header) {
-			.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		= VIRTIO_ID_BLOCK,
-			.bar[0]			= blk_dev_base_addr | PCI_BASE_ADDRESS_SPACE_IO,
+	*bdev = (struct blk_dev) {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+		.disk			= disk,
+		.blk_config		= (struct virtio_blk_config) {
+			.capacity	= disk->size / SECTOR_SIZE,
+			.seg_max	= DISK_SEG_MAX,
 		},
-		/*
-		 * Note we don't set VIRTIO_BLK_F_GEOMETRY here so the
-		 * guest kernel will compute disk geometry by own, the
-		 * same applies to VIRTIO_BLK_F_BLK_SIZE
-		 */
-		.host_features			= (1UL << VIRTIO_BLK_F_SEG_MAX | 1UL << VIRTIO_BLK_F_FLUSH),
 	};
 
-	list_add_tail(&bdev->list, &bdevs);
-
-	if (irq__register_device(VIRTIO_ID_BLOCK, &dev, &pin, &line) < 0)
-		return;
-
-	bdev->pci_hdr.irq_pin	= pin;
-	bdev->pci_hdr.irq_line	= line;
-
-	pci__register(&bdev->pci_hdr, dev);
-
-	for (i = 0; i < NUM_VIRT_QUEUES; i++) {
-		ioevent = (struct ioevent) {
-			.io_addr		= blk_dev_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-			.io_len			= sizeof(u16),
-			.fn			= ioevent_callback,
-			.datamatch		= i,
-			.fn_ptr			= bdev,
-			.fn_kvm			= kvm,
-			.fd			= eventfd(0, 0),
-		};
+	virtio_pci__init(kvm, &bdev->vpci, bdev, PCI_DEVICE_ID_VIRTIO_BLK, VIRTIO_ID_BLOCK);
+	bdev->vpci.ops = (struct virtio_pci_ops) {
+		.set_config		= set_config,
+		.get_config		= get_config,
+		.get_host_features	= get_host_features,
+		.set_guest_features	= set_guest_features,
+		.init_vq		= init_vq,
+		.notify_vq		= notify_vq,
+		.get_pfn_vq		= get_pfn_vq,
+		.get_size_vq		= get_size_vq,
+	};
 
-		ioeventfd__add_event(&ioevent);
-	}
+	list_add_tail(&bdev->list, &bdevs);
 
 	bdev->compat_id = compat__add_message("virtio-blk device was not detected",
 						"While you have requested a virtio-blk device, "
@@ -348,7 +261,7 @@ void virtio_blk__delete_all(struct kvm *kvm)
 		struct blk_dev *bdev;
 
 		bdev = list_first_entry(&bdevs, struct blk_dev, list);
-		ioeventfd__del_event(bdev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 0);
+		ioeventfd__del_event(bdev->vpci.base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 0);
 		list_del(&bdev->list);
 		free(bdev);
 	}
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-08-22 13:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-22 12:58 [PATCH 1/6] kvm tools: Seperate virtio-pci layer Sasha Levin
2011-08-22 12:58 ` [PATCH 2/6] kvm tools: Seperate virtio-pci layer out of virtio-rng Sasha Levin
2011-08-22 12:58 ` [PATCH 3/6] kvm tools: Seperate virtio-pci layer out of virtio-net Sasha Levin
2011-08-22 12:58 ` [PATCH 4/6] kvm tools: Seperate virtio-pci layer out of virtio-balloon Sasha Levin
2011-08-22 12:58 ` [PATCH 5/6] kvm tools: Seperate virtio-pci layer out of virtio-9p Sasha Levin
2011-08-22 12:58 ` [PATCH 6/6] kvm tools: Seperate virtio-pci layer out of virtio-blk Sasha Levin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.