Skip to contentSkip to conversation

AlacrityVM guest drivers

PATCH In review Gregory Haskins 10 participants 61 messages Aug 3, 2009 – Oct 2, 2009

Subsystems (5)
Networking Network drivers x86 KVM +1 more subsystems
lore
Share & tools
lore
#0 lore raw

cover AlacrityVM guest drivers

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

Regards,
-Greg

---

Gregory Haskins (7):
venet: add scatter-gather/GSO support
net: Add vbus_enet driver
ioq: add driver-side vbus helpers
vbus-proxy: add a pci-to-vbus bridge
vbus: add a "vbus-proxy" bus model for vbus_driver objects
ioq: Add basic definitions for a shared-memory, lockless queue
shm-signal: shared-memory signals

 arch/x86/Kconfig            |    2 
 drivers/Makefile            |    1 
 drivers/net/Kconfig         |   14 +
 drivers/net/Makefile        |    1 
 drivers/net/vbus-enet.c     |  899 +++++++++++++++++++++++++++++++++++++++++++
 drivers/vbus/Kconfig        |   24 +
 drivers/vbus/Makefile       |    6 
 drivers/vbus/bus-proxy.c    |  216 ++++++++++
 drivers/vbus/pci-bridge.c   |  824 +++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild        |    4 
 include/linux/ioq.h         |  415 ++++++++++++++++++++
 include/linux/shm_signal.h  |  189 +++++++++
 include/linux/vbus_driver.h |   80 ++++
 include/linux/vbus_pci.h    |  127 ++++++
 include/linux/venet.h       |   84 ++++
 lib/Kconfig                 |   21 +
 lib/Makefile                |    2 
 lib/ioq.c                   |  294 ++++++++++++++
 lib/shm_signal.c            |  192 +++++++++
 19 files changed, 3395 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 drivers/vbus/Kconfig
 create mode 100644 drivers/vbus/Makefile
 create mode 100644 drivers/vbus/bus-proxy.c
 create mode 100644 drivers/vbus/pci-bridge.c
 create mode 100644 include/linux/ioq.h
 create mode 100644 include/linux/shm_signal.h
 create mode 100644 include/linux/vbus_driver.h
 create mode 100644 include/linux/vbus_pci.h
 create mode 100644 include/linux/venet.h
 create mode 100644 lib/ioq.c
 create mode 100644 lib/shm_signal.c
Signature · 1 line
Signature
#1 lore raw

PATCH 1/7 shm-signal: shared-memory signals

shm-signal provides a generic shared-memory based bidirectional signaling mechanism. It is used in conjunction with an existing signal transport (such as posix-signals, interrupts, pipes, etc) to increase the efficiency of the transport since the state information is directly accessible to both sides of the link. The shared-memory design provides very cheap access to features such as event-masking and spurious delivery mititgation, and is useful implementing higher level shared-memory constructs such as rings.

We will use this mechanism as the basis for a shared-memory interface later in the series.

---

 include/linux/Kbuild       |    1 
 include/linux/shm_signal.h |  189 +++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig                |    9 ++
 lib/Makefile               |    1 
 lib/shm_signal.c           |  192 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 392 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/shm_signal.h
 create mode 100644 lib/shm_signal.c
include/linux/Kbuild +1 -0
index 334a359..01d67b6 100644
@@ -331,6 +331,7 @@ unifdef-y += serial_core.h
 unifdef-y += serial.h
 unifdef-y += serio.h
 unifdef-y += shm.h
+unifdef-y += shm_signal.h
 unifdef-y += signal.h
 unifdef-y += smb_fs.h
 unifdef-y += smb.h
include/linux/shm_signal.h new file +189 -0

189 lines not on this page · raw message

lib/Kconfig +9 -0
index bb1326d..136da19 100644
@@ -200,4 +200,13 @@ config NLATTR
 config GENERIC_ATOMIC64
        bool
 
+config SHM_SIGNAL
+	tristate "SHM Signal - Generic shared-memory signaling mechanism"
+	default n
+	help
+	 Provides a shared-memory based signaling mechansim to indicate
+         memory-dirty notifications between two end-points.
+
+	 If unsure, say N
+
 endmenu
lib/Makefile +1 -0
index 2e78277..503bf7b 100644
@@ -76,6 +76,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
 obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
 obj-$(CONFIG_SMP) += percpu_counter.o
 obj-$(CONFIG_AUDIT_GENERIC) += audit.o
+obj-$(CONFIG_SHM_SIGNAL) += shm_signal.o
 
 obj-$(CONFIG_SWIOTLB) += swiotlb.o
 obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o
lib/shm_signal.c new file +192 -0

192 lines not on this page · raw message

#2 lore raw

Re: [PATCH 1/7] shm-signal: shared-memory signals

Quoted 8 lines · Gregory Haskins

shm-signal provides a generic shared-memory based bidirectional signaling mechanism. It is used in conjunction with an existing signal transport (such as posix-signals, interrupts, pipes, etc) to increase the efficiency of the transport since the state information is directly accessible to both sides of the link. The shared-memory design provides very cheap access to features such as event-masking and spurious delivery mititgation, and is useful implementing higher level shared-memory constructs such as rings.

Looks like a very useful feature in general.

include/linux/shm_signal.h line 42

Quoted 5 lines
include/linux/shm_signal.h new file +5 -0
+struct shm_signal_irq {
+       __u8                  enabled;
+       __u8                  pending;
+       __u8                  dirty;
+};

Won't this layout cause cache line ping pong? Other schemes I have seen try to separate the bits so that each cache line is written to by only one side. This gets much more interesting if the two sides are on remote ends of an I/O link, e.g. using a nontransparent PCI bridge, where you only want to send stores over the wire, but never fetches or even read-modify-write cycles.

Your code is probably optimal if you only communicate between host and guest code on the same CPU, but not so good if it crosses NUMA nodes or worse.

include/linux/shm_signal.h line 53

Quoted 5 lines
include/linux/shm_signal.h new file +5 -0
+struct shm_signal_desc {
+       __u32                 magic;
+       __u32                 ver;
+       struct shm_signal_irq irq[2];
+};

This data structure has implicit padding of two bytes at the end. How about adding another '__u16 reserved' to make it explicit?

Quoted 9 lines
lib/shm_signal.c new file +9 -0
+	/*
+	 * We always mark the remote side as dirty regardless of whether
+	 * they need to be notified.
+	 */
+	irq->dirty = 1;
+	wmb();   /* dirty must be visible before we test the pending state */
+
+	if (irq->enabled && !irq->pending) {
+		rmb();

lib/shm_signal.c line 98

Quoted 10 lines
lib/shm_signal.c new file +10 -0
+
+		/*
+		 * If the remote side has enabled notifications, and we do
+		 * not see a notification pending, we must inject a new one.
+		 */
+		irq->pending = 1;
+		wmb(); /* make it visible before we do the injection */
+
+		s->ops->inject(s);
+	}

Barriers always confuse me, but the rmb() looks slightly wrong. AFAIU it only prevents reads after the barrier from being done before the barrier, but you don't do any reads after it.

The (irq->enabled && !irq->pending) check could be done before the irq->dirty = 1 arrives at the bus, but that does not seem to hurt, it would at most cause a duplicate ->inject().

Regarding the scope of the barrier, did you intentionally use the global versions (rmb()/wmb()) and not the lighter single-system (smp_rmb()/smp_wmb()) versions? Your version should cope with remote links over PCI but looks otherwise optimized for local use, as I wrote above.

	Arnd <><
#3 lore raw

Re: [PATCH 1/7] shm-signal: shared-memory signals

Hi Arnd,

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 9:56 AM, in message <[email protected]>, Arnd

Quoted 11 lines · Bergmann
Quoted 8 lines · Gregory Haskins

shm-signal provides a generic shared-memory based bidirectional signaling mechanism. It is used in conjunction with an existing signal transport (such as posix-signals, interrupts, pipes, etc) to increase the efficiency of the transport since the state information is directly accessible to both sides of the link. The shared-memory design provides very cheap access to features such as event-masking and spurious delivery mititgation, and is useful implementing higher level shared-memory constructs such as rings.

Looks like a very useful feature in general.

Thanks, I was hoping that would be the case.

Quoted 10 lines

include/linux/shm_signal.h line 42

Quoted 6 lines
include/linux/shm_signal.h new file +5 -0
+struct shm_signal_irq {
+       __u8                  enabled;
+       __u8                  pending;
+       __u8                  dirty;
+};

Won't this layout cause cache line ping pong? Other schemes I have seen try to separate the bits so that each cache line is written to by only one side.

It could possibly use some optimization in that regard. I generally consider myself an expert at concurrent programming, but this lockless stuff is, um, hard ;) I was going for correctness first.

Long story short, any suggestions on ways to split this up are welcome (particularly now, before the ABI is sealed ;)

Quoted 4 lines

This gets much more interesting if the two sides
are on remote ends of an I/O link, e.g. using a nontransparent PCI bridge, where you only want to send stores over the wire, but never fetches or even read-modify-write cycles.

/me head explodes ;)

Quoted 4 lines

Your code is probably optimal if you only communicate between host and guest code on the same CPU, but not so good if it crosses NUMA nodes or worse.

Yeah, I wont lie and say it wasn't designed primarily for the former case in mind (since it was my particular itch). I would certainly appreciate any insight on ways to make it more generally applicable for things like the transparent bridge model, and/or NUMA, though.

Quoted 9 lines

include/linux/shm_signal.h line 53

Quoted 6 lines
include/linux/shm_signal.h new file +5 -0
+struct shm_signal_desc {
+       __u32                 magic;
+       __u32                 ver;
+       struct shm_signal_irq irq[2];
+};

This data structure has implicit padding of two bytes at the end. How about adding another '__u16 reserved' to make it explicit?

Good idea. Will fix.

Quoted 16 lines
Quoted 16 lines
lib/shm_signal.c new file +15 -0
+	/*
+	 * We always mark the remote side as dirty regardless of whether
+	 * they need to be notified.
+	 */
+	irq->dirty = 1;
+	wmb();   /* dirty must be visible before we test the pending state */
+
+	if (irq->enabled && !irq->pending) {
+		rmb();
+
+		/*
+		 * If the remote side has enabled notifications, and we do
+		 * not see a notification pending, we must inject a new one.
+		 */
+		irq->pending = 1;
Quoted 8 lines

lib/shm_signal.c line 98

Quoted 4 lines
lib/shm_signal.c new file +4 -0
+		wmb(); /* make it visible before we do the injection */
+
+		s->ops->inject(s);
+	}

Barriers always confuse me, but the rmb() looks slightly wrong. AFAIU it only prevents reads after the barrier from being done before the barrier, but you don't do any reads after it.

Its probably overzealous barrier'ing on my part. I had a conversation with Paul McKenney (CC'd) where I was wondering if a conditional was an implicit barrier. His response was something to the effect of "on most arches, yes, but not all". And we concluded that, to be conservative, there should be a rmb() after the if().

That said, tbh I am not sure if its actually needed. Paul?

Quoted 10 lines

The (irq->enabled && !irq->pending) check could be done before the irq->dirty = 1 arrives at the bus, but that does not seem to hurt, it would at most cause a duplicate ->inject().

Regarding the scope of the barrier, did you intentionally use the global versions (rmb()/wmb()) and not the lighter single-system (smp_rmb()/smp_wmb()) versions? Your version should cope with remote links over PCI but looks otherwise optimized for local use, as I wrote above.

Yes, it was intentional. Both for the remote case, as you point out. Also for the case where local might be mismatched (for instance, a guest compiled as UP).

Thanks Arnd,
-Greg

#4 lore raw

Re: [PATCH 1/7] shm-signal: shared-memory signals

Quoted 31 lines · Gregory Haskins

Hi Arnd,

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 9:56 AM, in message <[email protected]>, Arnd

Quoted 11 lines · Bergmann
Quoted 8 lines · Gregory Haskins

shm-signal provides a generic shared-memory based bidirectional signaling mechanism. It is used in conjunction with an existing signal transport (such as posix-signals, interrupts, pipes, etc) to increase the efficiency of the transport since the state information is directly accessible to both sides of the link. The shared-memory design provides very cheap access to features such as event-masking and spurious delivery mititgation, and is useful implementing higher level shared-memory constructs such as rings.

Looks like a very useful feature in general.

Thanks, I was hoping that would be the case.

Quoted 10 lines

include/linux/shm_signal.h line 42

Quoted 6 lines
include/linux/shm_signal.h new file +5 -0
+struct shm_signal_irq {
+       __u8                  enabled;
+       __u8                  pending;
+       __u8                  dirty;
+};

Won't this layout cause cache line ping pong? Other schemes I have seen try to separate the bits so that each cache line is written to by only one side.

It could possibly use some optimization in that regard. I generally consider myself an expert at concurrent programming, but this lockless stuff is, um, hard ;) I was going for correctness first.

Quoted 9 lines

Long story short, any suggestions on ways to split this up are welcome (particularly now, before the ABI is sealed ;)

Quoted 4 lines

This gets much more interesting if the two sides
are on remote ends of an I/O link, e.g. using a nontransparent PCI bridge, where you only want to send stores over the wire, but never fetches or even read-modify-write cycles.

/me head explodes ;)

I've actually implemented this idea for virtio. Read the virtio-over-PCI patches I posted, and you'll see that the entire virtqueue implementation NEVER uses reads across the PCI bus, only writes. The slowpath configuration space uses reads, but the virtqueues themselves are write-only.

Some trivial benchmarking against an earlier driver that did writes+reads across the PCI bus showed that the write-only driver was about 2x as fast. (Throughput increased from ~30MB/sec to ~65MB/sec).

I'm sure the write-only design was not the only change responsible for the speedup, but it was definitely a contributing factor.

Ira

#5 lore raw

PATCH 2/7 ioq: Add basic definitions for a shared-memory, lockless queue

In reply to Gregory Haskins

IOQ allows asynchronous communication between two end-points via a common shared-memory region. Memory is synchronized using pure barriers (i.e.
lockless), and updates are communicated via an embedded shm-signal. The
design of the interface allows one code base to universally provide both sides of a given channel.

We will use this mechanism later in the series to efficiently move data in and out of a guest kernel from various sources, including both infrastructure level and application level transports.

---

 include/linux/Kbuild |    1 
 include/linux/ioq.h  |  415 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig          |   12 +
 lib/Makefile         |    1 
 lib/ioq.c            |  294 +++++++++++++++++++++++++++++++++++
 5 files changed, 723 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/ioq.h
 create mode 100644 lib/ioq.c
include/linux/Kbuild +1 -0
index 01d67b6..32b3eb8 100644
@@ -247,6 +247,7 @@ unifdef-y += in.h
 unifdef-y += in6.h
 unifdef-y += inotify.h
 unifdef-y += input.h
+unifdef-y += ioq.h
 unifdef-y += ip.h
 unifdef-y += ipc.h
 unifdef-y += ipmi.h
include/linux/ioq.h new file +415 -0

415 lines not on this page · raw message

lib/Kconfig +12 -0
index 136da19..255778d 100644
@@ -209,4 +209,16 @@ config SHM_SIGNAL
 
 	 If unsure, say N
 
+config IOQ
+	tristate "IO-Queue library - Generic shared-memory queue"
+	select SHM_SIGNAL
+	default n
+	help
+	 IOQ is a generic shared-memory-queue mechanism that happens to be
+	 friendly to virtualization boundaries. It can be used in a variety
+	 of ways, though its intended purpose is to become a low-level
+	 communication path for paravirtualized drivers.
+
+	 If unsure, say N
+
 endmenu
lib/Makefile +1 -0
index 503bf7b..215f0c9 100644
@@ -77,6 +77,7 @@ obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
 obj-$(CONFIG_SMP) += percpu_counter.o
 obj-$(CONFIG_AUDIT_GENERIC) += audit.o
 obj-$(CONFIG_SHM_SIGNAL) += shm_signal.o
+obj-$(CONFIG_IOQ) += ioq.o
 
 obj-$(CONFIG_SWIOTLB) += swiotlb.o
 obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o
lib/ioq.c new file +294 -0

294 lines not on this page · raw message

#6 lore raw

PATCH 3/7 vbus: add a "vbus-proxy" bus model for vbus_driver objects

In reply to Gregory Haskins

This will generally be used for hypervisors to publish any host-side virtual devices up to a guest. The guest will have the opportunity to consume any devices present on the vbus-proxy as if they were platform devices, similar to existing buses like PCI.

---

 arch/x86/Kconfig            |    2 +
 drivers/Makefile            |    1 
 drivers/vbus/Kconfig        |   14 ++++
 drivers/vbus/Makefile       |    3 +
 drivers/vbus/bus-proxy.c    |  152 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/vbus_driver.h |   73 +++++++++++++++++++++
 6 files changed, 245 insertions(+), 0 deletions(-)
 create mode 100644 drivers/vbus/Kconfig
 create mode 100644 drivers/vbus/Makefile
 create mode 100644 drivers/vbus/bus-proxy.c
 create mode 100644 include/linux/vbus_driver.h
arch/x86/Kconfig +2 -0
index 738bdc6..72ff902 100644
@@ -2037,6 +2037,8 @@ source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
 
+source "drivers/vbus/Kconfig"
+
 endmenu
 
 
drivers/Makefile +1 -0
index bc4205d..d5bedb1 100644
@@ -110,3 +110,4 @@ obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
 obj-y				+= ieee802154/
+obj-y				+= vbus/
drivers/vbus/Kconfig new file +14 -0
new file mode 100644
index 0000000..e1939f5
@@ -0,0 +1,14 @@
+#
+# Virtual-Bus (VBus) driver configuration
+#
+
+config VBUS_PROXY
+       tristate "Virtual-Bus support"
+       select SHM_SIGNAL
+       default n
+       help
+       Adds support for a virtual-bus model drivers in a guest to connect
+	to host side virtual-bus resources.  If you are using this kernel
+	in a virtualization solution which implements virtual-bus devices
+	on the backend, say Y.  If unsure, say N.
+
drivers/vbus/Makefile new file +3 -0
new file mode 100644
index 0000000..a29a1e0
@@ -0,0 +1,3 @@
+
+vbus-proxy-objs += bus-proxy.o
+obj-$(CONFIG_VBUS_PROXY) += vbus-proxy.o
drivers/vbus/bus-proxy.c new file +152 -0

152 lines not on this page · raw message

include/linux/vbus_driver.h new file +73 -0

73 lines not on this page · raw message

#7 lore raw

PATCH 4/7 vbus-proxy: add a pci-to-vbus bridge

In reply to Gregory Haskins

This patch adds a pci-based driver to interface between the a host VBUS and the guest's vbus-proxy bus model.

---

 drivers/vbus/Kconfig      |   10 +
 drivers/vbus/Makefile     |    3 
 drivers/vbus/pci-bridge.c |  824 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild      |    1 
 include/linux/vbus_pci.h  |  127 +++++++
 5 files changed, 965 insertions(+), 0 deletions(-)
 create mode 100644 drivers/vbus/pci-bridge.c
 create mode 100644 include/linux/vbus_pci.h
drivers/vbus/Kconfig +10 -0
index e1939f5..87c545d 100644
@@ -12,3 +12,13 @@ config VBUS_PROXY
 	in a virtualization solution which implements virtual-bus devices
 	on the backend, say Y.  If unsure, say N.
 
+config VBUS_PCIBRIDGE
+       tristate "PCI to Virtual-Bus bridge"
+       depends on PCI
+       depends on VBUS_PROXY
+       select IOQ
+       default n
+       help
+        Provides a way to bridge host side vbus devices via a PCI-BRIDGE
+        object.  If you are running virtualization with vbus devices on the
+	host, and the vbus is exposed via PCI, say Y.  Otherwise, say N.
drivers/vbus/Makefile +3 -0
index a29a1e0..944b7f1 100644
@@ -1,3 +1,6 @@
 
 vbus-proxy-objs += bus-proxy.o
 obj-$(CONFIG_VBUS_PROXY) += vbus-proxy.o
+
+vbus-pcibridge-objs += pci-bridge.o
+obj-$(CONFIG_VBUS_PCIBRIDGE) += vbus-pcibridge.o
drivers/vbus/pci-bridge.c new file +824 -0

824 lines not on this page · raw message

include/linux/Kbuild +1 -0
index 32b3eb8..fa15bbf 100644
@@ -358,6 +358,7 @@ unifdef-y += uio.h
 unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
+unifdef-y += vbus_pci.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
include/linux/vbus_pci.h new file +127 -0

127 lines not on this page · raw message

#8 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 4 lines · Gregory Haskins

This patch adds a pci-based driver to interface between the a host VBUS and the guest's vbus-proxy bus model.

This seems to be duplicating parts of virtio-pci that could be kept common by extending the virtio code. Layering on top of virtio would also make it possible to use the same features you add on top of other transports (e.g. the s390 virtio code) without adding yet another backend for each of them.

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+static int
+vbus_pci_hypercall(unsigned long nr, void *data, unsigned long len)
+{
+	struct vbus_pci_hypercall params = {
+		.vector = nr,
+		.len    = len,
+		.datap  = __pa(data),
+	};
+	unsigned long flags;
+	int ret;

drivers/vbus/pci-bridge.c line 83

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+
+	spin_lock_irqsave(&vbus_pci.lock, flags);
+
+	memcpy_toio(&vbus_pci.regs->hypercall.data, &params, sizeof(params));
+	ret = ioread32(&vbus_pci.regs->hypercall.result);
+
+	spin_unlock_irqrestore(&vbus_pci.lock, flags);
+
+	return ret;
+}

The functionality looks reasonable but please don't call this a hypercall. A hypercall would be hypervisor specific by definition while this one is device specific if I understand it correctly. How about "command queue", "mailbox", "message queue", "devcall" or something else that we have in existing PCI devices?

Quoted 13 lines
drivers/vbus/pci-bridge.c new file +13 -0
+
+static int
+vbus_pci_device_open(struct vbus_device_proxy *vdev, int version, int flags)
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct vbus_pci_deviceopen params;
+	int ret;
+
+	if (dev->handle)
+		return -EINVAL;
+
+	params.devid   = vdev->id;
+	params.version = version;

drivers/vbus/pci-bridge.c line 171

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+
+	ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVOPEN,
+				 &params, sizeof(params));
+	if (ret < 0)
+		return ret;
+
+	dev->handle = params.handle;
+
+	return 0;
+}

This seems to add an artificial abstraction that does not make sense if you stick to the PCI abstraction. The two sensible and common models for virtual devices that I've seen are:

* The hypervisor knows what virtual resources exist and provides them to the guest. The guest owns them as soon as they show up in the bus (e.g. PCI) probe. The 'handle' is preexisting.

* The guest starts without any devices and asks for resources it wants to access. There is no probing of resources but the guest issues a hypercall to get a handle to a newly created virtual device (or -ENODEV).

What is your reasoning for requiring both a probe and an allocation?

Quoted 71 lines
drivers/vbus/pci-bridge.c new file +71 -0
+static int
+vbus_pci_device_shm(struct vbus_device_proxy *vdev, int id, int prio,
+		    void *ptr, size_t len,
+		    struct shm_signal_desc *sdesc, struct shm_signal **signal,
+		    int flags)
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct _signal *_signal = NULL;
+	struct vbus_pci_deviceshm params;
+	unsigned long iflags;
+	int ret;
+
+	if (!dev->handle)
+		return -EINVAL;
+
+	params.devh   = dev->handle;
+	params.id     = id;
+	params.flags  = flags;
+	params.datap  = (u64)__pa(ptr);
+	params.len    = len;
+
+	if (signal) {
+		/*
+		 * The signal descriptor must be embedded within the
+		 * provided ptr
+		 */
+		if (!sdesc
+		    || (len < sizeof(*sdesc))
+		    || ((void *)sdesc < ptr)
+		    || ((void *)sdesc > (ptr + len - sizeof(*sdesc))))
+			return -EINVAL;
+
+		_signal = kzalloc(sizeof(*_signal), GFP_KERNEL);
+		if (!_signal)
+			return -ENOMEM;
+
+		_signal_init(&_signal->signal, sdesc, &_signal_ops);
+
+		/*
+		 * take another reference for the host.  This is dropped
+		 * by a SHMCLOSE event
+		 */
+		shm_signal_get(&_signal->signal);
+
+		params.signal.offset = (u64)sdesc - (u64)ptr;
+		params.signal.prio   = prio;
+		params.signal.cookie = (u64)_signal;
+
+	} else
+		params.signal.offset = -1; /* yes, this is a u32, but its ok */
+
+	ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVSHM,
+				 &params, sizeof(params));
+	if (ret < 0) {
+		if (_signal) {
+			/*
+			 * We held two references above, so we need to drop
+			 * both of them
+			 */
+			shm_signal_put(&_signal->signal);
+			shm_signal_put(&_signal->signal);
+		}
+
+		return ret;
+	}
+
+	if (signal) {
+		_signal->handle = ret;
+
+		spin_lock_irqsave(&vbus_pci.lock, iflags);
+

drivers/vbus/pci-bridge.c line 296

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+		list_add_tail(&_signal->list, &dev->shms);
+
+		spin_unlock_irqrestore(&vbus_pci.lock, iflags);
+
+		shm_signal_get(&_signal->signal);
+		*signal = &_signal->signal;
+	}
+
+	return 0;
+}

This could be implemented by virtio devices as well, right?

Quoted 8 lines
drivers/vbus/pci-bridge.c new file +8 -0
+static int
+vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
+		     size_t len, int flags)
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct vbus_pci_devicecall params = {
+		.devh  = dev->handle,
+		.func  = func,

drivers/vbus/pci-bridge.c line 315

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+		.datap = (u64)__pa(data),
+		.len   = len,
+		.flags = flags,
+	};
+
+	if (!dev->handle)
+		return -EINVAL;
+
+	return vbus_pci_hypercall(VBUS_PCI_HC_DEVCALL, &params, sizeof(params));
+}

Why the indirection? It seems to me that you could do the simpler

static int
vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
size_t len, int flags)

{
	struct vbus_pci_device *dev = to_dev(vdev);
	struct vbus_pci_hypercall params = {
		.vector = func,
		.len    = len,
		.datap  = __pa(data),
	};
	spin_lock_irqsave(&dev.lock, flags);
	memcpy_toio(&dev.regs->hypercall.data, &params, sizeof(params));
	ret = ioread32(&dev.regs->hypercall.result);
	spin_unlock_irqrestore(&dev.lock, flags);

	return ret;
}

This gets rid of your 'handle' and the unwinding through an extra pointer indirection. You just need to make sure that the device specific call numbers don't conflict with any global ones.

Quoted 52 lines
drivers/vbus/pci-bridge.c new file +49 -0
+
+static struct ioq_notifier eventq_notifier;
 
...
 
+/* Invoked whenever the hypervisor ioq_signal()s our eventq */
+static void
+eventq_wakeup(struct ioq_notifier *notifier)
+{
+	struct ioq_iterator iter;
+	int ret;
+
+	/* We want to iterate on the head of the in-use index */
+	ret = ioq_iter_init(&vbus_pci.eventq, &iter, ioq_idxtype_inuse, 0);
+	BUG_ON(ret < 0);
+
+	ret = ioq_iter_seek(&iter, ioq_seek_head, 0, 0);
+	BUG_ON(ret < 0);
+
+	/*
+	 * The EOM is indicated by finding a packet that is still owned by
+	 * the south side.
+	 *
+	 * FIXME: This in theory could run indefinitely if the host keeps
+	 * feeding us events since there is nothing like a NAPI budget.  We
+	 * might need to address that
+	 */
+	while (!iter.desc->sown) {
+		struct ioq_ring_desc *desc  = iter.desc;
+		struct vbus_pci_event *event;
+
+		event = (struct vbus_pci_event *)desc->cookie;
+
+		switch (event->eventid) {
+		case VBUS_PCI_EVENT_DEVADD:
+			event_devadd(&event->data.add);
+			break;
+		case VBUS_PCI_EVENT_DEVDROP:
+			event_devdrop(&event->data.handle);
+			break;
+		case VBUS_PCI_EVENT_SHMSIGNAL:
+			event_shmsignal(&event->data.handle);
+			break;
+		case VBUS_PCI_EVENT_SHMCLOSE:
+			event_shmclose(&event->data.handle);
+			break;
+		default:
+			printk(KERN_WARNING "VBUS_PCI: Unexpected event %d\n",
+			       event->eventid);
+			break;
+		};
+

drivers/vbus/pci-bridge.c line 550

Quoted 10 lines
drivers/vbus/pci-bridge.c new file +10 -0
+		memset(event, 0, sizeof(*event));
+
+		/* Advance the in-use head */
+		ret = ioq_iter_pop(&iter, 0);
+		BUG_ON(ret < 0);
+	}
+
+	/* And let the south side know that we changed the queue */
+	ioq_signal(&vbus_pci.eventq, 0);
+}

Ah, so you have a global event queue and your own device hotplug mechanism. But why would you then still use PCI to back it? We already have PCI hotplug to add and remove devices and you have defined per device notifier queues that you can use for waking up the device, right?

	Arnd <><
#9 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 10:42 AM, in message <[email protected]>, Arnd

Quoted 11 lines · Bergmann
Quoted 4 lines · Gregory Haskins

This patch adds a pci-based driver to interface between the a host VBUS and the guest's vbus-proxy bus model.

This seems to be duplicating parts of virtio-pci that could be kept common by extending the virtio code. Layering on top of virtio would also make it possible to use the same features you add on top of other transports (e.g. the s390 virtio code) without adding yet another backend for each of them.

This doesn't make sense to me, but I suspect we are both looking at what this code does differently. I am under the impression that you may believe that there is one of these objects per vbus device. Note that this is just a bridge to vbus, so there is only one of these per system with potentially many vbus devices behind it.

In essence, this driver's job is to populate the "vbus-proxy" LDM bus with objects that it finds across the PCI-OTHER bridge. This would actually sit below the virtio components in the stack, so it doesnt make sense (to me) to turn around and build this on top of virtio. But perhaps I am missing something you are seeing.

Can you elaborate?

Quoted 15 lines
Quoted 15 lines
drivers/vbus/pci-bridge.c new file +14 -0
+static int
+vbus_pci_hypercall(unsigned long nr, void *data, unsigned long len)
+{
+	struct vbus_pci_hypercall params = {
+		.vector = nr,
+		.len    = len,
+		.datap  = __pa(data),
+	};
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&vbus_pci.lock, flags);
+
+	memcpy_toio(&vbus_pci.regs->hypercall.data, &params, sizeof(params));
Quoted 8 lines

drivers/vbus/pci-bridge.c line 83

Quoted 6 lines
drivers/vbus/pci-bridge.c new file +6 -0
+	ret = ioread32(&vbus_pci.regs->hypercall.result);
+
+	spin_unlock_irqrestore(&vbus_pci.lock, flags);
+
+	return ret;
+}

The functionality looks reasonable but please don't call this a hypercall.

Heh, I guess its just semantics. The reason why its called hypercall is two fold:

1) In previous versions (vbus-v3 and earlier), it actually *was* literally a KVM-hypercall.
2) In this current version, it is purely a PCI device doing PIO, but it still acts exactly like a hypercall on the backend (via the ioeventfd mechanism in KVM).

That said, I am not married to the name, so I can come up with something more appropriate/descriptive.

Quoted 24 lines

A hypercall would be hypervisor specific by definition while this one is device specific if I understand it correctly. How about "command queue", "mailbox", "message queue", "devcall" or something else that we have in existing PCI devices?

drivers/vbus/pci-bridge.c

Quoted 3 lines
drivers/vbus/pci-bridge.c new file +3 -0
+
+static int
+vbus_pci_device_open(struct vbus_device_proxy *vdev, int version, int 

flags)

Quoted 15 lines
drivers/vbus/pci-bridge.c new file +15 -0
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct vbus_pci_deviceopen params;
+	int ret;
+
+	if (dev->handle)
+		return -EINVAL;
+
+	params.devid   = vdev->id;
+	params.version = version;
+
+	ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVOPEN,
+				 &params, sizeof(params));
+	if (ret < 0)
+		return ret;
Quoted 8 lines

drivers/vbus/pci-bridge.c line 171

Quoted 5 lines
drivers/vbus/pci-bridge.c new file +5 -0
+
+	dev->handle = params.handle;
+
+	return 0;
+}

This seems to add an artificial abstraction that does not make sense if you stick to the PCI abstraction.

I think there may be confusion about what is going on here. The "device-open" pertains to a vbus device *beyond* the bridge, not the PCI device (the bridge) itself. Nor is the vbus device a PCI device.

Whats happening here is somewhat analogous to a PCI config-cycle. Its a way to open a channel to a device beyond the bridge in _response_ to a probe.

We have a way to enumerate devices present beyond the bridge (this yields a "device-id") but in order to actually talk to the device, you must first call DEVOPEN(id). When a device-id is enumerated, it generates a probe() event on vbus-proxy. The responding driver in question would then turn around and issue the handle = dev->open(VERSION) to see if it is compatible with the device, and to establish a context for further communication.

The reason why DEVOPEN returns a unique handle is to help ensure that the driver has established proper context before allowing other calls.

Quoted 7 lines

The two sensible and common models
for virtual devices that I've seen are:

* The hypervisor knows what virtual resources exist and provides them to the guest. The guest owns them as soon as they show up in the bus (e.g. PCI) probe. The 'handle' is preexisting.

Quoted 6 lines

* The guest starts without any devices and asks for resources it wants to access. There is no probing of resources but the guest issues a hypercall to get a handle to a newly created virtual device (or -ENODEV).

What is your reasoning for requiring both a probe and an allocation?

Answered above, I thnk

Quoted 76 lines
Quoted 76 lines
drivers/vbus/pci-bridge.c new file +75 -0
+static int
+vbus_pci_device_shm(struct vbus_device_proxy *vdev, int id, int prio,
+		    void *ptr, size_t len,
+		    struct shm_signal_desc *sdesc, struct shm_signal **signal,
+		    int flags)
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct _signal *_signal = NULL;
+	struct vbus_pci_deviceshm params;
+	unsigned long iflags;
+	int ret;
+
+	if (!dev->handle)
+		return -EINVAL;
+
+	params.devh   = dev->handle;
+	params.id     = id;
+	params.flags  = flags;
+	params.datap  = (u64)__pa(ptr);
+	params.len    = len;
+
+	if (signal) {
+		/*
+		 * The signal descriptor must be embedded within the
+		 * provided ptr
+		 */
+		if (!sdesc
+		    || (len < sizeof(*sdesc))
+		    || ((void *)sdesc < ptr)
+		    || ((void *)sdesc > (ptr + len - sizeof(*sdesc))))
+			return -EINVAL;
+
+		_signal = kzalloc(sizeof(*_signal), GFP_KERNEL);
+		if (!_signal)
+			return -ENOMEM;
+
+		_signal_init(&_signal->signal, sdesc, &_signal_ops);
+
+		/*
+		 * take another reference for the host.  This is dropped
+		 * by a SHMCLOSE event
+		 */
+		shm_signal_get(&_signal->signal);
+
+		params.signal.offset = (u64)sdesc - (u64)ptr;
+		params.signal.prio   = prio;
+		params.signal.cookie = (u64)_signal;
+
+	} else
+		params.signal.offset = -1; /* yes, this is a u32, but its ok */
+
+	ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVSHM,
+				 &params, sizeof(params));
+	if (ret < 0) {
+		if (_signal) {
+			/*
+			 * We held two references above, so we need to drop
+			 * both of them
+			 */
+			shm_signal_put(&_signal->signal);
+			shm_signal_put(&_signal->signal);
+		}
+
+		return ret;
+	}
+
+	if (signal) {
+		_signal->handle = ret;
+
+		spin_lock_irqsave(&vbus_pci.lock, iflags);
+
+		list_add_tail(&_signal->list, &dev->shms);
+
+		spin_unlock_irqrestore(&vbus_pci.lock, iflags);
+
Quoted 8 lines

drivers/vbus/pci-bridge.c line 296

Quoted 6 lines
drivers/vbus/pci-bridge.c new file +6 -0
+		shm_signal_get(&_signal->signal);
+		*signal = &_signal->signal;
+	}
+
+	return 0;
+}

This could be implemented by virtio devices as well, right?

The big difference with dev->shm() is that it is not bound to a particular ABI within the shared-memory (as opposed to virtio, which assumes a virtio ABI). This just creates an empty shared-memory region (with a bidirectional signaling path) which you can overlay a variety of structures (virtio included). You can of course also use non-ring based structures, such as, say, an array of idempotent state.

The point is that, once this is done, you have a shared-memory region and a way (via the shm-signal) to bidirectionally signal changes to that memory region. You can then build bigger things with it, like virtqueues.

Quoted 13 lines
Quoted 13 lines
drivers/vbus/pci-bridge.c new file +12 -0
+static int
+vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
+		     size_t len, int flags)
+{
+	struct vbus_pci_device *dev = to_dev(vdev);
+	struct vbus_pci_devicecall params = {
+		.devh  = dev->handle,
+		.func  = func,
+		.datap = (u64)__pa(data),
+		.len   = len,
+		.flags = flags,
+	};
Quoted 8 lines

drivers/vbus/pci-bridge.c line 315

Quoted 6 lines
drivers/vbus/pci-bridge.c new file +6 -0
+
+	if (!dev->handle)
+		return -EINVAL;
+
+	return vbus_pci_hypercall(VBUS_PCI_HC_DEVCALL, &params, sizeof(params));
+}

Why the indirection? It seems to me that you could do the simpler

What indirection?

/me looks below and thinks he sees the confusion..

Quoted 19 lines

static int
vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
size_t len, int flags)

{
	struct vbus_pci_device *dev = to_dev(vdev);
	struct vbus_pci_hypercall params = {
		.vector = func,
		.len    = len,
		.datap  = __pa(data),
	};
	spin_lock_irqsave(&dev.lock, flags);
	memcpy_toio(&dev.regs->hypercall.data, &params, sizeof(params));
	ret = ioread32(&dev.regs->hypercall.result);
	spin_unlock_irqrestore(&dev.lock, flags);

	return ret;
}
Quoted 4 lines

This gets rid of your 'handle' and the unwinding through an extra pointer indirection. You just need to make sure that the device specific call numbers
don't conflict with any global ones.

Ah, now I see the confusion...

DEVCALL is sending a synchronous call to a specific device beyond the bridge. The MMIO going on here against dev.regs->hypercall.data is sending a synchronous call to the bridge itself. They are distinctly different ;)

Quoted 58 lines
Quoted 58 lines
drivers/vbus/pci-bridge.c new file +54 -0
+
+static struct ioq_notifier eventq_notifier;
 
...
 
+/* Invoked whenever the hypervisor ioq_signal()s our eventq */
+static void
+eventq_wakeup(struct ioq_notifier *notifier)
+{
+	struct ioq_iterator iter;
+	int ret;
+
+	/* We want to iterate on the head of the in-use index */
+	ret = ioq_iter_init(&vbus_pci.eventq, &iter, ioq_idxtype_inuse, 0);
+	BUG_ON(ret < 0);
+
+	ret = ioq_iter_seek(&iter, ioq_seek_head, 0, 0);
+	BUG_ON(ret < 0);
+
+	/*
+	 * The EOM is indicated by finding a packet that is still owned by
+	 * the south side.
+	 *
+	 * FIXME: This in theory could run indefinitely if the host keeps
+	 * feeding us events since there is nothing like a NAPI budget.  We
+	 * might need to address that
+	 */
+	while (!iter.desc->sown) {
+		struct ioq_ring_desc *desc  = iter.desc;
+		struct vbus_pci_event *event;
+
+		event = (struct vbus_pci_event *)desc->cookie;
+
+		switch (event->eventid) {
+		case VBUS_PCI_EVENT_DEVADD:
+			event_devadd(&event->data.add);
+			break;
+		case VBUS_PCI_EVENT_DEVDROP:
+			event_devdrop(&event->data.handle);
+			break;
+		case VBUS_PCI_EVENT_SHMSIGNAL:
+			event_shmsignal(&event->data.handle);
+			break;
+		case VBUS_PCI_EVENT_SHMCLOSE:
+			event_shmclose(&event->data.handle);
+			break;
+		default:
+			printk(KERN_WARNING "VBUS_PCI: Unexpected event %d\n",
+			       event->eventid);
+			break;
+		};
+
+		memset(event, 0, sizeof(*event));
+
+		/* Advance the in-use head */
+		ret = ioq_iter_pop(&iter, 0);
+		BUG_ON(ret < 0);
Quoted 8 lines

drivers/vbus/pci-bridge.c line 550

Quoted 5 lines
drivers/vbus/pci-bridge.c new file +5 -0
+	}
+
+	/* And let the south side know that we changed the queue */
+	ioq_signal(&vbus_pci.eventq, 0);
+}

Ah, so you have a global event queue and your own device hotplug mechanism. But why would you then still use PCI to back it?

PCI is only used as a PCI-to-vbus bridge. Beyond that, the bridge is populating the vbus devices it sees beyond the bridge into the vbus-proxy LDM bus.

That said, the event queue is sending me events such as "device added" and "shm-signal", which are then reflected up into the general model.

Quoted 1 line

We already have PCI hotplug to add and remove devices

Yep, and I do actually use that...to get a probe for the bridge itself ;)

Quoted 1 line

and you have defined per device notifier queues that you can use for waking up the device, right?

Only per bridge. vbus drivers themselves allocate additional dynamic shm-signal channels that are tunneled through the bridge's eventq(s).

Kind Regards,
-Greg

#10 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 14 lines · you
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 10:42 AM, in message <[email protected]>, Arnd

Quoted 11 lines · Bergmann
Quoted 4 lines · Gregory Haskins

This patch adds a pci-based driver to interface between the a host VBUS and the guest's vbus-proxy bus model.

This seems to be duplicating parts of virtio-pci that could be kept common by extending the virtio code. Layering on top of virtio would also make it possible to use the same features you add on top of other transports (e.g. the s390 virtio code) without adding yet another backend for each of them.

Quoted 5 lines

This doesn't make sense to me, but I suspect we are both looking at what this code does differently. I am under the impression that you may believe that there is one of these objects per vbus device. Note that this is just a bridge to vbus, so there is only one of these per system with potentially many vbus devices behind it.

Right, this did not become clear from the posting. For virtio, we discussed a model like this in the beginning and then rejected it in favour of a "one PCI device per virtio device" model, which I now think is a better approach than your pci-to-vbus bridge.

Quoted 7 lines

In essence, this driver's job is to populate the "vbus-proxy" LDM bus with objects that it finds across the PCI-OTHER bridge. This would actually sit below the virtio components in the stack, so it doesnt make sense (to me) to turn around and build this on top of virtio. But perhaps I am missing something you are seeing.

Can you elaborate?

Your PCI device does not serve any real purpose as far as I can tell, you could just as well have a root device as a parent for all the vbus devices if you do your device probing like this.

However, assuming that you do the IMHO right thing to do probing like virtio with a PCI device for each slave, the code will be almost the same as virtio-pci and the two can be the same.

Quoted 18 lines
Quoted 2 lines

This seems to add an artificial abstraction that does not make sense if you stick to the PCI abstraction.

I think there may be confusion about what is going on here. The "device-open" pertains to a vbus device *beyond* the bridge, not the PCI device (the bridge) itself. Nor is the vbus device a PCI device.

Whats happening here is somewhat analogous to a PCI config-cycle. Its a way to open a channel to a device beyond the bridge in _response_ to a probe.

We have a way to enumerate devices present beyond the bridge (this yields a "device-id") but in order to actually talk to the device, you must first call DEVOPEN(id). When a device-id is enumerated, it generates a probe() event on vbus-proxy. The responding driver in question would then turn around and issue the handle = dev->open(VERSION) to see if it is compatible with the device, and to establish a context for further communication.

Quoted 2 lines

The reason why DEVOPEN returns a unique handle is to help ensure that the driver has established proper context before allowing other calls.

So assuming this kind of bus is the right idea (which I think it's not), why can't the host assume they are open to start with and you go and enumerate the devices on the bridge, creating a vbus_device for each one as you go. Then you just need to match the vbus drivers with the devices by some string or vendor/device ID tuple.

Quoted 11 lines
Quoted 2 lines

This could be implemented by virtio devices as well, right?

The big difference with dev->shm() is that it is not bound to a particular ABI within the shared-memory (as opposed to virtio, which assumes a virtio ABI). This just creates a n empty shared-memory region (with a bidirectional signaling path) which you can overlay a variety of structures (virtio included). You can of course also use non-ring based structures, such as, say, an array of idempotent state.

Quoted 4 lines

The point is that, once this is done, you have a shared-memory region and a way (via the shm-signal) to bidirectionally signal changes to that memory region. You can then build bigger things with it, like virtqueues.

Let me try to rephrase my point: I believe you can implement the shm/ioq data transport on top of the virtio bus level, by adding shm and signal functions to struct virtio_config_ops alongside find_vqs() so that a virtio_device can have either any combination of virtqueues, shm and ioq.

Quoted 18 lines
Quoted 18 lines

static int
vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
size_t len, int flags)

{
	struct vbus_pci_device *dev = to_dev(vdev);
	struct vbus_pci_hypercall params = {
		.vector = func,
		.len    = len,
		.datap  = __pa(data),
	};
	spin_lock_irqsave(&dev.lock, flags);
	memcpy_toio(&dev.regs->hypercall.data, &params, sizeof(params));
	ret = ioread32(&dev.regs->hypercall.result);
	spin_unlock_irqrestore(&dev.lock, flags);

	return ret;
}
Quoted 8 lines
Quoted 4 lines

This gets rid of your 'handle' and the unwinding through an extra pointer indirection. You just need to make sure that the device specific call numbers
don't conflict with any global ones.

Ah, now I see the confusion...

DEVCALL is sending a synchronous call to a specific device beyond the bridge. The MMIO going on here against dev.regs->hypercall.data is sending a synchronous call to the bridge itself. They are distinctly different ;)

well, my point earlier was that they probably should not be different ;-)

	Arnd <><
#11 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 1:03 PM, in message <[email protected]>, Arnd

Quoted 19 lines · Bergmann
Quoted 8 lines · you
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 10:42 AM, in message <[email protected]>, Arnd

Quoted 6 lines · Bergmann
Quoted 4 lines · Gregory Haskins

This patch adds a pci-based driver to interface between the a host VBUS and the guest's vbus-proxy bus model.

Quoted 7 lines
Quoted 5 lines

This seems to be duplicating parts of virtio-pci that could be kept common by extending the virtio code. Layering on top of virtio would also make it possible to use the same features you add on top of other transports (e.g. the s390 virtio code) without adding yet another backend for each of them.

This doesn't make sense to me, but I suspect we are both looking at what

this

Quoted 2 lines

code does differently. I am under the impression that you may believe that there is one of these objects per vbus device. Note that this is just a

Quoted 8 lines

bridge

Quoted 2 lines

to vbus, so there is only one of these per system with potentially many vbus devices behind it.

Right, this did not become clear from the posting. For virtio, we discussed a model like this in the beginning and then rejected it in favour of a "one PCI device per virtio device" model, which I now think is a better approach than your pci-to-vbus bridge.

I agree that the 1:1 model may have made sense for QEMU based virtio. I think you will find it has diminished value here, however.

Here are some of my arguments against it:

1) there is an ample PCI model that is easy to work with when you are in QEMU and using its device model (and you get it for free). Its the path of least resistance. For something in kernel, it is more awkward to try to coordinate the in-kernel state with the PCI state. Afaict, you either need to have it live partially in both places, or you need some PCI emulation in the kernel.

2) The signal model for the 1:1 design is not very flexible IMO.
2a) I want to be able to allocate dynamic signal paths, not pre-allocate msi-x vectors at dev-add.
2b) I also want to collapse multiple interrupts together so as to minimize the context switch rate (inject + EIO overhead). My design effectively has "NAPI" for interrupt handling. This helps when the system needs it the most: heavy IO.

3) The 1:1 model is not buying us much in terms of hotplug. We don't really "use" PCI very much even in virtio. Its a thin-shim of uniform dev-ids to resurface to the virtio-bus as something else. With LDM, hotplug is ridiculously easy anyway, so who cares. I already need an event channel anyway for (2b) anyway, so the devadd/devdrop events are trivial to handle.

4) communicating with something efficiently in-kernel requires more finesse than basic PIO/MMIO. There are tricks you can do to get around this, but with 1:1 you would have to do this trick repeatedly for each device. Even with a library solution to help, you still have per-cpu .data overhead and cpu hotplug overhead to get maximum performance. With my "bridge" model, I do it once, which I believe is ideal.

5) 1:1 is going to quickly populate the available MMIO/PIO and IDT slots for any kind of medium to large configuration. The bridge model scales better in this regard.

So based on that, I think the bridge model works better for vbus. Perhaps you can convince me otherwise ;)

Quoted 10 lines
Quoted 8 lines

In essence, this driver's job is to populate the "vbus-proxy" LDM bus with objects that it finds across the PCI-OTHER bridge. This would actually sit below the virtio components in the stack, so it doesnt make sense (to me) to turn around and build this on top of virtio. But perhaps I am missing something you are seeing.

Can you elaborate?

Your PCI device does not serve any real purpose as far as I can tell

That is certainly debatable. Its purpose is as follows:

1) Allows a guest to discover the vbus feature (fwiw: I used to do this with cpuid)
2) Allows the guest to establish proper context to communicate with the feature (mmio, pio, and msi) (fwiw: i used to use hypercalls)
3) Access the virtual-devices that have been configured for the feature

Correct me if I am wrong: Isn't this more of less the exact intent of something like an LDM bus (vbus-proxy) and a PCI-BRIDGE? Other than the possibility that there might be some mergable overlap (still debatable), I don't think its fair to say that this does not serve a purpose.

Quoted 2 lines

, you could just as well have a root device as a parent for all the vbus devices if you do your device probing like this.

Yes, I suppose the "bridge" could have been advertised as a virtio-based root device. In this way, the virtio probe() would replace my pci probe() for feature discovery, and a virtqueue could replace my msi+ioq for the eventq channel.

I see a few issues with that, however:

1) The virtqueue library, while a perfectly nice ring design at the metadata level, does not have an API that is friendly to kernel-to-kernel communication. It was designed more for frontend use to some remote backend. The IOQ library on the other hand, was specifically designed to support use as kernel-to-kernel (see north/south designations). So this made life easier for me. To do what you propose, the eventq channel would need to terminate in kernel, and I would thus be forced to deal that the potential API problems.

2) I would need to have Avi et. al. allocate a virtio vector to use from their namespace, which I am sure they wont be willing to do until they accept my design. Today, I have a nice conflict free PCI ID to use as I see fit.

Im sure both of these hurdles are not insurmountable, but I am left scratching my head as to why its worth the effort. It seems to me its a "six of one, half-dozen of the other" kind of scenario. Either I write a qemu PCI device and pci-bridge driver, or I write a qemu virtio-devicve and virtio root driver.

In short: What does this buy us, or did you mean something else?

Quoted 4 lines

However, assuming that you do the IMHO right thing to do probing like virtio with a PCI device for each slave, the code will be almost the same as virtio-pci and the two can be the same.

Can you elaborate?

Quoted 21 lines
Quoted 5 lines
Quoted 3 lines

This seems to add an artificial abstraction that does not make sense if you stick to the PCI abstraction.

I think there may be confusion about what is going on here. The

"device-open"

Quoted 1 line

pertains to a vbus device *beyond* the bridge, not the PCI device (the

bridge)

Quoted 13 lines

itself. Nor is the vbus device a PCI device.

Whats happening here is somewhat analogous to a PCI config-cycle. Its a way to open a channel to a device beyond the bridge in _response_ to a probe.

We have a way to enumerate devices present beyond the bridge (this yields a "device-id") but in order to actually talk to the device, you must first call DEVOPEN(id). When a device-id is enumerated, it generates a probe() event on vbus-proxy. The responding driver in question would then turn around and issue the handle = dev->open(VERSION) to see if it is compatible with the device, and to establish a context for further communication.

Quoted 5 lines
Quoted 2 lines

The reason why DEVOPEN returns a unique handle is to help ensure that the driver has established proper context before allowing other calls.

So assuming this kind of bus is the right idea (which I think it's not), why can't the host assume they are open to start with

Read on..

Quoted 2 lines

and you go and enumerate the devices on the bridge, creating a vbus_device for each one as you go.

Thats exactly what it does.

Quoted 3 lines

Then you just need to match the vbus drivers with the devices by some string or vendor/device ID tuple.

Yep, thats right too. Then, when the driver gets a ->probe(), it does an dev->open() to check various state:

a) can the device be opened? if it has an max-open policy (most will have a max-open = 1 policy) and something else already has the device open, it will fail (this will not be common).
b) is the driver ABI revision compatible with the device ABI revision? This is like checking the pci config-space revision number.

For an example, see drivers/net/vbus-enet.c, line 764:

http://git.kernel.org/?p=linux/kernel/git/ghaskins/alacrityvm/linux-2.6.git;a=blob;f=drivers/net/vbus-enet.c;h=7220f43723adc5b0bece1bc37974fae1b034cd9e;hb=b3b2339efbd4e754b1c85f8bc8f85f21a1a1f509#l764

Its simple a check to see if the driver and device are compatible, and therefore the probe should succeed. Nothing more. I think what I have done is similar to how most buses (like PCI) work today (ala revision number checks with a config-cycle).

Regarding the id->handle indirection:

Internally, the DEVOPEN call translates an "id" to a "handle". The handle is just a token to help ensure that the caller actually opened the device successfully. Note that the "id" namespace is 0 based. Therefore, something like an errant DEVCALL(0) would be indistinguishable from a legit request. Using the handle abstraction gives me a slightly more robust mechanism to ensure the caller actually meant to call the host, and was in the proper context to do so. For one thing, if the device had never been opened, this would have failed before it ever reached the model. Its one more check I can do at the infrastructure level, and one less thing each model has to look out for.

Is the id->handle translation critical? No, i'm sure we could live without it, but I also don't think it hurts anything. It allows the overall code to be slightly more robust, and the individual model code to be slightly less complicated. Therefore, I don't see a problem.

Quoted 16 lines
Quoted 11 lines
Quoted 2 lines

This could be implemented by virtio devices as well, right?

The big difference with dev->shm() is that it is not bound to a particular ABI within the shared-memory (as opposed to virtio, which assumes a virtio ABI). This just creates a n empty shared-memory region (with a bidirectional signaling path) which you can overlay a variety of structures (virtio included). You can of course also use non-ring based structures, such as, say, an array of idempotent state.

Quoted 4 lines

The point is that, once this is done, you have a shared-memory region and a way (via the shm-signal) to bidirectionally signal changes to that memory region. You can then build bigger things with it, like virtqueues.

Quoted 5 lines

Let me try to rephrase my point: I believe you can implement the shm/ioq data transport on top of the virtio bus level, by adding shm and signal functions to struct virtio_config_ops alongside find_vqs() so that a virtio_device can have either any combination of virtqueues, shm and ioq.

Yes, I believe this might be doable, but I don't know virtio well enough to say for sure.

Quoted 24 lines
Quoted 24 lines
Quoted 23 lines

static int
vbus_pci_device_call(struct vbus_device_proxy *vdev, u32 func, void *data,
size_t len, int flags)

{
	struct vbus_pci_device *dev = to_dev(vdev);
	struct vbus_pci_hypercall params = {
		.vector = func,
		.len    = len,
		.datap  = __pa(data),
	};
	spin_lock_irqsave(&dev.lock, flags);
	memcpy_toio(&dev.regs->hypercall.data, &params, sizeof(params));
	ret = ioread32(&dev.regs->hypercall.result);
	spin_unlock_irqrestore(&dev.lock, flags);

	return ret;
}

This gets rid of your 'handle' and the unwinding through an extra pointer indirection. You just need to make sure that the device specific call numbers
don't conflict with any global ones.

Quoted 7 lines
Quoted 3 lines

Ah, now I see the confusion...

DEVCALL is sending a synchronous call to a specific device beyond the

bridge. The MMIO going on here against dev.regs->hypercall.data is sending a synchronous call to the bridge itself. They are distinctly different ;)

well, my point earlier was that they probably should not be different ;-)

Ok :)

I still do not see how they could be merged in a way that is both a) worth the effort, and b) doesn't compromise my design. But I will keep an open mind if you want to continue the conversation.

Thanks for all the feedback. I do appreciate it.

Kind Regards,
-Greg

#12 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 4 lines · Gregory Haskins
Quoted 1 line
Quoted 1 line
Quoted 1 line · Arnd Bergmann

Here are some of my arguments against it:

1) there is an ample PCI model that is easy to work with when you are in QEMU and using its device model (and you get it for free). Its the path of least resistance. For something in kernel, it is more awkward to try to coordinate the in-kernel state with the PCI state. Afaict, you either need to have it live partially in both places, or you need some PCI emulation in the kernel.

True, if the whole hypervisor is in the host kernel, then doing full PCI emulation would be insane. I was assuming that all of the setup code still lived in host user space. What is the reason why it cannot? Do you want to use something other than qemu, do you think this will impact performance, or something else?

Quoted 2 lines

2) The signal model for the 1:1 design is not very flexible IMO.
2a) I want to be able to allocate dynamic signal paths, not pre-allocate msi-x vectors at dev-add.

I believe msi-x implies that the interrupt vectors get added by the device driver at run time, unlike legacy interrupts or msi. It's been a while since I dealt with that though.

Quoted 1 line

2b) I also want to collapse multiple interrupts together so as to minimize the context switch rate (inject + EIO overhead). My design effectively has "NAPI" for interrupt handling. This helps when the system needs it the most: heavy IO.

That sounds like a very useful concept in general, but this seems to be a detail of the interrupt controller implementation. If the IO-APIC cannot do what you want here, maybe we just need a paravirtual IRQ controller driver, like e.g. the PS3 has.

Quoted 1 line

3) The 1:1 model is not buying us much in terms of hotplug. We don't really "use" PCI very much even in virtio. Its a thin-shim of uniform dev-ids to resurface to the virtio-bus as something else. With LDM, hotplug is ridiculously easy anyway, so who cares. I already need an event channel anyway for (2b) anyway, so the devadd/devdrop events are trivial to handle.

I agree for Linux guests, but when you want to run other guest operating systems, PCI hotplug is probably the most common interface for this. AFAIK, the windows virtio-net driver does not at all have a concept of a virtio layer but is simply a network driver for a PCI card. The same could be applied any other device, possibly with some library code doing all the queue handling in a common way.l

Quoted 3 lines

4) communicating with something efficiently in-kernel requires more finesse than basic PIO/MMIO. There are tricks you can do to get around this, but with 1:1 you would have to do this trick repeatedly for each device. Even with a library solution to help, you still have per-cpu .data overhead and cpu hotplug overhead to get maximum performance. With my "bridge" model, I do it once, which I believe is ideal.

5) 1:1 is going to quickly populate the available MMIO/PIO and IDT slots for any kind of medium to large configuration. The bridge model scales better in this regard.

We don't need to rely on PIO, it's just the common interface that all hypervisors can easily support. We could have different underlying methods for the communication if space or performance becomes a bottleneck because of this.

Quoted 1 line

So based on that, I think the bridge model works better for vbus. Perhaps you can convince me otherwise ;)

Being able to define all of it in the host kernel seems to be the major advantage of your approach, the other points you mentioned are less important IMHO. The question is whether that is indeed a worthy goal, or if it should just live in user space as with the qemu PCI code.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

In essence, this driver's job is to populate the "vbus-proxy" LDM bus with objects that it finds across the PCI-OTHER bridge. This would actually sit below the virtio components in the stack, so it doesnt make sense (to me) to turn around and build this on top of virtio. But perhaps I am missing something you are seeing.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Can you elaborate?

Your PCI device does not serve any real purpose as far as I can tell

That is certainly debatable. Its purpose is as follows:

1) Allows a guest to discover the vbus feature (fwiw: I used to do this with cpuid)

true, I missed that.

Quoted 4 lines

2) Allows the guest to establish proper context to communicate with the feature (mmio, pio, and msi) (fwiw: i used to use hypercalls)
3) Access the virtual-devices that have been configured for the feature

Correct me if I am wrong: Isn't this more of less the exact intent of something like an LDM bus (vbus-proxy) and a PCI-BRIDGE? Other than the possibility that there might be some mergable overlap (still debatable), I don't think its fair to say that this does not serve a purpose.

I guess you are right on that. An interesting variation of that would be make the child devices of it virtio devices again though: Instead of the PCI emulation code in the host kernel, you could define a simpler interface to the same effect. So the root device would be a virtio-pci device, below which you can have virtio-virtio devices.

Quoted 8 lines
Quoted 2 lines

, you could just as well have a root device as a parent for all the vbus devices if you do your device probing like this.

Yes, I suppose the "bridge" could have been advertised as a virtio-based root device. In this way, the virtio probe() would replace my pci probe() for feature discovery, and a virtqueue could replace my msi+ioq for the eventq channel.

I see a few issues with that, however:

1) The virtqueue library, while a perfectly nice ring design at the metadata level, does not have an API that is friendly to kernel-to-kernel communication. It was designed more for frontend use to some remote backend. The IOQ library on the other hand, was specifically designed to support use as kernel-to-kernel (see north/south designations). So this made life easier for me. To do what you propose, the eventq channel would need to terminate in kernel, and I would thus be forced to deal that the potential API problems.

Well, virtqueues are not that bad for kernel-to-kernel communication, as Ira mentioned referring to his virtio-over-PCI driver. You can have virtqueues on both sides, having the host kernel create a pair of virtqueues (one in user aka guest space, one in the host kernel), with the host virtqueue_ops doing copy_{to,from}_user to move data between them.

If you have that, you can actually use the same virtio_net driver in both guest and host kernel, just communicating over different virtio implementations. Interestingly, that would mean that you no longer need a separation between guest and host device drivers (vbus and vbus-proxy in your case) but could use the same device abstraction with just different transports to back the shm-signal or virtqueue.

Quoted 1 line

2) I would need to have Avi et. al. allocate a virtio vector to use from their namespace, which I am sure they wont be willing to do until they accept my design. Today, I have a nice conflict free PCI ID to use as I see fit.

My impression is the opposite: as long as you try to reinvent everything at once, you face opposition, but if you just improve parts of the existing design one by one (like eventfd), I think you will find lots of support.

Quoted 3 lines

Im sure both of these hurdles are not insurmountable, but I am left scratching my head as to why its worth the effort. It seems to me its a "six of one, half-dozen of the other" kind of scenario. Either I write a qemu PCI device and pci-bridge driver, or I write a qemu virtio-devicve and virtio root driver.

In short: What does this buy us, or did you mean something else?

In my last reply, I was thinking of a root device that can not be probed like a PCI device.

Quoted 5 lines
Quoted 3 lines

However, assuming that you do the IMHO right thing to do probing like virtio with a PCI device for each slave, the code will be almost the same as virtio-pci and the two can be the same.

Can you elaborate?

Well, let me revise based on the discussion:

The main point that remains is that I think a vbus-proxy should be the same as a virtio device. This could be done by having (as in my earlier mails) a PCI device per vbus-proxy, with devcall implemented in PIO or config-space and additional shm/shm-signal, or it could be a single virtio device from virtio-pci or one of the other existing provides that connects you with a new virtio provider sitting in the host kernel. This provider has child devices for any endpoint (virtio-net, venet, ...) that is implemented in the host kernel.

Quoted 11 lines
Quoted 2 lines

and you go and enumerate the devices on the bridge, creating a vbus_device for each one as you go.

Thats exactly what it does.

Quoted 3 lines

Then you just need to match the vbus drivers with the devices by some string or vendor/device ID tuple.

Yep, thats right too. Then, when the driver gets a ->probe(), it does an dev->open() to check various state:

Quoted 8 lines

a) can the device be opened? if it has an max-open policy (most will have a max-open = 1 policy) and something else already has the device open, it will fail (this will not be common).
b) is the driver ABI revision compatible with the device ABI revision? This is like checking the pci config-space revision number.

For an example, see drivers/net/vbus-enet.c, line 764:

http://git.kernel.org/?p=linux/kernel/git/ghaskins/alacrityvm/linux-2.6.git;a=blob;f=drivers/net/vbus-enet.c;h=7220f43723adc5b0bece1bc37974fae1b034cd9e;hb=b3b2339efbd4e754b1c85f8bc8f85f21a1a1f509#l764

Its simple a check to see if the driver and device are compatible, and therefore the probe should succeed. Nothing more. I think what I have done is similar to how most buses (like PCI) work today (ala revision number checks with a config-cycle).

ok.

Quoted 5 lines

Regarding the id->handle indirection:

Internally, the DEVOPEN call translates an "id" to a "handle". The handle is just a token to help ensure that the caller actually opened the device successfully. Note that the "id" namespace is 0 based. Therefore, something like an errant DEVCALL(0) would be indistinguishable from a legit request. Using the handle abstraction gives me a slightly more robust mechanism to ensure the caller actually meant to call the host, and was in the proper context to do so. For one thing, if the device had never been opened, this would have failed before it ever reached the model. Its one more check I can do at the infrastructure level, and one less thing each model has to look out for.

Is the id->handle translation critical? No, i'm sure we could live without it, but I also don't think it hurts anything. It allows the overall code to be slightly more robust, and the individual model code to be slightly less complicated. Therefore, I don't see a problem.

Right, assuming your model with all vbus devices behind a single PCI device, your handle does not hurt, it's the equivalent of a bus/dev/fn number or an MMIO address.

	Arnd <><
#13 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 6:57 PM, in message <[email protected]>, Arnd

Quoted 12 lines · Bergmann
Quoted 1 line · Gregory Haskins
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 1:03 PM, in message <[email protected]>, Arnd

Quoted 3 lines · Bergmann

Here are some of my arguments against it:

1) there is an ample PCI model that is easy to work with when you are in

QEMU and using its device model (and you get it for free). Its the path of least resistance. For something in kernel, it is more awkward to try to coordinate the in-kernel state with the PCI state. Afaict, you either need to have it live partially in both places, or you need some PCI emulation in the kernel.

Quoted 3 lines

True, if the whole hypervisor is in the host kernel, then doing full PCI emulation would be
insane.

In this case, the entire bus is more or less self contained and in-kernel. We technically *do* still have qemu present, however, so you are right there.

Quoted 2 lines

I was assuming that all of the setup code still lived in host user space.

Very little. Just enough to register the PCI device, handle the MMIO/PIO/MSI configuration, etc. All the bus management uses the standard vbus management interface (configfs/sysfs)

Quoted 1 line

What is the reason why it cannot?

Its not that it "can't" per se.. Its just awkward to have it live in two places, and I would need to coordinate in-kernel changes to userspace, etc. Today I do not need to do this: i.e. the model in userspace is very simple.

Quoted 1 line

Do you want to use something other than qemu,

Well, only in the sense that vbus has its own management interface and bus model, and I want them to be used.

Quoted 1 line

do you think this will impact performance, or something else?

performance is not a concern for this aspect of operation.

Quoted 10 lines
Quoted 3 lines

2) The signal model for the 1:1 design is not very flexible IMO. 2a) I want to be able to allocate dynamic signal paths, not pre-allocate

msi-x vectors at dev-add.

I believe msi-x implies that the interrupt vectors get added by the device driver
at run time, unlike legacy interrupts or msi. It's been a while since I dealt with
that though.

Yeah, its been a while for me too. I would have to look at the spec again.

My understanding was that its just a slight variation of msi, with some of the constraints revised (no <= 32 vector limit, etc). Perhaps it is fancier than that and 2a is unfounded. TBD.

Quoted 10 lines
Quoted 2 lines

2b) I also want to collapse multiple interrupts together so as to

minimize the context switch rate (inject + EIO overhead). My design effectively has "NAPI" for interrupt handling. This helps when the system needs it the most: heavy IO.

That sounds like a very useful concept in general, but this seems to be a detail of the interrupt controller implementation. If the IO-APIC cannot do what you want here, maybe we just need a paravirtual IRQ controller driver, like e.g. the PS3 has.

Yeah, I agree this could be a function of the APIC code. Do note that I mentioned this in passing to Avi a few months ago but FWIW he indicated at that time that he is not interested in making the APIC PV.

Also, I almost forgot an important one. Add:

2c) Interrupt prioritization. I want to be able to assign priority to interrupts and handle them in priority order.

Quoted 7 lines
Quoted 2 lines

3) The 1:1 model is not buying us much in terms of hotplug. We don't really

"use" PCI very much even in virtio. Its a thin-shim of uniform dev-ids to resurface to the virtio-bus as something else. With LDM, hotplug is ridiculously easy anyway, so who cares. I already need an event channel anyway for (2b) anyway, so the devadd/devdrop events are trivial to handle.

Quoted 9 lines

I agree for Linux guests, but when you want to run other guest operating systems,
PCI hotplug is probably the most common interface for this. AFAIK, the windows
virtio-net driver does not at all have a concept of a virtio layer but is simply
a network driver for a PCI card. The same could be applied any other device, possibly with some library code doing all the queue handling in a common way.l

I was told it also has a layering like Linux, but I haven't actually seen the code myself, so I do not know if this is true.

Quoted 9 lines
Quoted 2 lines

4) communicating with something efficiently in-kernel requires more finesse

than basic PIO/MMIO. There are tricks you can do to get around this, but with 1:1 you would have to do this trick repeatedly for each device. Even with a library solution to help, you still have per-cpu .data overhead and cpu hotplug overhead to get maximum performance. With my "bridge" model, I do it once, which I believe is ideal.

Quoted 2 lines

5) 1:1 is going to quickly populate the available MMIO/PIO and IDT slots for

Quoted 8 lines

any kind of medium to large configuration. The bridge model scales better in this regard.

We don't need to rely on PIO, it's just the common interface that all hypervisors
can easily support. We could have different underlying methods for the communication
if space or performance becomes a bottleneck because of this.

Heh...I already proposed an alternative, which incidentally was shot down:

http://lkml.org/lkml/2009/5/5/132

(in the end, I think we agreed that a technique of tunneling PIO/MMIO over hypercaills would be better than introducing a new namespace. But we also decided that the difference between PIO and PIOoHC was too small to care, and we don't care about non-x86)

But in any case, my comment still stands: 1:1 puts load on the PIO emulation (even if you use PIOoHC). I am not sure this can be easily worked around.

Quoted 8 lines
Quoted 2 lines

So based on that, I think the bridge model works better for vbus. Perhaps

you can convince me otherwise ;)

Being able to define all of it in the host kernel seems to be the major advantage of your approach, the other points you mentioned are less important IMHO. The question is whether that is indeed a worthy goal, or if it should just live in user space as with the qemu PCI code.

I don't think we can gloss over these so easily. They are all important to me, particularly 2b and 2c.

Quoted 28 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

In essence, this driver's job is to populate the "vbus-proxy" LDM bus with objects that it finds across the PCI-OTHER bridge. This would actually sit below the virtio components in the stack, so it doesnt make sense (to me)

to

Quoted 10 lines
Quoted 6 lines
Quoted 4 lines

turn around and build this on top of virtio. But perhaps I am missing something you are seeing.

Can you elaborate?

Your PCI device does not serve any real purpose as far as I can tell

That is certainly debatable. Its purpose is as follows:

1) Allows a guest to discover the vbus feature (fwiw: I used to do this with

cpuid)

true, I missed that.

Quoted 1 line

2) Allows the guest to establish proper context to communicate with the

feature (mmio, pio, and msi) (fwiw: i used to use hypercalls)

Quoted 3 lines

3) Access the virtual-devices that have been configured for the feature

Correct me if I am wrong: Isn't this more of less the exact intent of

something like an LDM bus (vbus-proxy) and a PCI-BRIDGE? Other than the possibility that there might be some mergable overlap (still debatable), I don't think its fair to say that this does not serve a purpose.

Quoted 9 lines

I guess you are right on that. An interesting variation of that would be make the
child devices of it virtio devices again though: Instead of the PCI emulation code
in the host kernel, you could define a simpler interface to the same effect. So the
root device would be a virtio-pci device, below which you can have virtio-virtio
devices.

Interesting....but note I think that is effectively what I do today (with virtio-vbus) except you wouldn't have the explicit vbus-proxy model underneath. Also, if 1:1 via PCI is important for windows, that solution would have the same problem that the virtio-vbus model does.

Quoted 21 lines
Quoted 2 lines
Quoted 2 lines

, you could just as well have a root device as a parent for all the vbus

devices

Quoted 3 lines
Quoted 1 line

if you do your device probing like this.

Yes, I suppose the "bridge" could have been advertised as a virtio-based root

device. In this way, the virtio probe() would replace my pci probe() for feature discovery, and a virtqueue could replace my msi+ioq for the eventq channel.

Quoted 4 lines

I see a few issues with that, however:

1) The virtqueue library, while a perfectly nice ring design at the metadata

level, does not have an API that is friendly to kernel-to-kernel communication.
It was designed more for frontend use to some remote backend. The IOQ
library on the other hand, was specifically designed to support use as kernel-to-kernel (see north/south designations). So this made life easier for me. To do what you propose, the eventq channel would need to terminate in kernel, and I would thus be forced to deal that the potential API problems.

Quoted 8 lines

Well, virtqueues are not that bad for kernel-to-kernel communication, as Ira mentioned
referring to his virtio-over-PCI driver. You can have virtqueues on both sides, having
the host kernel create a pair of virtqueues (one in user aka guest space, one in the host
kernel), with the host virtqueue_ops doing copy_{to,from}_user to move data between them.

Its been a while since I looked, so perhaps I am wrong here. I will look again.

Quoted 10 lines

If you have that, you can actually use the same virtio_net driver in both guest and
host kernel, just communicating over different virtio implementations. Interestingly,
that would mean that you no longer need a separation between guest and host device
drivers (vbus and vbus-proxy in your case) but could use the same device abstraction
with just different transports to back the shm-signal or virtqueue.

Actually, I think there are some problems with that model (such as management of the interface). virtio-net really wants to connect to a virtio-net-backend (such as the one in qemu or vbus). It wasn't designed to connect back to back like that. I think you will quickly run into problems similar to what Ira faced with virtio-over-PCI with that model.

Quoted 17 lines
Quoted 2 lines

2) I would need to have Avi et. al. allocate a virtio vector to use from

their namespace, which I am sure they wont be willing to do until they accept my design. Today, I have a nice conflict free PCI ID to use as I see fit.

My impression is the opposite: as long as you try to reinvent everything at once,
you face opposition, but if you just improve parts of the existing design one
by one (like eventfd), I think you will find lots of support.

Quoted 1 line

Im sure both of these hurdles are not insurmountable, but I am left

scratching my head as to why its worth the effort. It seems to me its a "six of one, half-dozen of the other" kind of scenario. Either I write a qemu PCI device and pci-bridge driver, or I write a qemu virtio-devicve and virtio root driver.

Quoted 1 line
Quoted 4 lines
Quoted 1 line

In short: What does this buy us, or did you mean something else?

In my last reply, I was thinking of a root device that can not be probed like a PCI device.

IIUC, because you missed the "feature discovery" function of the bridge, you thought this was possible but now see it is problematic? Or are you saying that this concept is still valid and should be considered? I think its the former, but wanted to be sure we were on the same page.

Quoted 7 lines
Quoted 6 lines
Quoted 4 lines

However, assuming that you do the IMHO right thing to do probing like virtio with a PCI device for each slave, the code will be almost the same as virtio-pci and the two can be the same.

Can you elaborate?

Quoted 8 lines

Well, let me revise based on the discussion:

The main point that remains is that I think a vbus-proxy should be the same as a
virtio device. This could be done by having (as in my earlier mails) a PCI device
per vbus-proxy, with devcall implemented in PIO or config-space and additional shm/shm-signal,

So the problem with this model is the points I made earlier (such as 2b, 2c).

I do agree with you that the *lack* of this model may be problematic for Windows, depending on the answer w.r.t. what the windows drivers look like.

Quoted 4 lines

or it could be a single virtio device from virtio-pci or one
of the other existing provides that connects you with a new virtio provider sitting in the host kernel. This provider has child devices for any endpoint (virtio-net, venet, ...) that is implemented in the host kernel.

This is an interesting idea, but I think it also has problems.

What we do get with having the explicit vbus-proxy exposed in the stack (aside from being able to support "vbus native" drivers, like venet) is a neat way to map vbus-isms into virtio-isms. For instance, vbus uses a string-based device id, and virtio uses a PCI-ID. Using this as an intermediate layer allows the "virtio" vbus-id to know that we issue dev->call(GETID) to obtain the PCI-ID value of this virtio-device, and we should publish this result to virtio-bus.

Without this intermediate layer, the vbus identity scheme would have to be compatible with virtio PCI-ID based scheme, and I think this is suboptimal for the overall design of vbus.

[snip]

Quoted 15 lines
Quoted 4 lines

Regarding the id->handle indirection:

Internally, the DEVOPEN call translates an "id" to a "handle". The handle

is just a token to help ensure that the caller actually opened the device successfully. Note that the "id" namespace is 0 based. Therefore, something like an errant DEVCALL(0) would be indistinguishable from a legit request. Using the handle abstraction gives me a slightly more robust mechanism to ensure the caller actually meant to call the host, and was in the proper context to do so. For one thing, if the device had never been opened, this would have failed before it ever reached the model. Its one more check I can do at the infrastructure level, and one less thing each model has to look out for.

Quoted 2 lines

Is the id->handle translation critical? No, i'm sure we could live without

Quoted 8 lines

it, but I also don't think it hurts anything. It allows the overall code to be slightly more robust, and the individual model code to be slightly less complicated. Therefore, I don't see a problem.

Right, assuming your model with all vbus devices behind a single PCI device, your
handle does not hurt, it's the equivalent of a bus/dev/fn number or an MMIO address.

Agreed

Thanks Arnd,
-Greg

#14 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 13 lines · Gregory Haskins
Quoted 8 lines
Quoted 1 line
Quoted 1 line

Arnd Bergmann <[email protected]> wrote:

Quoted 4 lines · Gregory Haskins

2b) I also want to collapse multiple interrupts together so as to
minimize the context switch rate (inject + EIO overhead). My design effectively has "NAPI" for interrupt handling. This helps when the system needs it the most: heavy IO.

Quoted 4 lines

That sounds like a very useful concept in general, but this seems to be a detail of the interrupt controller implementation. If the IO-APIC cannot do what you want here, maybe we just need a paravirtual IRQ controller driver, like e.g. the PS3 has.

Quoted 8 lines

Yeah, I agree this could be a function of the APIC code. Do note that I mentioned this in passing to Avi a few months ago but FWIW he indicated at that time that he is not interested in making the APIC PV.

Also, I almost forgot an important one. Add:

2c) Interrupt prioritization. I want to be able to assign priority to interrupts and handle them in priority order.

I think this part of the interface has developed into the wrong direction because you confused two questions:

1. should you build an advanced interrupt mechanism for virtual drivers?
2. how should you build an advanced interrupt mechanism for virtual drivers?

My guess is that when Avi said he did not want a paravirtual IO-APIC, he implied that the existing one is good enough (maybe Avi can clarify that point himself) answering question 1, while you took that as an indication that the code should live elsewhere instead, answering question 2.

What you built with the shm-signal code is essentially a paravirtual nested interrupt controller by another name, and deeply integrated into a new bigger subsystem. I believe that this has significant disadvantages over the approach of making it a standard interrupt controller driver:

* It completely avoids the infrastructure that we have built into Linux to deal with interrupts, e.g. /proc/interrupts statistics, IRQ balancing and CPU affinity.

* It makes it impossible to quantify the value of the feature to start with, which could be used to answer question 1 above.

* Less importantly, it does not work with any other drivers that might also benefit from a new interrupt controller -- if it is indeed better than the one we already have.

	Arnd <><
#15 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/7/2009 at 10:57 AM, in message <[email protected]>, Arnd

Quoted 44 lines · Bergmann
Quoted 14 lines · Gregory Haskins
Quoted 7 lines
Quoted 1 line
Quoted 1 line

Arnd Bergmann <[email protected]> wrote:

Quoted 3 lines · Gregory Haskins

2b) I also want to collapse multiple interrupts together so as to
minimize the context switch rate (inject + EIO overhead). My design effectively has "NAPI" for interrupt handling. This helps when the system

Quoted 6 lines
Quoted 1 line

needs it the most: heavy IO.

That sounds like a very useful concept in general, but this seems to be a detail of the interrupt controller implementation. If the IO-APIC cannot do what you want here, maybe we just need a paravirtual IRQ controller driver, like e.g. the PS3 has.

Quoted 8 lines

Yeah, I agree this could be a function of the APIC code. Do note that I mentioned this in passing to Avi a few months ago but FWIW he indicated at that time that he is not interested in making the APIC PV.

Also, I almost forgot an important one. Add:

2c) Interrupt prioritization. I want to be able to assign priority to interrupts and handle them in priority order.

I think this part of the interface has developed into the wrong direction because you confused two questions:

1. should you build an advanced interrupt mechanism for virtual drivers?
2. how should you build an advanced interrupt mechanism for virtual drivers?

My guess is that when Avi said he did not want a paravirtual IO-APIC, he implied that the existing one is good enough (maybe Avi can clarify that point himself) answering question 1, while you took that as an indication that the code should live elsewhere instead, answering question 2.

What you built with the shm-signal code is essentially a paravirtual nested interrupt controller by another name, and deeply integrated into a new bigger subsystem. I believe that this has significant disadvantages over the approach of making it a standard interrupt controller driver:

* It completely avoids the infrastructure that we have built into Linux to deal with interrupts, e.g. /proc/interrupts statistics, IRQ balancing and CPU affinity.

Quoted 8 lines

* It makes it impossible to quantify the value of the feature to start with, which could be used to answer question 1 above.

* Less importantly, it does not work with any other drivers that might also benefit from a new interrupt controller -- if it is indeed better than the one we already have.

	Arnd <><

Hi Arnd,

I don't strongly disagree with anything you said (except for perhaps that I confused the question). I agree that the PCI-bridge effectively implements something akin to an interrupt controller. I agree that this interrupt controller, if indeed superior (I believe it is), can only benefit devices inherently behind the bridge instead of all of KVM (this in of itself doesnt bother me, as I plan on all my performance work to be based on that bus, but I digress. Also note that this is not dissimilar to other bridge+bus (think usb, scsi) operation). I agree that a potentially more ideal solution would be if we had a proper generic PV interrupt controller that exhibited similar traits as to what I describe (priority, inject+EIO overhead reduction, etc) so that all of KVM benefited.

The issue wasn't that I didn't know these things. The issue is that I have no control over whether such an intrusive change to KVM (and the guest arch code) is accepted (and at least one relevant maintainer expressed dissatisfaction (*) at the idea when proposed) Conversely, I am the maintainer of AlacrityVM, so I do have control over the bridge design. ;) Also note that this particular design decision is completely encapsulated within alacrityvm's components. IOW, I am not foisting my ideas on the entire kernel tree: If someone doesn't like what I have done, they can choose not to use alacrity and its like my ideas never existed. The important thing with this distinction is I am not changing how core linux or core kvm works in the process, only the one little piece of the world that
particularly interests me.

That said, if attitudes about some of these ideas have changed, I may be able to break that piece out and start submitting it to kvm@ as some kind of pv interrupt controller. I would only be interested in doing so if Avi et. al. express an openness to the idea...I.e.. I don't want to waste my time any more than any one elses.

Kind Regards,
-Greg

(*) I think Avi said something to the effect of "you are falling into the 'lets PV the world' trap"

#16 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

In reply to Gregory Haskins
Quoted 2 lines · Gregory Haskins
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 6:57 PM, in message <[email protected]>, Arnd

Bergmann <[email protected]> wrote:

[ big snip ]

Quoted 33 lines
Quoted 11 lines
Quoted 3 lines

I see a few issues with that, however:

1) The virtqueue library, while a perfectly nice ring design at the metadata

level, does not have an API that is friendly to kernel-to-kernel communication.
It was designed more for frontend use to some remote backend. The IOQ
library on the other hand, was specifically designed to support use as kernel-to-kernel (see north/south designations). So this made life easier for me. To do what you propose, the eventq channel would need to terminate in kernel, and I would thus be forced to deal that the potential API problems.

Quoted 8 lines

Well, virtqueues are not that bad for kernel-to-kernel communication, as Ira mentioned
referring to his virtio-over-PCI driver. You can have virtqueues on both sides, having
the host kernel create a pair of virtqueues (one in user aka guest space, one in the host
kernel), with the host virtqueue_ops doing copy_{to,from}_user to move data between them.

Its been a while since I looked, so perhaps I am wrong here. I will look again.

Quoted 10 lines

If you have that, you can actually use the same virtio_net driver in both guest and
host kernel, just communicating over different virtio implementations. Interestingly,
that would mean that you no longer need a separation between guest and host device
drivers (vbus and vbus-proxy in your case) but could use the same device abstraction
with just different transports to back the shm-signal or virtqueue.

Quoted 2 lines

Actually, I think there are some problems with that model (such as management of the interface). virtio-net really wants to connect to a virtio-net-backend (such as the one in qemu or vbus). It wasn't designed to connect back to back like that. I think you will quickly run into problems similar to what Ira faced with virtio-over-PCI with that model.

Getting the virtio-net devices talking to each other over PCI was not terribly difficult. However, the capabilities negotiation works in a VERY awkward way. The capabilities negotiation was really designed with a virtio-net-backend in mind. Unless I'm missing something obvious, it is essentially broken for the case where two virtio-net's are talking to each other.

For example, imagine the situation where you'd like the guest to get a specific MAC address, but you do not care what MAC address the host recieves.

Normally, you'd set struct virtio_net_config's mac[] field, and set the VIRTIO_NET_F_MAC feature. However, when you have two virtio-net's communicating directly, this doesn't work.

Let me explain with a quick diagram. The results described are the values RETURNED from virtio_config_ops->get() and virtio_config_ops->get_features() when called by the system in question.

Guest System
1) struct virtio_net_config->mac[]: 00:11:22:33:44:55
2) features: VIRTIO_NET_F_MAC

Host System
1) struct virtio_net_config->mac[]: unset
2) features: VIRTIO_NET_F_MAC unset

In this case, the feature negotiation code will not accept the VIRTIO_NET_F_MAC feature, and both systems will generate random mac addresses. Not the behavior we want at all.

I "fixed" the problem by ALWAYS setting a random MAC address, and ALWAYS setting the VIRTIO_NET_F_MAC feature. By doing this, both sides always negotiate the VIRTIO_NET_F_MAC feature.

In conclusion, the feature negotiation works fine for driver features, such as VIRTIO_NET_MRG_RXBUF or VIRTIO_NET_F_GSO, but completely breaks down for user-controlled features, like VIRTIO_NET_F_MAC.

I think the vbus configfs interface works great for this situation, because it has an obvious and seperate backend. It is obvious where the configuration information is coming from.

With my powerpc hardware, it should be easily possible to have at least 6 devices, each with two virtqueues, one for tx and one for rx. (The limit is caused by the amount of distinct kick() events I can generate.) This could allow many combinations of devices, such as:

* 1 virtio-net, 1 virtio-console
* 3 virtio-net, 2 virtio-console
* 6 virtio-net
* etc.

In all honesty, I don't really care so much about the management interface for my purposes. A static configuration of devices works for me. However, I doubt that would ever be accepted into the upstream kernel, which is what I'm really concerned about. I hate seeing drivers live out-of-tree.

Getting two virtio-net's talking to each other had one other major
problem: the fields in struct virtio_net_hdr are not defined with a constant endianness. When connecting two virtio-net's running on different machines, they may have different endianness, as in my case between a big-endian powerpc guest and a little-endian x86 host. I'm not confident that qemu-system-ppc, running on x86, using virtio for the network interface, even works at all. (I have not tested it.)

Sorry that this got somewhat long winded and went a little off topic. Ira

#17 lore raw

Re: [PATCH 4/7] vbus-proxy: add a pci-to-vbus bridge

Ira W. Snyder wrote:

<big snip>

Quoted 9 lines

With my powerpc hardware, it should be easily possible to have at least 6 devices, each with two virtqueues, one for tx and one for rx. (The limit is caused by the amount of distinct kick() events I can generate.) This could allow many combinations of devices, such as:

* 1 virtio-net, 1 virtio-console
* 3 virtio-net, 2 virtio-console
* 6 virtio-net
* etc.

Note that the vbus "connector" design abstract details such as kick events, so you are not limited by the number of physical interrupts of your hardware, per se.

You can actually have an arbitrary width namespace for your virtqueues running over a single interrupt, if you were so inclined. (Note you can also have a 1:1 with interrupts if you like, too)

If you look at the design of the vbus-pcibridge connector, it actually aggregates the entire namespace into between 1 and 8 interrupts (depending on availability, and separated by priority level). If multiple vectors are not available, the entire protocol can fallback to run over a single vector when necessary.

Kind Regards,
-Greg

#18 lore raw

PATCH 5/7 ioq: add driver-side vbus helpers

In reply to Gregory Haskins

It will be a common pattern to map an IOQ over the VBUS shared-memory interfaces. Therefore, we provide a helper function to generalize the allocation and registration of an IOQ to make this use case simple and easy.

---

 drivers/vbus/bus-proxy.c    |   64 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/vbus_driver.h |    7 +++++
 2 files changed, 71 insertions(+), 0 deletions(-)
drivers/vbus/bus-proxy.c +64 -0
index 3177f9f..88cd904 100644
@@ -150,3 +150,67 @@ void vbus_driver_unregister(struct vbus_driver *drv)
 }
 EXPORT_SYMBOL_GPL(vbus_driver_unregister);
 
+/*
+ *---------------------------------
+ * driver-side IOQ helper
+ *---------------------------------
+ */
+static void
+vbus_driver_ioq_release(struct ioq *ioq)
+{
+	kfree(ioq->head_desc);
+	kfree(ioq);
+}
+
+static struct ioq_ops vbus_driver_ioq_ops = {
+	.release = vbus_driver_ioq_release,
+};
+
+
+int vbus_driver_ioq_alloc(struct vbus_device_proxy *dev, int id, int prio,
+			  size_t count, struct ioq **ioq)
+{
+	struct ioq           *_ioq;
+	struct ioq_ring_head *head = NULL;
+	struct shm_signal    *signal = NULL;
+	size_t                len = IOQ_HEAD_DESC_SIZE(count);
+	int                   ret = -ENOMEM;
+
+	_ioq = kzalloc(sizeof(*_ioq), GFP_KERNEL);
+	if (!_ioq)
+		goto error;
+
+	head = kzalloc(len, GFP_KERNEL | GFP_DMA);
+	if (!head)
+		goto error;
+
+	head->magic     = IOQ_RING_MAGIC;
+	head->ver	= IOQ_RING_VER;
+	head->count     = count;
+
+	ret = dev->ops->shm(dev, id, prio, head, len,
+			    &head->signal, &signal, 0);
+	if (ret < 0)
+		goto error;
+
+	ioq_init(_ioq,
+		 &vbus_driver_ioq_ops,
+		 ioq_locality_north,
+		 head,
+		 signal,
+		 count);
+
+	*ioq = _ioq;
+
+	return 0;
+
+ error:
+	kfree(_ioq);
+	kfree(head);
+
+	if (signal)
+		shm_signal_put(signal);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vbus_driver_ioq_alloc);
include/linux/vbus_driver.h +7 -0
index c53e13f..9cfbf60 100644
@@ -26,6 +26,7 @@
 
 #include <linux/device.h>
 #include <linux/shm_signal.h>
+#include <linux/ioq.h>
 
 struct vbus_device_proxy;
 struct vbus_driver;
@@ -70,4 +71,10 @@ struct vbus_driver {
 int vbus_driver_register(struct vbus_driver *drv);
 void vbus_driver_unregister(struct vbus_driver *drv);
 
+/*
+ * driver-side IOQ helper - allocates device-shm and maps an IOQ on it
+ */
+int vbus_driver_ioq_alloc(struct vbus_device_proxy *dev, int id, int prio,
+			  size_t ringsize, struct ioq **ioq);
+
 #endif /* _LINUX_VBUS_DRIVER_H */
#19 lore raw

PATCH 6/7 net: Add vbus_enet driver

In reply to Gregory Haskins

A virtualized 802.x network device based on the VBUS interface. It can be used with any hypervisor/kernel that supports the virtual-ethernet/vbus protocol.

---

 drivers/net/Kconfig     |   14 +
 drivers/net/Makefile    |    1 
 drivers/net/vbus-enet.c |  672 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild    |    1 
 include/linux/venet.h   |   49 +++
 5 files changed, 737 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 include/linux/venet.h
drivers/net/Kconfig +14 -0
index 5f6509a..974213e 100644
@@ -3209,4 +3209,18 @@ config VIRTIO_NET
 	  This is the virtual network driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
 
+config VBUS_ENET
+	tristate "VBUS Ethernet Driver"
+	default n
+	select VBUS_PROXY
+	help
+	   A virtualized 802.x network device based on the VBUS
+	   "virtual-ethernet" interface.  It can be used with any
+	   hypervisor/kernel that supports the vbus+venet protocol.
+
+config VBUS_ENET_DEBUG
+        bool "Enable Debugging"
+	depends on VBUS_ENET
+	default n
+
 endif # NETDEVICES
drivers/net/Makefile +1 -0
index ead8cab..2a3c7a9 100644
@@ -277,6 +277,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
 obj-$(CONFIG_NETXEN_NIC) += netxen/
 obj-$(CONFIG_NIU) += niu.o
 obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
+obj-$(CONFIG_VBUS_ENET) += vbus-enet.o
 obj-$(CONFIG_SFC) += sfc/
 
 obj-$(CONFIG_WIMAX) += wimax/
drivers/net/vbus-enet.c new file +672 -0

672 lines not on this page · raw message

include/linux/Kbuild +1 -0
index fa15bbf..911f7ef 100644
@@ -359,6 +359,7 @@ unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
 unifdef-y += vbus_pci.h
+unifdef-y += venet.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
include/linux/venet.h new file +49 -0

49 lines not on this page · raw message

#20 lore raw

Re: [PATCH 6/7] net: Add vbus_enet driver

drivers/net/vbus-enet.c line 548

Quoted 9 lines · On Mon, 03 Aug 2009 13:18:02 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c new file +9 -0
+
+static const struct net_device_ops vbus_enet_netdev_ops = {
+	.ndo_open          = vbus_enet_open,
+	.ndo_stop          = vbus_enet_stop,
+	.ndo_set_config    = vbus_enet_config,
+	.ndo_start_xmit    = vbus_enet_tx_start,
+	.ndo_change_mtu	   = vbus_enet_change_mtu,
+	.ndo_tx_timeout    = vbus_enet_timeout,
+};

Missing
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,

Also, should have change_mtu.

Suggest adding ethtool to report link and settings.

For performance this device should do scatter/gather, tso, gso, etc.

#21 lore raw

Re: [PATCH 6/7] net: Add vbus_enet driver

Quoted 18 lines · Stephen Hemminger

drivers/net/vbus-enet.c line 548

Quoted 9 lines · On Mon, 03 Aug 2009 13:18:02 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c new file +9 -0
+
+static const struct net_device_ops vbus_enet_netdev_ops = {
+	.ndo_open          = vbus_enet_open,
+	.ndo_stop          = vbus_enet_stop,
+	.ndo_set_config    = vbus_enet_config,
+	.ndo_start_xmit    = vbus_enet_tx_start,
+	.ndo_change_mtu	   = vbus_enet_change_mtu,
+	.ndo_tx_timeout    = vbus_enet_timeout,
+};

Missing
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,

Ack.

Quoted 1 line

Also, should have change_mtu.

note that I do have .ndo_change_mtu. I assume this is what you are referring to and just missed it. If there is something else I need there, let me know.

Kind Regards,
-Greg

#22 lore raw

Re: [PATCH 6/7] net: Add vbus_enet driver

Quoted 20 lines · On Mon, 03 Aug 2009 16:10:37 -0400 Gregory Haskins <[email protected]> wrote:
Quoted 18 lines · Stephen Hemminger

drivers/net/vbus-enet.c line 548

Quoted 9 lines · On Mon, 03 Aug 2009 13:18:02 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c new file +9 -0
+
+static const struct net_device_ops vbus_enet_netdev_ops = {
+	.ndo_open          = vbus_enet_open,
+	.ndo_stop          = vbus_enet_stop,
+	.ndo_set_config    = vbus_enet_config,
+	.ndo_start_xmit    = vbus_enet_tx_start,
+	.ndo_change_mtu	   = vbus_enet_change_mtu,
+	.ndo_tx_timeout    = vbus_enet_timeout,
+};

Missing
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,

Quoted 7 lines

Ack.

Quoted 1 line

Also, should have change_mtu.

note that I do have .ndo_change_mtu. I assume this is what you are referring to and just missed it. If there is something else I need there, let me know.

If you don't have a change_mtu, then MTU is unlimited. Can the device handle 64K or larger transfers?

#23 lore raw

Re: [PATCH 6/7] net: Add vbus_enet driver

Quoted 21 lines · Stephen Hemminger
Quoted 18 lines · On Mon, 03 Aug 2009 16:10:37 -0400 Gregory Haskins <[email protected]> wrote:
Quoted 17 lines · Stephen Hemminger

drivers/net/vbus-enet.c line 548

Quoted 9 lines · On Mon, 03 Aug 2009 13:18:02 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c new file +9 -0
+
+static const struct net_device_ops vbus_enet_netdev_ops = {
+	.ndo_open          = vbus_enet_open,
+	.ndo_stop          = vbus_enet_stop,
+	.ndo_set_config    = vbus_enet_config,
+	.ndo_start_xmit    = vbus_enet_tx_start,
+	.ndo_change_mtu	   = vbus_enet_change_mtu,
+	.ndo_tx_timeout    = vbus_enet_timeout,
+};

Missing
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,

Quoted 8 lines
Quoted 6 lines

Ack.

Quoted 1 line

Also, should have change_mtu.

note that I do have .ndo_change_mtu. I assume this is what you are referring to and just missed it. If there is something else I need there, let me know.

If you don't have a change_mtu, then MTU is unlimited.

Is "change_mtu" different from .ndo_change_mtu" on the ndo struct? That's whats confusing me, as I have the .ndo one already. Is there something else I need in addition, or should I be ok as is?

Quoted 1 line

Can the device handle 64K or larger transfers?

Well, its been tested with 64K GSO packets at least. I think it could handle arbitrarily large packets as long as they are paged, but I have never tried this beyond 64k due to the simple L4 limitations of 64k.

Thanks Stephen,
-Greg

#24 lore raw

Re: [PATCH 6/7] net: Add vbus_enet driver

Quoted 29 lines · On Mon, 03 Aug 2009 16:24:10 -0400 Gregory Haskins <[email protected]>…
Quoted 28 lines · Stephen Hemminger
Quoted 24 lines · On Mon, 03 Aug 2009 16:10:37 -0400 Gregory Haskins <[email protected]> wrote:
Quoted 17 lines · Stephen Hemminger

drivers/net/vbus-enet.c line 548

Quoted 9 lines · On Mon, 03 Aug 2009 13:18:02 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c new file +9 -0
+
+static const struct net_device_ops vbus_enet_netdev_ops = {
+	.ndo_open          = vbus_enet_open,
+	.ndo_stop          = vbus_enet_stop,
+	.ndo_set_config    = vbus_enet_config,
+	.ndo_start_xmit    = vbus_enet_tx_start,
+	.ndo_change_mtu	   = vbus_enet_change_mtu,
+	.ndo_tx_timeout    = vbus_enet_timeout,
+};

Missing
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,

Ack.

Quoted 1 line

Also, should have change_mtu.

note that I do have .ndo_change_mtu. I assume this is what you are referring to and just missed it. If there is something else I need there, let me know.

Quoted 5 lines
Quoted 1 line

If you don't have a change_mtu, then MTU is unlimited.

Is "change_mtu" different from .ndo_change_mtu" on the ndo struct? That's whats confusing me, as I have the .ndo one already. Is there something else I need in addition, or should I be ok as is?

Never mind, it is same as .ndo_change_mtu

#25 lore raw

PATCH v2 1/1 net: Add vbus_enet driver

In reply to Gregory Haskins

This is version-2 of the vbus_enet driver, originally posted here:

http://lkml.org/lkml/2009/8/3/278

It address (I believe) all of Stephen Hemminger's feedback

[ Changelog:

v2:
*) folded patches 6/7 and 7/7 together
*) get rid of shadow flags
*) add missing baseline .ndo callbacks
*) add support for ethtool
]

Regards,
-Greg

-----------------------------

net: Add vbus_enet driver

A virtualized 802.x network device based on the VBUS interface. It can be used with any hypervisor/kernel that supports the virtual-ethernet/vbus protocol.

---

 drivers/net/Kconfig     |   14 +
 drivers/net/Makefile    |    1 
 drivers/net/vbus-enet.c |  895 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild    |    1 
 include/linux/venet.h   |   84 ++++
 5 files changed, 995 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 include/linux/venet.h
drivers/net/Kconfig +14 -0
index 5f6509a..974213e 100644
@@ -3209,4 +3209,18 @@ config VIRTIO_NET
 	  This is the virtual network driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
 
+config VBUS_ENET
+	tristate "VBUS Ethernet Driver"
+	default n
+	select VBUS_PROXY
+	help
+	   A virtualized 802.x network device based on the VBUS
+	   "virtual-ethernet" interface.  It can be used with any
+	   hypervisor/kernel that supports the vbus+venet protocol.
+
+config VBUS_ENET_DEBUG
+        bool "Enable Debugging"
+	depends on VBUS_ENET
+	default n
+
 endif # NETDEVICES
drivers/net/Makefile +1 -0
index ead8cab..2a3c7a9 100644
@@ -277,6 +277,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
 obj-$(CONFIG_NETXEN_NIC) += netxen/
 obj-$(CONFIG_NIU) += niu.o
 obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
+obj-$(CONFIG_VBUS_ENET) += vbus-enet.o
 obj-$(CONFIG_SFC) += sfc/
 
 obj-$(CONFIG_WIMAX) += wimax/
drivers/net/vbus-enet.c new file +895 -0

895 lines not on this page · raw message

include/linux/Kbuild +1 -0
index fa15bbf..911f7ef 100644
@@ -359,6 +359,7 @@ unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
 unifdef-y += vbus_pci.h
+unifdef-y += venet.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
include/linux/venet.h new file +84 -0

84 lines not on this page · raw message

maintainer Acked-by on v2 1/1
#26 lore raw

Re: [PATCH v2] net: Add vbus_enet driver

From: Gregory Haskins <[email protected]>
Date: Mon, 03 Aug 2009 21:14:04 -0400

Quoted 7 lines

net: Add vbus_enet driver

A virtualized 802.x network device based on the VBUS interface. It can be used with any hypervisor/kernel that supports the virtual-ethernet/vbus protocol.

I'm fine with this, it depends upon the vbus infrastructure so whoever pulls that in can pull this in as well:

#27 lore raw

Re: [Alacrityvm-devel] [PATCH v2] net: Add vbus_enet driver

Quoted 9 lines · David Miller

From: Gregory Haskins <[email protected]>
Date: Mon, 03 Aug 2009 21:14:04 -0400

Quoted 6 lines

net: Add vbus_enet driver

A virtualized 802.x network device based on the VBUS interface. It can be used with any hypervisor/kernel that supports the virtual-ethernet/vbus protocol.

Quoted 6 lines
Quoted 1 line

I'm fine with this, it depends upon the vbus infrastructure so whoever pulls that in can pull this in as well:

Thanks, David.

If there are no other comments/objections, I would propose to pull this into linux-next. I have prepared a branch specifically for this purpose, which can be found here:

git://git.kernel.org/pub/scm/linux/kernel/git/ghaskins/alacrityvm/linux-2.6.git
linux-next

I have also folded the following update to MAINTAINERS into the series:

MAINTAINERS +25 -0
index d6befb2..7cbcf5d 100644
@@ -2707,6 +2707,12 @@ L:       [email protected]
 S:     Maintained
 F:     drivers/serial/ioc3_serial.c
 
+IOQ LIBRARY
+M:     Gregory Haskins <[email protected]>
+S:     Maintained
+F:     include/linux/ioq.h
+F:     lib/ioq.c
+
 IP MASQUERADING
 M:     Juanjo Ciarlante <[email protected]>
 S:     Maintained
@@ -4555,6 +4561,12 @@ F:       drivers/serial/serial_lh7a40x.c
 F:     drivers/usb/gadget/lh7a40*
 F:     drivers/usb/host/ohci-lh7a40*
 
+SHM-SIGNAL LIBRARY
+M:     Gregory Haskins <[email protected]>
+S:     Maintained
+F:     include/linux/shm_signal.h
+F:     lib/shm_signal.c
+
 SHPC HOTPLUG DRIVER
 M:     Kristen Carlson Accardi <[email protected]>
 L:     [email protected]
@@ -5423,6 +5435,19 @@ S:       Maintained
 F:     Documentation/fb/uvesafb.txt
 F:     drivers/video/uvesafb.*
 
+VBUS
+M:     Gregory Haskins <[email protected]>
+S:     Maintained
+F:     include/linux/vbus*
+F:     drivers/vbus/*
+
+VBUS ETHERNET DRIVER
+M:     Gregory Haskins <[email protected]>
+S:     Maintained
+W:     http://developer.novell.com/wiki/index.php/AlacrityVM
+F:     include/linux/venet.h
+F:     drivers/net/vbus-enet.c
+
 VFAT/FAT/MSDOS FILESYSTEM
 M:     OGAWA Hirofumi <[email protected]>
 S:     Maintained
#28 lore raw

PATCH v3 1/1 net: Add vbus_enet driver

In reply to Gregory Haskins

A virtualized 802.x network device based on the VBUS interface. It can be used with any hypervisor/kernel that supports the virtual-ethernet/vbus protocol.

[ added several new features since last review:
pre-mapped-transmit descriptors,
event-queue,
link-state event
tx-complete event
]

---

 MAINTAINERS             |    7 
 drivers/net/Kconfig     |   14 +
 drivers/net/Makefile    |    1 
 drivers/net/vbus-enet.c | 1203 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild    |    1 
 include/linux/venet.h   |  123 +++++
 6 files changed, 1349 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 include/linux/venet.h
MAINTAINERS +7 -0
index b484756..ade37b5 100644
@@ -5456,6 +5456,13 @@ S:	Maintained
 F:	include/linux/vbus*
 F:	drivers/vbus/*
 
+VBUS ETHERNET DRIVER
+M:	Gregory Haskins <[email protected]>
+S:	Maintained
+W:	http://developer.novell.com/wiki/index.php/AlacrityVM
+F:	include/linux/venet.h
+F:	drivers/net/vbus-enet.c
+
 VFAT/FAT/MSDOS FILESYSTEM
 M:	OGAWA Hirofumi <[email protected]>
 S:	Maintained
drivers/net/Kconfig +14 -0
index 5ce7cba..722f892 100644
@@ -3211,4 +3211,18 @@ config VIRTIO_NET
 	  This is the virtual network driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
 
+config VBUS_ENET
+	tristate "VBUS Ethernet Driver"
+	default n
+	select VBUS_PROXY
+	help
+	   A virtualized 802.x network device based on the VBUS
+	   "virtual-ethernet" interface.  It can be used with any
+	   hypervisor/kernel that supports the vbus+venet protocol.
+
+config VBUS_ENET_DEBUG
+        bool "Enable Debugging"
+	depends on VBUS_ENET
+	default n
+
 endif # NETDEVICES
drivers/net/Makefile +1 -0
index ead8cab..2a3c7a9 100644
@@ -277,6 +277,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
 obj-$(CONFIG_NETXEN_NIC) += netxen/
 obj-$(CONFIG_NIU) += niu.o
 obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
+obj-$(CONFIG_VBUS_ENET) += vbus-enet.o
 obj-$(CONFIG_SFC) += sfc/
 
 obj-$(CONFIG_WIMAX) += wimax/
drivers/net/vbus-enet.c new file +1203 -0

1,203 lines not on this page · raw message

include/linux/Kbuild +1 -0
index fa15bbf..911f7ef 100644
@@ -359,6 +359,7 @@ unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
 unifdef-y += vbus_pci.h
+unifdef-y += venet.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
include/linux/venet.h new file +123 -0

123 lines not on this page · raw message

#29 lore raw

PATCH 7/7 venet: add scatter-gather/GSO support

In reply to Gregory Haskins

SG/GSO significantly enhance the performance of network traffic under certain circumstances. We implement this feature as a separate patch to avoid intially complicating the baseline venet driver. This will presumably make the review process slightly easier, since we can focus on the basic interface first.

---

 drivers/net/vbus-enet.c |  249 +++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/venet.h   |   39 +++++++
 2 files changed, 275 insertions(+), 13 deletions(-)
drivers/net/vbus-enet.c +238 -11
index 8fcc2d6..5aa56ff 100644
@@ -42,6 +42,8 @@ static int rx_ringlen = 256;
 module_param(rx_ringlen, int, 0444);
 static int tx_ringlen = 256;
 module_param(tx_ringlen, int, 0444);
+static int sg_enabled = 1;
+module_param(sg_enabled, int, 0444);
 
 #define PDEBUG(_dev, fmt, args...) dev_dbg(&(_dev)->dev, fmt, ## args)
 
@@ -58,8 +60,17 @@ struct vbus_enet_priv {
 	struct vbus_enet_queue     rxq;
 	struct vbus_enet_queue     txq;
 	struct tasklet_struct      txtask;
+	struct {
+		int                sg:1;
+		int                tso:1;
+		int                ufo:1;
+		int                tso6:1;
+		int                ecn:1;
+	} flags;
 };
 
+static void vbus_enet_tx_reap(struct vbus_enet_priv *priv, int force);
+
 static struct vbus_enet_priv *
 napi_to_priv(struct napi_struct *napi)
 {
@@ -193,6 +204,93 @@ rx_teardown(struct vbus_enet_priv *priv)
 	}
 }
 
+static int
+tx_setup(struct vbus_enet_priv *priv)
+{
+	struct ioq *ioq = priv->txq.queue;
+	struct ioq_iterator iter;
+	int i;
+	int ret;
+
+	if (!priv->flags.sg)
+		/*
+		 * There is nothing to do for a ring that is not using
+		 * scatter-gather
+		 */
+		return 0;
+
+	ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+	BUG_ON(ret < 0);
+
+	ret = ioq_iter_seek(&iter, ioq_seek_set, 0, 0);
+	BUG_ON(ret < 0);
+
+	/*
+	 * Now populate each descriptor with an empty SG descriptor
+	 */
+	for (i = 0; i < tx_ringlen; i++) {
+		struct venet_sg *vsg;
+		size_t iovlen = sizeof(struct venet_iov) * (MAX_SKB_FRAGS-1);
+		size_t len = sizeof(*vsg) + iovlen;
+
+		vsg = kzalloc(len, GFP_KERNEL);
+		if (!vsg)
+			return -ENOMEM;
+
+		iter.desc->cookie = (u64)vsg;
+		iter.desc->len    = len;
+		iter.desc->ptr    = (u64)__pa(vsg);
+
+		ret = ioq_iter_seek(&iter, ioq_seek_next, 0, 0);
+		BUG_ON(ret < 0);
+	}
+
+	return 0;
+}
+
+static void
+tx_teardown(struct vbus_enet_priv *priv)
+{
+	struct ioq *ioq = priv->txq.queue;
+	struct ioq_iterator iter;
+	int ret;
+
+	/* forcefully free all outstanding transmissions */
+	vbus_enet_tx_reap(priv, 1);
+
+	if (!priv->flags.sg)
+		/*
+		 * There is nothing else to do for a ring that is not using
+		 * scatter-gather
+		 */
+		return;
+
+	ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+	BUG_ON(ret < 0);
+
+	/* seek to position 0 */
+	ret = ioq_iter_seek(&iter, ioq_seek_set, 0, 0);
+	BUG_ON(ret < 0);
+
+	/*
+	 * free each valid descriptor
+	 */
+	while (iter.desc->cookie) {
+		struct venet_sg *vsg = (struct venet_sg *)iter.desc->cookie;
+
+		iter.desc->valid = 0;
+		wmb();
+
+		iter.desc->ptr = 0;
+		iter.desc->cookie = 0;
+
+		ret = ioq_iter_seek(&iter, ioq_seek_next, 0, 0);
+		BUG_ON(ret < 0);
+
+		kfree(vsg);
+	}
+}
+
 /*
  * Open and close
  */
@@ -396,14 +494,67 @@ vbus_enet_tx_start(struct sk_buff *skb, struct net_device *dev)
 	BUG_ON(ret < 0);
 	BUG_ON(iter.desc->sown);
 
-	/*
-	 * We simply put the skb right onto the ring.  We will get an interrupt
-	 * later when the data has been consumed and we can reap the pointers
-	 * at that time
-	 */
-	iter.desc->cookie = (u64)skb;
-	iter.desc->len = (u64)skb->len;
-	iter.desc->ptr = (u64)__pa(skb->data);
+	if (priv->flags.sg) {
+		struct venet_sg *vsg = (struct venet_sg *)iter.desc->cookie;
+		struct scatterlist sgl[MAX_SKB_FRAGS+1];
+		struct scatterlist *sg;
+		int count, maxcount = ARRAY_SIZE(sgl);
+
+		sg_init_table(sgl, maxcount);
+
+		memset(vsg, 0, sizeof(*vsg));
+
+		vsg->cookie = (u64)skb;
+		vsg->len    = skb->len;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			vsg->flags      |= VENET_SG_FLAG_NEEDS_CSUM;
+			vsg->csum.start  = skb->csum_start - skb_headroom(skb);
+			vsg->csum.offset = skb->csum_offset;
+		}
+
+		if (skb_is_gso(skb)) {
+			struct skb_shared_info *sinfo = skb_shinfo(skb);
+
+			vsg->flags |= VENET_SG_FLAG_GSO;
+
+			vsg->gso.hdrlen = skb_transport_header(skb) - skb->data;
+			vsg->gso.size = sinfo->gso_size;
+			if (sinfo->gso_type & SKB_GSO_TCPV4)
+				vsg->gso.type = VENET_GSO_TYPE_TCPV4;
+			else if (sinfo->gso_type & SKB_GSO_TCPV6)
+				vsg->gso.type = VENET_GSO_TYPE_TCPV6;
+			else if (sinfo->gso_type & SKB_GSO_UDP)
+				vsg->gso.type = VENET_GSO_TYPE_UDP;
+			else
+				panic("Virtual-Ethernet: unknown GSO type " \
+				      "0x%x\n", sinfo->gso_type);
+
+			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
+				vsg->flags |= VENET_SG_FLAG_ECN;
+		}
+
+		count = skb_to_sgvec(skb, sgl, 0, skb->len);
+
+		BUG_ON(count > maxcount);
+
+		for (sg = &sgl[0]; sg; sg = sg_next(sg)) {
+			struct venet_iov *iov = &vsg->iov[vsg->count++];
+
+			iov->len = sg->length;
+			iov->ptr = (u64)sg_phys(sg);
+		}
+
+	} else {
+		/*
+		 * non scatter-gather mode: simply put the skb right onto the
+		 * ring.
+		 */
+		iter.desc->cookie = (u64)skb;
+		iter.desc->len = (u64)skb->len;
+		iter.desc->ptr = (u64)__pa(skb->data);
+	}
+
 	iter.desc->valid  = 1;
 
 	priv->dev->stats.tx_packets++;
@@ -459,7 +610,17 @@ vbus_enet_tx_reap(struct vbus_enet_priv *priv, int force)
 	 * owned by the south-side
 	 */
 	while (iter.desc->valid && (!iter.desc->sown || force)) {
-		struct sk_buff *skb = (struct sk_buff *)iter.desc->cookie;
+		struct sk_buff *skb;
+
+		if (priv->flags.sg) {
+			struct venet_sg *vsg;
+
+			vsg = (struct venet_sg *)iter.desc->cookie;
+			skb = (struct sk_buff *)vsg->cookie;
+
+		} else {
+			skb = (struct sk_buff *)iter.desc->cookie;
+		}
 
 		PDEBUG(priv->dev, "completed sending %d bytes\n", skb->len);
 
@@ -538,6 +699,47 @@ tx_isr(struct ioq_notifier *notifier)
        tasklet_schedule(&priv->txtask);
 }
 
+static int
+vbus_enet_negcap(struct vbus_enet_priv *priv)
+{
+	int ret;
+	struct venet_capabilities caps;
+
+	memset(&caps, 0, sizeof(caps));
+
+	if (sg_enabled) {
+		caps.gid = VENET_CAP_GROUP_SG;
+		caps.bits |= (VENET_CAP_SG|VENET_CAP_TSO4|VENET_CAP_TSO6
+			      |VENET_CAP_ECN);
+		/* note: exclude UFO for now due to stack bug */
+	}
+
+	ret = devcall(priv, VENET_FUNC_NEGCAP, &caps, sizeof(caps));
+	if (ret < 0)
+		return ret;
+
+	if (caps.bits & VENET_CAP_SG) {
+		priv->flags.sg = true;
+
+		if (caps.bits & VENET_CAP_TSO4)
+			priv->flags.tso = true;
+		if (caps.bits & VENET_CAP_TSO6)
+			priv->flags.tso6 = true;
+		if (caps.bits & VENET_CAP_UFO)
+			priv->flags.ufo = true;
+		if (caps.bits & VENET_CAP_ECN)
+			priv->flags.ecn = true;
+
+		dev_info(&priv->dev->dev, "Detected GSO features %s%s%s%s\n",
+			 priv->flags.tso  ? "t" : "-",
+			 priv->flags.tso6 ? "T" : "-",
+			 priv->flags.ufo  ? "u" : "-",
+			 priv->flags.ecn  ? "e" : "-");
+	}
+
+	return 0;
+}
+
 static const struct net_device_ops vbus_enet_netdev_ops = {
 	.ndo_open          = vbus_enet_open,
 	.ndo_stop          = vbus_enet_stop,
@@ -574,12 +776,21 @@ vbus_enet_probe(struct vbus_device_proxy *vdev)
 	priv->dev  = dev;
 	priv->vdev = vdev;
 
+	ret = vbus_enet_negcap(priv);
+	if (ret < 0) {
+		printk(KERN_INFO "VENET: Error negotiating capabilities for " \
+		       "%lld\n",
+		       priv->vdev->id);
+		goto out_free;
+	}
+
 	tasklet_init(&priv->txtask, deferred_tx_isr, (unsigned long)priv);
 
 	queue_init(priv, &priv->rxq, VENET_QUEUE_RX, rx_ringlen, rx_isr);
 	queue_init(priv, &priv->txq, VENET_QUEUE_TX, tx_ringlen, tx_isr);
 
 	rx_setup(priv);
+	tx_setup(priv);
 
 	ioq_notify_enable(priv->rxq.queue, 0);  /* enable interrupts */
 	ioq_notify_enable(priv->txq.queue, 0);
@@ -599,6 +810,22 @@ vbus_enet_probe(struct vbus_device_proxy *vdev)
 
 	dev->features |= NETIF_F_HIGHDMA;
 
+	if (priv->flags.sg) {
+		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM|NETIF_F_FRAGLIST;
+
+		if (priv->flags.tso)
+			dev->features |= NETIF_F_TSO;
+
+		if (priv->flags.ufo)
+			dev->features |= NETIF_F_UFO;
+
+		if (priv->flags.tso6)
+			dev->features |= NETIF_F_TSO6;
+
+		if (priv->flags.ecn)
+			dev->features |= NETIF_F_TSO_ECN;
+	}
+
 	ret = register_netdev(dev);
 	if (ret < 0) {
 		printk(KERN_INFO "VENET: error %i registering device \"%s\"\n",
@@ -626,9 +853,9 @@ vbus_enet_remove(struct vbus_device_proxy *vdev)
 	napi_disable(&priv->napi);
 
 	rx_teardown(priv);
-	vbus_enet_tx_reap(priv, 1);
-
 	ioq_put(priv->rxq.queue);
+
+	tx_teardown(priv);
 	ioq_put(priv->txq.queue);
 
 	dev->ops->close(dev, 0);
include/linux/venet.h +37 -2
index 586be40..47ed37d 100644
@@ -37,8 +37,43 @@ struct venet_capabilities {
 	__u32 bits;
 };
 
-/* CAPABILITIES-GROUP 0 */
-/* #define VENET_CAP_FOO    0   (No capabilities defined yet, for now) */
+#define VENET_CAP_GROUP_SG 0
+
+/* CAPABILITIES-GROUP SG */
+#define VENET_CAP_SG     (1 << 0)
+#define VENET_CAP_TSO4   (1 << 1)
+#define VENET_CAP_TSO6   (1 << 2)
+#define VENET_CAP_ECN    (1 << 3)
+#define VENET_CAP_UFO    (1 << 4)
+
+struct venet_iov {
+	__u32 len;
+	__u64 ptr;
+};
+
+#define VENET_SG_FLAG_NEEDS_CSUM (1 << 0)
+#define VENET_SG_FLAG_GSO        (1 << 1)
+#define VENET_SG_FLAG_ECN        (1 << 2)
+
+struct venet_sg {
+	__u64            cookie;
+	__u32            flags;
+	__u32            len;     /* total length of all iovs */
+	struct {
+		__u16    start;	  /* csum starting position */
+		__u16    offset;  /* offset to place csum */
+	} csum;
+	struct {
+#define VENET_GSO_TYPE_TCPV4	0	/* IPv4 TCP (TSO) */
+#define VENET_GSO_TYPE_UDP	1	/* IPv4 UDP (UFO) */
+#define VENET_GSO_TYPE_TCPV6	2	/* IPv6 TCP */
+		__u8     type;
+		__u16    hdrlen;
+		__u16    size;
+	} gso;
+	__u32            count;   /* nr of iovs */
+	struct venet_iov iov[1];
+};
 
 #define VENET_FUNC_LINKUP   0
 #define VENET_FUNC_LINKDOWN 1
#30 lore raw

Re: [PATCH 7/7] venet: add scatter-gather/GSO support

Quoted 7 lines · On Mon, 03 Aug 2009 13:18:07 -0400 Gregory Haskins <[email protected]> wrote:

SG/GSO significantly enhance the performance of network traffic under certain circumstances. We implement this feature as a separate patch to avoid intially complicating the baseline venet driver. This will presumably make the review process slightly easier, since we can focus on the basic interface first.

Never mind, previous comment about adding TSO. But it still would be good to have ethtool interface for this.

#31 lore raw

Re: [PATCH 7/7] venet: add scatter-gather/GSO support

Quoted 9 lines · Stephen Hemminger
Quoted 6 lines · On Mon, 03 Aug 2009 13:18:07 -0400 Gregory Haskins <[email protected]> wrote:

SG/GSO significantly enhance the performance of network traffic under certain circumstances. We implement this feature as a separate patch to avoid intially complicating the baseline venet driver. This will presumably make the review process slightly easier, since we can focus on the basic interface first.

Quoted 3 lines
Quoted 1 line

Never mind, previous comment about adding TSO.

I should probably fold 6+7 together anyway, so this was my fault. I think I was originally keeping them separate because the venet was serving as the canonical example for the vbus interface. But Ill just come up with something simpler to demonstrate the interface and merge these two patches.

Quoted 1 line

But it still would be good to have ethtool interface for this.

Ack. Will do.

Thanks Stephen,
-Greg

#32 lore raw

Re: [PATCH 7/7] venet: add scatter-gather/GSO support

In reply to Gregory Haskins

drivers/net/vbus-enet.c struct vbus_enet_priv { · line 69

Quoted 7 lines · On Mon, 03 Aug 2009 13:18:07 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c +7 -0
+	struct {
+		int                sg:1;
+		int                tso:1;
+		int                ufo:1;
+		int                tso6:1;
+		int                ecn:1;
+	} flags;

Why do you have to shadow flags that are already available in net_device? It is bad design to replicate state in a device driver. The problem with replicated state is that it has to be updated in both places.

#33 lore raw

Re: [PATCH 7/7] venet: add scatter-gather/GSO support

Quoted 15 lines · Stephen Hemminger

drivers/net/vbus-enet.c struct vbus_enet_priv { · line 69

Quoted 7 lines · On Mon, 03 Aug 2009 13:18:07 -0400 Gregory Haskins <[email protected]> wrote:
drivers/net/vbus-enet.c +7 -0
+	struct {
+		int                sg:1;
+		int                tso:1;
+		int                ufo:1;
+		int                tso6:1;
+		int                ecn:1;
+	} flags;

Why do you have to shadow flags that are already available in net_device? It is bad design to replicate state in a device driver. The problem with replicated state is that it has to be updated in both places.

Ya, you are right. I think the rationale was that the flags were "hw" state, whereas dev->features was software state. But thinking about it after you comments, I don't think it makes much difference either way.

I will just have the negcap() function set the features directly in v2.

Kind Regards,
-Greg

#34 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Gregory Haskins
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right? Merging the guest first means relying on kernel interface from an out of tree driver, which well might change before it goes in. Would it make more sense to start merging with the host side of the project?

Quoted 5 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

Quoted 2 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

The graphs comparing virtio with vbus look interesting. However, they do not compare apples to apples, do they? These compare userspace virtio with kernel vbus, where for apples to apples comparison one would need to compare kernel virtio with kernel vbus. Right?

Quoted 54 lines

Regards,
-Greg

---

Gregory Haskins (7):
venet: add scatter-gather/GSO support
net: Add vbus_enet driver
ioq: add driver-side vbus helpers
vbus-proxy: add a pci-to-vbus bridge
vbus: add a "vbus-proxy" bus model for vbus_driver objects
ioq: Add basic definitions for a shared-memory, lockless queue
shm-signal: shared-memory signals

 arch/x86/Kconfig            |    2 
 drivers/Makefile            |    1 
 drivers/net/Kconfig         |   14 +
 drivers/net/Makefile        |    1 
 drivers/net/vbus-enet.c     |  899 +++++++++++++++++++++++++++++++++++++++++++
 drivers/vbus/Kconfig        |   24 +
 drivers/vbus/Makefile       |    6 
 drivers/vbus/bus-proxy.c    |  216 ++++++++++
 drivers/vbus/pci-bridge.c   |  824 +++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild        |    4 
 include/linux/ioq.h         |  415 ++++++++++++++++++++
 include/linux/shm_signal.h  |  189 +++++++++
 include/linux/vbus_driver.h |   80 ++++
 include/linux/vbus_pci.h    |  127 ++++++
 include/linux/venet.h       |   84 ++++
 lib/Kconfig                 |   21 +
 lib/Makefile                |    2 
 lib/ioq.c                   |  294 ++++++++++++++
 lib/shm_signal.c            |  192 +++++++++
 19 files changed, 3395 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 drivers/vbus/Kconfig
 create mode 100644 drivers/vbus/Makefile
 create mode 100644 drivers/vbus/bus-proxy.c
 create mode 100644 drivers/vbus/pci-bridge.c
 create mode 100644 include/linux/ioq.h
 create mode 100644 include/linux/shm_signal.h
 create mode 100644 include/linux/vbus_driver.h
 create mode 100644 include/linux/vbus_pci.h
 create mode 100644 include/linux/venet.h
 create mode 100644 lib/ioq.c
 create mode 100644 lib/shm_signal.c
Signature · 5 lines
Signature
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#35 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 16 lines · Michael S. Tsirkin
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right? Merging the guest first means relying on kernel interface from an out of tree driver, which well might change before it goes in. Would it make more sense to start merging with the host side of the project?

Quoted 5 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

Quoted 8 lines
Quoted 2 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

The graphs comparing virtio with vbus look interesting. However, they do not compare apples to apples, do they? These compare userspace virtio with kernel vbus, where for apples to apples comparison one would need to compare kernel virtio with kernel vbus. Right?

Or userspace virtio with userspace vbus.

Quoted 54 lines
Quoted 54 lines

Regards,
-Greg

---

Gregory Haskins (7):
venet: add scatter-gather/GSO support
net: Add vbus_enet driver
ioq: add driver-side vbus helpers
vbus-proxy: add a pci-to-vbus bridge
vbus: add a "vbus-proxy" bus model for vbus_driver objects
ioq: Add basic definitions for a shared-memory, lockless queue
shm-signal: shared-memory signals

 arch/x86/Kconfig            |    2 
 drivers/Makefile            |    1 
 drivers/net/Kconfig         |   14 +
 drivers/net/Makefile        |    1 
 drivers/net/vbus-enet.c     |  899 +++++++++++++++++++++++++++++++++++++++++++
 drivers/vbus/Kconfig        |   24 +
 drivers/vbus/Makefile       |    6 
 drivers/vbus/bus-proxy.c    |  216 ++++++++++
 drivers/vbus/pci-bridge.c   |  824 +++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild        |    4 
 include/linux/ioq.h         |  415 ++++++++++++++++++++
 include/linux/shm_signal.h  |  189 +++++++++
 include/linux/vbus_driver.h |   80 ++++
 include/linux/vbus_pci.h    |  127 ++++++
 include/linux/venet.h       |   84 ++++
 lib/Kconfig                 |   21 +
 lib/Makefile                |    2 
 lib/ioq.c                   |  294 ++++++++++++++
 lib/shm_signal.c            |  192 +++++++++
 19 files changed, 3395 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/vbus-enet.c
 create mode 100644 drivers/vbus/Kconfig
 create mode 100644 drivers/vbus/Makefile
 create mode 100644 drivers/vbus/bus-proxy.c
 create mode 100644 drivers/vbus/pci-bridge.c
 create mode 100644 include/linux/ioq.h
 create mode 100644 include/linux/shm_signal.h
 create mode 100644 include/linux/vbus_driver.h
 create mode 100644 include/linux/vbus_pci.h
 create mode 100644 include/linux/venet.h
 create mode 100644 lib/ioq.c
 create mode 100644 lib/shm_signal.c
Signature · 5 lines
Signature
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#36 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 6:17 AM, in message <[email protected]>,

Quoted 20 lines · Michael S. Tsirkin
Quoted 19 lines · Michael S. Tsirkin
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right? Merging the guest first means relying on kernel interface from an out of tree driver, which well might change before it goes in. Would it make more sense to start merging with the host side of the project?

Quoted 5 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

Quoted 2 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

Quoted 7 lines
Quoted 5 lines

The graphs comparing virtio with vbus look interesting. However, they do not compare apples to apples, do they? These compare userspace virtio with kernel vbus, where for apples to apples comparison one would need to compare kernel virtio with kernel vbus. Right?

Or userspace virtio with userspace vbus.

Note: That would be pointless.

-Greg

#37 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Michael S. Tsirkin

Hi Michael,

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 4:19 AM, in message <[email protected]>,

Quoted 4 lines · Michael S. Tsirkin
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right?

Yep.

Quoted 3 lines

Merging the guest first means relying on
kernel interface from an out of tree driver, which well might change before it goes in.

ABI compatibility is already addressed/handled, so even if that is true its not a problem.

Quoted 1 line

Would it make more sense to start merging with the host side of the project?

Not necessarily, no. These are drivers for a "device", so its no different than merging any other driver really. This is especially true since the hypervisor is also already published and freely available today, so anyone can start using it.

Quoted 8 lines
Quoted 6 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

I *can* do that, but there is nothing in these drivers that is KVM specific (its all pure PCI and VBUS). I've already made the general announcement about the project/ml cross posted to KVM for anyone that might be interested, but I figure I will spare the general KVM list the details unless something specifically pertains to, or affects, KVM. For instance, when I get to pushing the hypervisor side, I still need to work on getting that 'xinterface' patch to you guys. I would certainly be CC'ing kvm@vger when that happens since it modifies the KVM code.

So instead, I would just encourage anyone interested (such as yourself) to join the alacrity list so I don't bother the KVM community unless absolutely necessary.

Quoted 6 lines
Quoted 3 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

The graphs comparing virtio with vbus look interesting. However, they do not compare apples to apples, do they?

Yes, I believe they do. They represent the best that KVM has to offer (to my knowledge) vs the best that alacrityvm has to offer.

Quoted 1 line

These compare userspace virtio with kernel vbus,

vbus is a device model (akin to QEMU's device model). Technically, it was a comparison of userspace virtio-net (via QEMU), to kernel venet (via vbus), which I again stress is the state of the art for both to my knowledge.

As I have explained before in earlier threads on kvm@vger, virtio is not mutually exclusive here. You can run the virtio protocol over the vbus model if someone were so inclined. In fact, I proposed this very idea to you a month or two ago but I believe you decided to go your own way and reinvent some other in-kernel model instead for your own reasons.

Quoted 2 lines

where for apples to apples comparison one would need to compare kernel virtio with kernel vbus. Right?

Again, it already *is* apples to apples as far as I am concerned.

At the time I ran those numbers, there was certainly no in-kernel virtio model to play with. And to my knowledge, there isn't one now (I was never CC'd on the patches, and a cursory search of the KVM list isn't revealing one that was posted recently).

To reiterate: kernel virtio-net (using ??) to kernel venet (vbus based) to kernel virtio-net (vbus, but doesnt exist yet) would be a fun bakeoff. If you have something for the kernel virtio-net, point me at it and I will try to include it in the comparison next time.

Kind Regards,
-Greg

#38 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 9 lines · Gregory Haskins

Hi Michael,

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 4:19 AM, in message <[email protected]>,

Quoted 4 lines · Michael S. Tsirkin
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right?

Quoted 7 lines

Yep.

Quoted 3 lines

Merging the guest first means relying on
kernel interface from an out of tree driver, which well might change before it goes in.

ABI compatibility is already addressed/handled, so even if that is true its not a problem.

It is? With versioning? Presumably this:

+ params.devid = vdev->id;
+ params.version = version;
+
+ ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVOPEN,
+ &params, sizeof(params));
+ if (ret < 0)
+ return ret;

Even assuming host even knows how to decode this structure (e.g. some other host module doesn't use VBUS_PCI_HC_DEVOPEN), checks the version and denies older guests, this might help guest not to crash, but guest still won't work.

Quoted 6 lines
Quoted 1 line

Would it make more sense to start merging with the host side of the project?

Not necessarily, no. These are drivers for a "device", so its no different than merging any other driver really. This is especially true since the hypervisor is also already published and freely available today, so anyone can start using it.

The difference is clear to me: devices do not get to set kernel/userspace interfaces. This "device" depends on a specific interface between kernel and (guest) userspace.

Signature · 1 line
MST
#39 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 8:24 AM, in message <[email protected]>,

Quoted 21 lines · Michael S. Tsirkin
Quoted 9 lines · Gregory Haskins

Hi Michael,

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 4:19 AM, in message <[email protected]>,

Quoted 4 lines · Michael S. Tsirkin
Quoted 1 line · Gregory Haskins

(Applies to v2.6.31-rc5, proposed for linux-next after review is complete)

These are guest drivers, right?

Quoted 7 lines

Yep.

Quoted 3 lines

Merging the guest first means relying on
kernel interface from an out of tree driver, which well might change before it goes in.

ABI compatibility is already addressed/handled, so even if that is true its

not a problem.

It is? With versioning? Presumably this:

Review

Quoted 7 lines
(quoted diff) +7 -0
+       params.devid   = vdev->id;
+       params.version = version;
+
+       ret = vbus_pci_hypercall(VBUS_PCI_HC_DEVOPEN,
+                                &params, sizeof(params));
+       if (ret < 0)
+               return ret;

This is part of it. There are various ABI version components (which, by the way, are only expected to only allow change while the code is experimental/alpha). The other component is capability functions (such as NEGCAP in the venet driver).

Quoted 3 lines

Even assuming host even knows how to decode this structure (e.g. some other host module doesn't use VBUS_PCI_HC_DEVOPEN),

This argument demonstrates a fundamental lack of understanding on how AlacrityVM works. Please study the code more closely and you will see that your concern is illogical. If it's still not clear, let me know and I will walk it through for you.

Quoted 3 lines

checks the version
and denies older guests, this might help guest not to crash, but guest still won't work.

Thats ok. As I said above, the version number is just there for gross ABI protection and generally will never be changed once a driver is "official" (if at all). We use things like capability-bit negotiation to allow backwards compat.

For an example, see drivers/net/vbus-enet.c, line 703:

http://git.kernel.org/?p=linux/kernel/git/ghaskins/alacrityvm/linux-2.6.git;a=blob;f=drivers/net/vbus-enet.c;h=7220f43723adc5b0bece1bc37974fae1b034cd9e;hb=b3b2339efbd4e754b1c85f8bc8f85f21a1a1f509#l703

venet exposes a verb "NEGCAP" (negotiate capabilities), which is used to extend the ABI. The version number you quote above (on the device open) is really just a check to make sure the NEGCAP ABI is compatible. The rest of the abi is negotiated at runtime with capability feature bits.

FWIW; I decided to not built a per-device capability into the low-level vbus protocol (e.g. there is no VBUS_PCI_HC_NEGCAP) because I felt as though the individual devices could better express their own capability mechanism, rather than try to generalize it. Therefore it is up to each device to define its own mechanism, presumably using a verb from its own private call() namespace (as venet has done).

Quoted 4 lines
Quoted 2 lines
Quoted 2 lines

Would it make more sense to start merging with the host side of the

project?

Quoted 1 line
Quoted 8 lines
Quoted 4 lines

Not necessarily, no. These are drivers for a "device", so its no different than merging any other driver really. This is especially true since the hypervisor is also already published and freely available today, so anyone can start using it.

The difference is clear to me: devices do not get to set kernel/userspace interfaces. This "device" depends on a specific interface between kernel and (guest) userspace.

This doesn't really parse for me, but I think the gist of it is based on an incorrect assumption.

Can you elaborate?

Kind Regards,
-Greg

#40 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Gregory Haskins
Quoted 8 lines · Gregory Haskins
Quoted 4 lines

Merging the guest first means relying on
kernel interface from an out of tree driver, which well might change before it goes in.

ABI compatibility is already addressed/handled, so even if that is true its not a problem.

Really the correct way to address the ABI is to publish a spec and write both host and guest drivers to that. Unfortunately we didn't do this with virtio.

It becomes more important when you have multiple implementations (e.g. Windows drivers).

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

Quoted 9 lines
Quoted 4 lines
Quoted 2 lines

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

I *can* do that, but there is nothing in these drivers that is KVM specific (its all pure PCI and VBUS). I've already made the general announcement about the project/ml cross posted to KVM for anyone that might be interested, but I figure I will spare the general KVM list the details unless something specifically pertains to, or affects, KVM. For instance, when I get to pushing the hypervisor side, I still need to work on getting that 'xinterface' patch to you guys. I would certainly be CC'ing kvm@vger when that happens since it modifies the KVM code.

So instead, I would just encourage anyone interested (such as yourself) to join the alacrity list so I don't bother the KVM community unless absolutely necessary.

It's true that vbus is a separate project (in fact even virtio is completely separate from kvm). Still I think it would be of interest to many kvm@ readers.

Signature · 1 line
error compiling committee.c: too many arguments to function
#41 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 8:54 AM, in message <[email protected]>, Avi Kivity

Quoted 36 lines · <[email protected]> wrote:
Quoted 6 lines · Gregory Haskins
Quoted 4 lines

Merging the guest first means relying on
kernel interface from an out of tree driver, which well might change before it goes in.

ABI compatibility is already addressed/handled, so even if that is true its

not a problem.

Quoted 2 lines

Really the correct way to address the ABI is to publish a spec and write both host and guest drivers to that. Unfortunately we didn't do this with virtio.

It becomes more important when you have multiple implementations (e.g. Windows drivers).

Quoted 10 lines
Quoted 8 lines
Quoted 6 lines

This series implements the guest-side drivers for accelerated IO when running on top of the AlacrityVM hypervisor, the details of which you can find here:

http://developer.novell.com/wiki/index.php/AlacrityVM

Since AlacrityVM is kvm based, Cc [email protected].

I *can* do that, but there is nothing in these drivers that is KVM specific

(its all pure PCI and VBUS). I've already made the general announcement about the project/ml cross posted to KVM for anyone that might be interested, but I figure I will spare the general KVM list the details unless something specifically pertains to, or affects, KVM. For instance, when I get to pushing the hypervisor side, I still need to work on getting that 'xinterface' patch to you guys. I would certainly be CC'ing kvm@vger when that happens since it modifies the KVM code.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

So instead, I would just encourage anyone interested (such as yourself) to

join the alacrity list so I don't bother the KVM community unless absolutely necessary.

Quoted 1 line

It's true that vbus is a separate project (in fact even virtio is completely separate from kvm). Still I think it would be of interest to many kvm@ readers.

Well, my goal was to not annoy KVM readers. ;) So if you feel as though there is benefit to having all of KVM CC'd and I won't be annoying everyone, I see no problem in cross posting.

Would you like to see all conversations, or just ones related to code (and, of course, KVM relevant items)?

Regards,
-Greg

#42 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 7 lines · Gregory Haskins
Quoted 4 lines

It's true that vbus is a separate project (in fact even virtio is completely separate from kvm). Still I think it would be of interest to many kvm@ readers.

Well, my goal was to not annoy KVM readers. ;) So if you feel as though there is benefit to having all of KVM CC'd and I won't be annoying everyone, I see no problem in cross posting.

I can only speak for myself, I'm interested in this project (though still rooting for virtio).

Quoted 1 line

Would you like to see all conversations, or just ones related to code (and, of course, KVM relevant items)

I guess internal vbus changes won't be too interesting for most readers, but new releases, benchmarks, and kvm-related stuff will be welcome on the kvm list.

Signature · 1 line
error compiling committee.c: too many arguments to function
#43 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 9:44 AM, in message <[email protected]>, Avi Kivity

Quoted 6 lines · <[email protected]> wrote:
Quoted 5 lines · Gregory Haskins
Quoted 4 lines

It's true that vbus is a separate project (in fact even virtio is completely separate from kvm). Still I think it would be of interest to many kvm@ readers.

Quoted 6 lines
Quoted 1 line

Well, my goal was to not annoy KVM readers. ;) So if you feel as though

there is benefit to having all of KVM CC'd and I won't be annoying everyone, I see no problem in cross posting.

Quoted 1 line

I can only speak for myself, I'm interested in this project

In that case, the best solution is probably to have you (and anyone else interested) to sign up, then:

https://lists.sourceforge.net/lists/listinfo/alacrityvm-devel
https://lists.sourceforge.net/lists/listinfo/alacrityvm-users

Quoted 1 line

(though still rooting for virtio).

Heh...not to belabor the point to death, but virtio is orthogonal (you keep forgetting that ;).

Its really the vbus device-model vs the qemu device-model (and possibly vs the "in-kernel pci emulation" model that I believe Michael is working on).

You can run virtio on any of those three.

Quoted 7 lines
Quoted 2 lines

Would you like to see all conversations, or just ones related to code (and,

of course, KVM relevant items)

I guess internal vbus changes won't be too interesting for most readers, but new releases, benchmarks, and kvm-related stuff will be welcome on the kvm list.

Ok, I was planning on that anyway.

Regards,
-Greg

#44 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 10 lines · Gregory Haskins
Quoted 3 lines

(though still rooting for virtio).

Heh...not to belabor the point to death, but virtio is orthogonal (you keep forgetting that ;).

Its really the vbus device-model vs the qemu device-model (and possibly vs the "in-kernel pci emulation" model that I believe Michael is working on).

You can run virtio on any of those three.

It's not orthogonal. virtio is one set of ABI+guest drivers+host support to get networking on kvm guests. AlacrityVM's vbus-based drivers are another set of ABI+guest drivers+host support to get networking on kvm guests. That makes them competitors (two different ways to do one thing), not orthogonal.

Signature · 1 line
error compiling committee.c: too many arguments to function
#45 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 9:57 AM, in message <[email protected]>, Avi Kivity

Quoted 11 lines · <[email protected]> wrote:
Quoted 5 lines · Gregory Haskins
Quoted 3 lines

(though still rooting for virtio).

Heh...not to belabor the point to death, but virtio is orthogonal (you keep

forgetting that ;).

Quoted 2 lines

Its really the vbus device-model vs the qemu device-model (and possibly vs the

"in-kernel pci emulation" model that I believe Michael is working on).

Quoted 1 line
Quoted 8 lines
Quoted 2 lines

You can run virtio on any of those three.

It's not orthogonal. virtio is one set of ABI+guest drivers+host support to get networking on kvm guests. AlacrityVM's vbus-based drivers are another set of ABI+guest drivers+host support to get networking on kvm guests. That makes them competitors (two different ways to do one thing), not orthogonal.

Thats not accurate, though.

The virtio stack is modular. For instance, with virtio-net, you have

(guest-side)

|--------------------------
| virtio-net
|--------------------------
| virtio-ring
|--------------------------
| virtio-bus
|--------------------------
| virtio-pci
|--------------------------
                      |
                   (pci)
                      |
|--------------------------
| kvm.ko
|--------------------------
| qemu
|--------------------------
| tun-tap
|--------------------------
| netif
|--------------------------
     (host-side)

We can exchange out the "virtio-pci" module like this:

(guest-side)

|--------------------------
| virtio-net
|--------------------------
| virtio-ring
|--------------------------
| virtio-bus
|--------------------------
| virtio-vbus
|--------------------------
| vbus-proxy
|--------------------------
| vbus-connector
|--------------------------
                      |
                   (vbus)
                      |
|--------------------------
| kvm.ko
|--------------------------
| vbus-connector
|--------------------------
| vbus
|--------------------------
| virtio-net-tap (vbus model)
|--------------------------
| netif
|--------------------------
     (host-side)

So virtio-net runs unmodified. What is "competing" here is "virtio-pci" vs "virtio-vbus". Also, venet vs virtio-net are technically competing. But to say "virtio vs vbus" is inaccurate, IMO.

HTH
-Greg

#46 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 33 lines · Gregory Haskins

We can exchange out the "virtio-pci" module like this:

(guest-side)

|--------------------------
| virtio-net
|--------------------------
| virtio-ring
|--------------------------
| virtio-bus
|--------------------------
| virtio-vbus
|--------------------------
| vbus-proxy
|--------------------------
| vbus-connector
|--------------------------
                      |
                   (vbus)
                      |
|--------------------------
| kvm.ko
|--------------------------
| vbus-connector
|--------------------------
| vbus
|--------------------------
| virtio-net-tap (vbus model)
|--------------------------
| netif
|--------------------------
     (host-side)
Quoted 2 lines

So virtio-net runs unmodified. What is "competing" here is "virtio-pci" vs "virtio-vbus". Also, venet vs virtio-net are technically competing. But to say "virtio vs vbus" is inaccurate, IMO.

I think what's confusing everyone is that you are competing on multiple issues:

1. Implementation of bus probing: both vbus and virtio are backed by PCI devices and can be backed by something else (e.g. virtio by lguest or even by vbus).

2. Exchange of metadata: virtio uses a config space, vbus uses devcall to do the same.

3. User data transport: virtio has virtqueues, vbus has shm/ioq.

I think these three are the main differences, and the venet vs. virtio-net question comes down to which interface the drivers use for each aspect. Do you agree with this interpretation?

Now to draw conclusions from each of these is of course highly subjective, but this is how I view it:

1. The bus probing is roughly equivalent, they both work and the virtio method seems to need a little less code but that could be fixed by slimming down the vbus code as I mentioned in my comments on the pci-to-vbus bridge code. However, I would much prefer not to have both of them, and virtio came first.

2. the two methods (devcall/config space) are more or less equivalent and you should be able to implement each one through the other one. The virtio design was driven by making it look similar to PCI, the vbus design was driven by making it easy to implement in a host kernel. I don't care too much about these, as they can probably coexist without causing any trouble. For a (hypothetical) vbus-in-virtio device, a devcall can be a config-set/config-get pair, for a virtio-in-vbus, you can do a config-get and a config-set devcall and be happy. Each could be done in a trivial helper library.

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

	Arnd <><
#47 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 6 lines · Arnd Bergmann

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

The current conjecture is that ioq outperforms virtio because the host side of ioq is implemented in the host kernel, while the host side of virtio is implemented in userspace. AFAIK, no one pointed out differences in the protocol which explain the differences in performance.

Signature · 1 line
error compiling committee.c: too many arguments to function
#48 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 11:50 AM, in message <[email protected]>, Avi Kivity

Quoted 8 lines · <[email protected]> wrote:
Quoted 6 lines · Arnd Bergmann

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

Quoted 4 lines

The current conjecture is that ioq outperforms virtio because the host side of ioq is implemented in the host kernel, while the host side of virtio is implemented in userspace. AFAIK, no one pointed out differences in the protocol which explain the differences in performance.

There *are* protocol difference that matter, though I think they are slowly being addressed.

For an example: Earlier versions of virtio-pci had a single interrupt for all ring events, and you had to do an extra MMIO cycle to learn the proper context. That will hurt...a _lot_ especially for latency. I think recent versions of KVM switched to MSI-X per queue which fixed this particular ugly.

However, generally I think Avi is right. The main reason why it outperforms virtio-pci by such a large margin has more to do with all the various inefficiencies in the backend (such as requiring multiple hops U->K, K->U per packet), coarse locking, lack of parallel processing, etc. I went through and streamlined all the bottlenecks (such as putting the code in the kernel, reducing locking/context switches, etc).

I have every reason to believe that someone will skills/time equal to myself could develop a virtio-based backend that does not use vbus and achieve similar numbers. However, as stated in my last reply, I am interested in this backend supporting more than KVM, and I designed vbus to fill that role. Therefore, it does not interest me to endeavor such an effort if it doesn't involve a backend that is independent of KVM.

Based on this, I will continue my efforts surrounding to use of vbus including its use to accelerate KVM for AlacrityVM. If I can find a way to do this in such a way that KVM upstream finds acceptable, I would be very happy and will work towards whatever that compromise might be. OTOH, if the KVM community is set against the concept of a generalized/shared backend, and thus wants to use some other approach that does not involve vbus, that is fine too. Choice is one of the great assets of open source, eh? :)

Kind Regards,
-Greg

#49 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 2 lines · Gregory Haskins

Based on this, I will continue my efforts surrounding to use of vbus including its use to accelerate KVM for AlacrityVM. If I can find a way to do this in such a way that KVM upstream finds acceptable, I would be very happy and will work towards whatever that compromise might be. OTOH, if the KVM community is set against the concept of a generalized/shared backend, and thus wants to use some other approach that does not involve vbus, that is fine too. Choice is one of the great assets of open source, eh? :)

KVM upstream (me) doesn't have much say regarding vbus. I am not a networking expert and I'm not the virtio or networking stack maintainer, so I'm not qualified to accept or reject the code. What I am able to do is make sure that kvm can efficiently work with any driver/device stack; this is why ioeventfd/irqfd were merged.

I still think vbus is a duplication of effort; I understand vbus has larger scope than virtio, but I still think these problems could have been solved within the existing virtio stack.

Signature · 1 line
error compiling committee.c: too many arguments to function
#50 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Arnd Bergmann
Quoted 7 lines · Arnd Bergmann

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

	Arnd <><

The fact that it's in kernel also likely contributes.

Signature · 1 line
MST
#51 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

How hard would it be to implement virtio over vbus and perhaps the virtio-net backend?

This would leave only one variable in the comparison, clear misconceptions and make evaluation easier by judging each of vbus, venet etc separately on its own merits.

The way things are now, it is unclear exactly where those performance improvements are coming from (or how much each component contributes) because there are too many variables.

Replacing virtio-net by venet would be a hard proposition if only because virtio-net has (closed source) windows drivers available. There has to be shown that venet by itself does something significantly better that virtio-net can't be modified to do comparably well.

Having venet in addition to virtio-net is also difficult, given that having only one set of paravirtual drivers in the kernel was the whole point behind virtio.

Just a user's 0.02,
Pantelis

#52 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

[not sure if it was intentional, but you dropped the CC list. Therefore, I didn't see this until I caught up on my kvm@vger reading]

Quoted 2 lines · Pantelis Koukousoulas

How hard would it be to implement virtio over vbus and perhaps the virtio-net backend?

It should be relatively trivial. I have already written the transport (called virtio-vbus) that would allow the existing front-end (virtio-net) to work without modification.

http://lkml.org/lkml/2009/4/21/427

All that is needed is to take venet-tap as an example and port it to something virtio compatible (via that patch I posted) on the backend. I have proposed this as an alternative to venet, but so far I have not had any takers to help with this effort. Likewise, I am too busy with the infrastructure to take this on myself.

Quoted 5 lines

This would leave only one variable in the comparison, clear misconceptions and make evaluation easier by judging each of vbus, venet etc separately on its own merits.

Quoted 8 lines

The way things are now, it is unclear exactly where those performance improvements are coming from (or how much each component contributes) because there are too many variables.

Replacing virtio-net by venet would be a hard proposition if only because virtio-net has (closed source) windows drivers available. There has to be shown that venet by itself does something significantly better that virtio-net can't be modified to do comparably well.

I am not proposing anyone replace virtio-net. It will continue to work fine despite the existence of an alternative, and KVM can continue to standardize on it if that is what KVM wants to do.

Quoted 3 lines

Having venet in addition to virtio-net is also difficult, given that having only one set of paravirtual drivers in the kernel was the whole point behind virtio.

As it stands right now, virtio-net fails to meet my performance goals, and venet meets them (or at least, gets much closer, but I will not rest..). So, at least for AlacrityVM, I will continue to use and promote it when performance matters. If at some time in the future I can get virtio-net to work in my environment in a comparable and satisfactory way, I will consider migrating to it and deprecating venet.

Until then, having two drivers is ok, and no-one has to use the one they don't like. I certainly do not think having more than one driver that speaks 802.x ethernet in the kernel tree is without precedent. ;)

Kind Regards,
-Greg

#53 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Arnd Bergmann
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 11:40 AM, in message <[email protected]>, Arnd

Quoted 40 lines · Bergmann
Quoted 33 lines · Gregory Haskins

We can exchange out the "virtio-pci" module like this:

(guest-side)

|--------------------------
| virtio-net
|--------------------------
| virtio-ring
|--------------------------
| virtio-bus
|--------------------------
| virtio-vbus
|--------------------------
| vbus-proxy
|--------------------------
| vbus-connector
|--------------------------
                      |
                   (vbus)
                      |
|--------------------------
| kvm.ko
|--------------------------
| vbus-connector
|--------------------------
| vbus
|--------------------------
| virtio-net-tap (vbus model)
|--------------------------
| netif
|--------------------------
     (host-side)
Quoted 1 line

So virtio-net runs unmodified. What is "competing" here is "virtio-pci" vs

"virtio-vbus".

Quoted 1 line

Also, venet vs virtio-net are technically competing. But to say "virtio vs

vbus" is inaccurate, IMO.

Quoted 6 lines

I think what's confusing everyone is that you are competing on multiple issues:

1. Implementation of bus probing: both vbus and virtio are backed by PCI devices and can be backed by something else (e.g. virtio by lguest or even by vbus).

More specifically, vbus-proxy and virtio-bus can be backed by modular adapters.

vbus-proxy can be backed by vbus-pcibridge (as it is in AlacrityVM). It was backed by KVM-hypercalls in previous releases, but we have deprecated/dropped that connector. Other types of connectors are possible...

virtio-bus can be backed by virtio-pci, virtio-lguest, virtio-s390, and virtio-vbus (which is backed by vbus-proxy, et. al.)

"vbus" itself is actually the host-side container technology which vbus-proxy connects to. This is an important distinction.

Quoted 3 lines

2. Exchange of metadata: virtio uses a config space, vbus uses devcall to do the same.

Sort of. You can use devcall() to implement something like config-space (and in fact, we do use it like this for some operations). But this can also be fast path (for when you need synchronous behavior).

This has various uses, such as when you need synchronous updates from non-preemptible guest code (cpupri, for instance, for -rt)

Quoted 2 lines

3. User data transport: virtio has virtqueues, vbus has shm/ioq.

Not quite: vbus has shm + shm-signal. You can then overlay shared-memory protocols over that, such as virtqueues, ioq, or even non-ring constructs.

I also consider the synchronous call() method to be part of the transport (tho more for niche devices, like -rt)

Quoted 14 lines

I think these three are the main differences, and the venet vs. virtio-net question comes down to which interface the drivers use for each aspect. Do you agree with this interpretation?

Now to draw conclusions from each of these is of course highly subjective, but this is how I view it:

1. The bus probing is roughly equivalent, they both work and the virtio method seems to need a little less code but that could be fixed by slimming down the vbus code as I mentioned in my comments on the pci-to-vbus bridge code. However, I would much prefer not to have both of them, and virtio came first.

Quoted 9 lines

2. the two methods (devcall/config space) are more or less equivalent and you should be able to implement each one through the other one. The virtio design was driven by making it look similar to PCI, the vbus design was driven by making it easy to implement in a host kernel. I don't care too much about these, as they can probably coexist without causing any trouble. For a (hypothetical) vbus-in-virtio device, a devcall can be a config-set/config-get pair, for a virtio-in-vbus, you can do a config-get and a config-set devcall and be happy. Each could be done in a trivial helper library.

Yep, in fact I publish something close to what I think you are talking about back in April

http://lkml.org/lkml/2009/4/21/427

Quoted 6 lines

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

While I appreciate the sentiment, I doubt that is actually whats helping here.

There are a variety of factors that I poured into venet/vbus that I think contribute to its superior performance. However, the difference in the ring design I do not think is one if them. In fact, in many ways I think Rusty's design might turn out to be faster if put side by side because he was much more careful with cacheline alignment than I was. Also note that I was careful to not pick one ring vs the other ;) They both should work.

IMO, we are only looking at the tip of the iceberg when looking at this purely as the difference between virtio-pci vs virtio-vbus, or venet vs virtio-net.

Really, the big thing I am working on here is the host side device-model. The idea here was to design a bus model that was conducive to high performance, software to software IO that would work in a variety of environments (that may or may not have PCI). KVM is one such environment, but I also have people looking at building other types of containers, and even physical systems (host+blade kind of setups).

The idea is that the "connector" is modular, and then something like virtio-net or venet "just work": in kvm, in the userspace container, on the blade system.

It provides a management infrastructure that (hopefully) makes sense for these different types of containers, regardless of whether they have PCI, QEMU, etc (e.g. things that are inherent to KVM, but not others).

I hope this helps to clarify the project :)

Kind Regards,
-Greg

#54 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 3 lines · Gregory Haskins
Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 11:40 AM, in message <[email protected]>, Arnd

Quoted 1 line · Bergmann

On Thursday 06 August 2009, Gregory Haskins wrote:

[ big snip ]

Quoted 10 lines
Quoted 6 lines

3. The ioq method seems to be the real core of your work that makes venet perform better than virtio-net with its virtqueues. I don't see any reason to doubt that your claim is correct. My conclusion from this would be to add support for ioq to virtio devices, alongside virtqueues, but to leave out the extra bus_type and probing method.

While I appreciate the sentiment, I doubt that is actually whats helping here.

There are a variety of factors that I poured into venet/vbus that I think contribute to its superior performance. However, the difference in the ring design I do not think is one if them. In fact, in many ways I think Rusty's design might turn out to be faster if put side by side because he was much more careful with cacheline alignment than I was. Also note that I was careful to not pick one ring vs the other ;) They both should work.

IMO, the virtio vring design is very well thought out. I found it relatively easy to port to a host+blade setup, and run virtio-net over a physical PCI bus, connecting two physical CPUs.

Quoted 11 lines

IMO, we are only looking at the tip of the iceberg when looking at this purely as the difference between virtio-pci vs virtio-vbus, or venet vs virtio-net.

Really, the big thing I am working on here is the host side device-model. The idea here was to design a bus model that was conducive to high performance, software to software IO that would work in a variety of environments (that may or may not have PCI). KVM is one such environment, but I also have people looking at building other types of containers, and even physical systems (host+blade kind of setups).

The idea is that the "connector" is modular, and then something like virtio-net or venet "just work": in kvm, in the userspace container, on the blade system.

It provides a management infrastructure that (hopefully) makes sense for these different types of containers, regardless of whether they have PCI, QEMU, etc (e.g. things that are inherent to KVM, but not others).

I hope this helps to clarify the project :)

I think this is the major benefit of vbus. I've only started studying the vbus code, so I don't have lots to say yet. The overview of the management interface makes it look pretty good.

Getting two virtio-net drivers hooked together in my virtio-over-PCI patches was nasty. If you read the thread that followed, you'll see the lack of a management interface as a concern of mine. It was basically decided that it could come "later". The configfs interface vbus provides is pretty nice, IMO.

Just my two cents,
Ira

#55 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Gregory Haskins
Quoted 3 lines · Gregory Haskins
Quoted 1 line

(though still rooting for virtio).

Heh...not to belabor the point to death, but virtio is orthogonal (you keep forgetting that ;).

venet and virtio aren't orthogonal, are they?

Signature · 1 line
MST
#56 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

Quoted 1 line
Quoted 1 line
Quoted 1 line

On 8/6/2009 at 9:59 AM, in message <[email protected]>,

Quoted 7 lines · Michael S. Tsirkin
Quoted 3 lines · Gregory Haskins
Quoted 1 line

(though still rooting for virtio).

Heh...not to belabor the point to death, but virtio is orthogonal (you keep

forgetting that ;).

venet and virtio aren't orthogonal, are they?

See my last reply to Avi.

Regards,
-Greg

#57 lore raw

Re: [PATCH 0/7] AlacrityVM guest drivers Reply-To:

In reply to Michael S. Tsirkin
Quoted 7 lines · Michael S. Tsirkin
Quoted 4 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

The graphs comparing virtio with vbus look interesting.

1gbit throughput on a 10gbit link? I have a hard time believing that.

I've seen much higher myself. Can you describe your test setup in more detail?

Regards,

Anthony Liguori

#58 lore raw
Quoted 6 lines · Anthony Liguori
Quoted 5 lines · Michael S. Tsirkin
Quoted 4 lines

This series includes the basic plumbing, as well as the driver for accelerated 802.x (ethernet) networking.

Quoted 7 lines
Quoted 2 lines

The graphs comparing virtio with vbus look interesting.

1gbit throughput on a 10gbit link? I have a hard time believing that.

I've seen much higher myself. Can you describe your test setup in more detail?

Sure,

For those graphs, two 8-core x86_64 boxes with Chelsio T3 10GE connected back to back via cross over with 1500mtu. The kernel version was as posted. The qemu version was generally something very close to qemu-kvm.git HEAD at the time the data was gathered, but unfortunately I didn't seem to log this info.

For KVM, we take one of those boxes and run a bridge+tap configuration on top of that. We always run the server on the bare-metal machine on the remote side of the link regardless of whether we run the client in a VM or baremetal.

For guests, virtio-net and venet connect to the same linux bridge instance, I just "ifdown eth0 / ifup eth1" (or vice versa) and repeat the same test. I do this multiple times (usually about 10) and average the result. I use several different programs, such as netperf, rsync, and ping to take measurements.

That said, note that the graphs were from earlier kernel runs (2.6.28, 29-rc8). The most recent data I can find that I published is for 2.6.29, announced with the vbus-v3 release back in April:

http://lkml.org/lkml/2009/4/21/408

In it, the virtio-net throughput numbers are substantially higher and possibly more in line with your expectations (4.5gb/s) (though notably still lagging venet, which weighed in at 5.6gb/s).

Generally, I find that the virtio-net exhibits non-deterministic results from release to release. I suspect (as we have discussed) the tx-mitigation scheme. Some releases buffer the daylights out of the stream, and virtio gets close(r) throughput (e.g. 4.5g vs 5.8g, but absolutely terrible latency (4000us vs 65us). Other releases it seems to operate with more of a compromise (1.3gb/s vs 3.8gb/s, but 350us vs 85us).

I do not understand what causes the virtio performance fluctuation, as I use the same kernel config across builds, and I do not typically change the qemu userspace. Note that some general fluctuation is evident across the board just from kernel to kernel. I am referring to more of the disparity in throughput vs latency than the ultimate numbers, as all targets seem to scale max throughput about the same per kernel.

That said, I know I need to redo the graphs against HEAD (31-rc5, and perhaps 30, and kvm.git). I've been heads down with the eventfd interfaces since vbus-v3 so I havent been as active with generating the results. I did confirm that vbus-v4 (alacrityvm-v0.1) still produces a similar graph, but I didn't gather the data as scientifically as I would feel comfortable publishing a graph for. This is on the TODO list.

If there is another patch-series/tree I should be using for comparison, please point me at it.

HTH

Kind Regards,
-Greg

#59 lore raw
Quoted 10 lines · Gregory Haskins

That said, note that the graphs were from earlier kernel runs (2.6.28, 29-rc8). The most recent data I can find that I published is for 2.6.29, announced with the vbus-v3 release back in April:

http://lkml.org/lkml/2009/4/21/408

In it, the virtio-net throughput numbers are substantially higher and possibly more in line with your expectations (4.5gb/s) (though notably still lagging venet, which weighed in at 5.6gb/s).

Okay, that makes more sense. Would be nice to update the graphs as they make virtio look really, really bad :-)

Quoted 8 lines

Generally, I find that the virtio-net exhibits non-deterministic results from release to release. I suspect (as we have discussed) the tx-mitigation scheme. Some releases buffer the daylights out of the stream, and virtio gets close(r) throughput (e.g. 4.5g vs 5.8g, but absolutely terrible latency (4000us vs 65us). Other releases it seems to operate with more of a compromise (1.3gb/s vs 3.8gb/s, but 350us vs 85us).

Are you using kvm modules or a new kernel? There was some timer infrastructure changes around 28/29 and it's possible that the system your on is now detecting an hpet which will result in a better time source. That could have an affect on mitigation.

Quoted 3 lines

If there is another patch-series/tree I should be using for comparison, please point me at it.

No, I think it's fair to look at upstream Linux. Looking at the latest bits would be nice though because there are some virtio friendly changes recently like MSI-x and GRO.

Since you're using the latest vbus bits, it makes sense to compare against the latest virtio bits.

Regards,

Anthony Liguori

#60 lore raw
Quoted 7 lines · Anthony Liguori
Quoted 6 lines · Gregory Haskins

That said, note that the graphs were from earlier kernel runs (2.6.28, 29-rc8). The most recent data I can find that I published is for 2.6.29, announced with the vbus-v3 release back in April:

http://lkml.org/lkml/2009/4/21/408

Quoted 7 lines
Quoted 4 lines

In it, the virtio-net throughput numbers are substantially higher and possibly more in line with your expectations (4.5gb/s) (though notably still lagging venet, which weighed in at 5.6gb/s).

Okay, that makes more sense. Would be nice to update the graphs as they make virtio look really, really bad :-)

Yeah, they are certainly ripe for an update. (Note that I was unilaterally stale on venet numbers, too) ;)

Quoted 11 lines
Quoted 9 lines

Generally, I find that the virtio-net exhibits non-deterministic results from release to release. I suspect (as we have discussed) the tx-mitigation scheme. Some releases buffer the daylights out of the stream, and virtio gets close(r) throughput (e.g. 4.5g vs 5.8g, but absolutely terrible latency (4000us vs 65us). Other releases it seems to operate with more of a compromise (1.3gb/s vs 3.8gb/s, but 350us vs 85us).

Are you using kvm modules or a new kernel?

I just build the entire kernel from git.

Quoted 4 lines

There was some timer
infrastructure changes around 28/29 and it's possible that the system your on is now detecting an hpet which will result in a better time source. That could have an affect on mitigation.

Yeah, I suspect you are right. I always kept the .config and machine constant, but I *do* bounce around kernel versions so perhaps I got hosed by a make-oldconfig cycle somewhere along the way.

Quoted 8 lines
Quoted 4 lines

If there is another patch-series/tree I should be using for comparison, please point me at it.

No, I think it's fair to look at upstream Linux. Looking at the latest bits would be nice though because there are some virtio friendly changes recently like MSI-x and GRO.

Yeah, I will definitely include kvm.git in addition to whatever is current from Linus. I already have adopted using the latest qemu-kvm.git into my workflow.

Regards,
-Greg