virtual-bus
Subsystems (13)
v3 cover virtual-bus
RFC: Virtual-Bus (applies to v2.6.30-rc2)
----------------------
Virtual-Bus is a Linux-kernel based virtual IO resource container technology. It allows you to declare virtualized device models directly within a host kernel that can be uniformly accessed from a variety of environments, such as KVM, userspace, lguest, Xen, etc. The goal is to reduce overhead while still preserving proper isolation to achieve maximum throughput and latency from your IO subsystem. It is installed on the host and configured using simple filesystem operations like "mkdir" to create a new container, "ln -s" to associate a device with a container, and "echo" to configure the device thanks to integration with configfs/sysfs. Therefore, managing a virtual-bus does not require special userspace tools.
Why would we want this?
----------------------
We believe that a combination of in-kernel models, coupled with optimizations in various areas such as reducing the number of context switches and executing the algorithms in parallel on modern multicore CPUs will result in the best possible IO performance for technologies such as virtualization. This facility aims to provide the framework for building such constructs in in software in the most efficient way we believe is possible.
Preliminary Results:
-----------------------
As a test, we wrote a virtual-ethernet backend and a Linux driver (called venet) and tested the setup with v2.6.29 on two 8-core x86_64 boxes with Chelsio T3 10GE connected back to back via cross over. We measured bare-metal performance, as well as a kvm guest (running the same kernel) connected to the T3 via a linux-bridge+tap configuration with a 1500 MTU. The results are as follows:
Bare metal : tput = 4078Mb/s, round-trip = 25593pps (39us rtt)
Virtio-net (PCI) : tput = 4003Mb/s, round-trip = 320pps (3125us rtt)
Venet (VBUS): tput = 4050Mb/s, round-trip = 15255 (65us rtt)
When we jump to 9000 byte MTU, the situation looks similar
Bare metal : tput = 9717Mb/s, round-trip = 30396pps (33us rtt)
Virtio-net (PCI) : tput = 4578Mb/s, round-trip = 249pps (4016us rtt)
Venet (VBUS): tput = 5802Mb/s, round-trip = 15127 (66us rtt)
Note that to be fair, part of the latency response from virtio-pci is due to the way that the driver/backend coalesces packets, and not a true limitation of the userspace path as the results may imply. Anthony Liguori is already looking into improving this based on the results we presented here, and is making good headway.
Also note that as of v2, we support a virtio-vbus transport, and therefore will soon be able to compare "Virtio-net (VBUS)" as an additional target in the near future once we have developed a virtio-net backend for the host. This virtio-net(pci) to virtio-net(vbus) comparison is probably more interesting than comparing to Venet as it would be more apples to apples. Also it would be nice to only need one PV driver per IO subsystem in the long term.
Changes v2->v3:
------------------
*) VBUS now renders as a PCI/MSI device instead of via cpuid/dynirq *) Dropped dynirq (replaced with MSI facility)
*) Dropped "reset" patch in favor of more reliably detecting reset via BUSOPEN *) Incorporated more review feedback from Stephen Hemminger on vbus-enet
driver
*) Added support for setting the guests MAC during host config (Pat Mullaney) *) Cleaned up documentation per feedback from Ben Hutchings
*) Numerous small tweaks to clean up things like warnings, comments, etc.
(Alex Tsariounov, Greg Haskins)
*) Fixed Kconfig dependency problem with virtio-vbus with feedback from
Peter Morreale.
Changes v1->v2:
*) Incorporated review feedback from Stephen Hemminger on vbus-enet driver *) Added support for connecting to vbus devices from userspace *) Added support for a virtio-vbus transport to allow virtio drivers to
work with vbus (needs testing and backend models).
Todo:
*) Beef up the userspace event channel ABI to support different event types *) Add memory-registration support
*) Develop some virtio backend devices.
*) Support ethtool_ops for venet.
*) Convert from MSI to MSIX to truely support multiple vectors
---------------------------------------
For more details, please see our Wiki at
http://developer.novell.com/wiki/index.php/Virtual-bus
---
Gregory Haskins (16):
virtio: add a vbus transport
vbus: add a userspace connector
kvm: Add guest-side support for VBUS
kvm: Add VBUS support to the host
venettap: add scatter-gather support
venet: add scatter-gather support
venet-tap: Adds a "venet" compatible "tap" device to VBUS
net: Add vbus_enet driver
venet: add the ABI definitions for an 802.x packet interface
ioq: add vbus helpers
ioq: Add basic definitions for a shared-memory, lockless queue
vbus: add a "vbus-proxy" bus model for vbus_driver objects
vbus: add bus-registration notifiers
vbus: add connection-client helper infrastructure
vbus: add virtual-bus definitions
shm-signal: shared-memory signals
Patrick Mullaney (1):
venet-tap: add the ability to set the client's mac address via sysfs
Documentation/vbus.txt | 385 +++++++++ arch/x86/Kconfig | 11 arch/x86/include/asm/kvm_para.h | 1 arch/x86/kvm/Kconfig | 9 arch/x86/kvm/Makefile | 3 arch/x86/kvm/x86.c | 6 arch/x86/kvm/x86.h | 12 drivers/Makefile | 2 drivers/net/Kconfig | 13 drivers/net/Makefile | 1 drivers/net/vbus-enet.c | 898 +++++++++++++++++++++ drivers/vbus/devices/Kconfig | 17 drivers/vbus/devices/Makefile | 1 drivers/vbus/devices/venet-tap.c | 1641 ++++++++++++++++++++++++++++++++++++++ drivers/vbus/proxy/Makefile | 2 drivers/vbus/proxy/kvm.c | 751 +++++++++++++++++ drivers/virtio/Kconfig | 15 drivers/virtio/Makefile | 1 drivers/virtio/virtio_vbus.c | 496 +++++++++++ fs/proc/base.c | 96 ++ include/linux/ioq.h | 410 +++++++++ include/linux/kvm.h | 7 include/linux/kvm_host.h | 26 + include/linux/kvm_para.h | 58 + include/linux/sched.h | 4 include/linux/shm_signal.h | 188 ++++ include/linux/vbus.h | 166 ++++ include/linux/vbus_client.h | 115 +++ include/linux/vbus_device.h | 424 ++++++++++ include/linux/vbus_driver.h | 80 ++ include/linux/vbus_userspace.h | 48 + include/linux/venet.h | 82 ++ include/linux/virtio_vbus.h | 163 ++++ kernel/Makefile | 1 kernel/exit.c | 2 kernel/fork.c | 2 kernel/vbus/Kconfig | 56 + kernel/vbus/Makefile | 11 kernel/vbus/attribute.c | 52 + kernel/vbus/client.c | 543 +++++++++++++ kernel/vbus/config.c | 275 ++++++ kernel/vbus/core.c | 626 ++++++++++++++ kernel/vbus/devclass.c | 124 +++ kernel/vbus/map.c | 72 ++ kernel/vbus/map.h | 41 + kernel/vbus/proxy.c | 216 +++++ kernel/vbus/shm-ioq.c | 89 ++ kernel/vbus/userspace-client.c | 485 +++++++++++ kernel/vbus/vbus.h | 117 +++ kernel/vbus/virtio.c | 627 +++++++++++++++ lib/Kconfig | 21 lib/Makefile | 2 lib/ioq.c | 298 +++++++ lib/shm_signal.c | 186 ++++ virt/kvm/kvm_main.c | 10 virt/kvm/vbus.c | 1392 ++++++++++++++++++++++++++++++++ 56 files changed, 11380 insertions(+), 0 deletions(-) create mode 100644 Documentation/vbus.txt create mode 100644 drivers/net/vbus-enet.c create mode 100644 drivers/vbus/devices/Kconfig create mode 100644 drivers/vbus/devices/Makefile create mode 100644 drivers/vbus/devices/venet-tap.c create mode 100644 drivers/vbus/proxy/Makefile create mode 100644 drivers/vbus/proxy/kvm.c create mode 100644 drivers/virtio/virtio_vbus.c create mode 100644 include/linux/ioq.h create mode 100644 include/linux/shm_signal.h create mode 100644 include/linux/vbus.h create mode 100644 include/linux/vbus_client.h create mode 100644 include/linux/vbus_device.h create mode 100644 include/linux/vbus_driver.h create mode 100644 include/linux/vbus_userspace.h create mode 100644 include/linux/venet.h create mode 100644 include/linux/virtio_vbus.h create mode 100644 kernel/vbus/Kconfig create mode 100644 kernel/vbus/Makefile create mode 100644 kernel/vbus/attribute.c create mode 100644 kernel/vbus/client.c create mode 100644 kernel/vbus/config.c create mode 100644 kernel/vbus/core.c create mode 100644 kernel/vbus/devclass.c create mode 100644 kernel/vbus/map.c create mode 100644 kernel/vbus/map.h create mode 100644 kernel/vbus/proxy.c create mode 100644 kernel/vbus/shm-ioq.c create mode 100644 kernel/vbus/userspace-client.c create mode 100644 kernel/vbus/vbus.h create mode 100644 kernel/vbus/virtio.c create mode 100644 lib/ioq.c create mode 100644 lib/shm_signal.c create mode 100644 virt/kvm/vbus.c
RFC PATCH v3 1/17 shm-signal: shared-memory signals
This interface provides a bidirectional shared-memory based signaling mechanism. It can be used by any entities which desire efficient communication via shared memory. The implementation details of the signaling are abstracted so that they may transcend a wide variety of locale boundaries (e.g. userspace/kernel, guest/host, etc).
The shm_signal mechanism supports event masking as well as spurious event delivery mitigation.
---
include/linux/shm_signal.h | 188 ++++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig | 9 ++ lib/Makefile | 1 lib/shm_signal.c | 186 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 384 insertions(+), 0 deletions(-) create mode 100644 include/linux/shm_signal.h create mode 100644 lib/shm_signal.c
include/linux/shm_signal.h new file +188 -0
@@ -0,0 +1,188 @@ +/* +* Copyright 2009 Novell. All Rights Reserved. +* +* Author: +* Gregory Haskins <[email protected]> +* +* This file is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINUX_SHM_SIGNAL_H +#define _LINUX_SHM_SIGNAL_H + +#include <asm/types.h> + +/* +*--------- +* The following structures represent data that is shared across boundaries +* which may be quite disparate from one another (e.g. Windows vs Linux, +* 32 vs 64 bit, etc). Therefore, care has been taken to make sure they +* present data in a manner that is independent of the environment. +*----------- +*/ + +#define SHM_SIGNAL_MAGIC 0x58fa39df +#define SHM_SIGNAL_VER 1 + +struct shm_signal_irq { +__u8 enabled; +__u8 pending; +__u8 dirty; +}; + +enum shm_signal_locality { + shm_locality_north, + shm_locality_south, +}; + +struct shm_signal_desc { +__u32 magic; +__u32 ver; +struct shm_signal_irq irq[2 ]; +}; + +/* --- END SHARED STRUCTURES --- */ + +#ifdef __KERNEL__ + +#include <linux/interrupt.h> + +struct shm_signal_notifier { +void (*signal)(struct shm_signal_notifier *); +}; + +struct shm_signal ; + +struct shm_signal_ops { +int (*inject)(struct shm_signal *s); +void (*fault)(struct shm_signal *s,const char *fmt, ...); +void (*release)(struct shm_signal *s); +}; + +enum { + shm_signal_in_wakeup, +}; + +struct shm_signal { +atomic_t refs; +spinlock_t lock; +enum shm_signal_locality locale; +unsigned long flags; +struct shm_signal_ops *ops; +struct shm_signal_desc *desc; +struct shm_signal_notifier *notifier; +struct tasklet_struct deferred_notify; +}; + +#define SHM_SIGNAL_FAULT(s, fmt, args...) \ + ((s)->ops->fault ? (s)->ops->fault((s), fmt, ## args) : panic(fmt, ## args)) + +/* +* These functions should only be used internally +*/ +void _shm_signal_release (struct shm_signal *s); +void _shm_signal_wakeup (struct shm_signal *s); + +/** +* shm_signal_init() - initialize an SHM_SIGNAL +* @s: SHM_SIGNAL context +* +* Initializes SHM_SIGNAL context before first use +* +**/ +void shm_signal_init (struct shm_signal *s); + +/** +* shm_signal_get() - acquire an SHM_SIGNAL context reference +* @s: SHM_SIGNAL context +* +**/ +static inline struct shm_signal *shm_signal_get (struct shm_signal *s) +{ +atomic_inc (&s->refs); + +return s; +} + +/** +* shm_signal_put() - release an SHM_SIGNAL context reference +* @s: SHM_SIGNAL context +* +**/ +static inline void shm_signal_put (struct shm_signal *s) +{ +if (atomic_dec_and_test (&s->refs)) +_shm_signal_release (s); +} + +/** +* shm_signal_enable() - enables local notifications on an SHM_SIGNAL +* @s: SHM_SIGNAL context +* @flags: Reserved for future use, must be 0 +* +* Enables/unmasks the registered notifier (if applicable) to receive wakeups +* whenever the remote side performs an shm_signal() operation. A notification +* will be dispatched immediately if any pending signals have already been +* issued prior to invoking this call. +* +* This is synonymous with unmasking an interrupt. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int shm_signal_enable (struct shm_signal *s,int flags); + +/** +* shm_signal_disable() - disable local notifications on an SHM_SIGNAL +* @s: SHM_SIGNAL context +* @flags: Reserved for future use, must be 0 +* +* Disables/masks the registered shm_signal_notifier (if applicable) from +* receiving any further notifications. Any subsequent calls to shm_signal() +* by the remote side will update the shm as dirty, but will not traverse the +* locale boundary and will not invoke the notifier callback. Signals +* delivered while masked will be deferred until shm_signal_enable() is +* invoked. +* +* This is synonymous with masking an interrupt +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int shm_signal_disable (struct shm_signal *s,int flags); + +/** +* shm_signal_inject() - notify the remote side about shm changes +* @s: SHM_SIGNAL context +* @flags: Reserved for future use, must be 0 +* +* Marks the shm state as "dirty" and, if enabled, will traverse +* a locale boundary to inject a remote notification. The remote +* side controls whether the notification should be delivered via +* the shm_signal_enable/disable() interface. +* +* The specifics of how to traverse a locale boundary are abstracted +* by the shm_signal_ops->signal() interface and provided by a particular +* implementation. However, typically going north to south would be +* something like a syscall/hypercall, and going south to north would be +* something like a posix-signal/guest-interrupt. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int shm_signal_inject (struct shm_signal *s,int flags); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_SHM_SIGNAL_H */
lib/Kconfig +9 -0
@@ -191,4 +191,13 @@ config DISABLE_OBSOLETE_CPUMASK_FUNCTIONS config NLATTR bool +config SHM_SIGNAL + boolean "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
@@ -75,6 +75,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 +186 -0
186 lines not on this page · raw message
RFC PATCH v3 2/17 vbus: add virtual-bus definitions
In reply to Gregory HaskinsSee Documentation/vbus.txt for details
---
Documentation/vbus.txt | 385 +++++++++++++++++++++++++++++ arch/x86/Kconfig | 2 fs/proc/base.c | 96 +++++++ include/linux/sched.h | 4 include/linux/vbus.h | 147 +++++++++++ include/linux/vbus_device.h | 417 ++++++++++++++++++++++++++++++++ kernel/Makefile | 1 kernel/exit.c | 2 kernel/fork.c | 2 kernel/vbus/Kconfig | 14 + kernel/vbus/Makefile | 1 kernel/vbus/attribute.c | 52 ++++ kernel/vbus/config.c | 275 +++++++++++++++++++++ kernel/vbus/core.c | 567 +++++++++++++++++++++++++++++++++++++++++++ kernel/vbus/devclass.c | 124 +++++++++ kernel/vbus/map.c | 72 +++++ kernel/vbus/map.h | 41 +++ kernel/vbus/vbus.h | 116 +++++++++ 18 files changed, 2318 insertions(+), 0 deletions(-) create mode 100644 Documentation/vbus.txt create mode 100644 include/linux/vbus.h create mode 100644 include/linux/vbus_device.h create mode 100644 kernel/vbus/Kconfig create mode 100644 kernel/vbus/Makefile create mode 100644 kernel/vbus/attribute.c create mode 100644 kernel/vbus/config.c create mode 100644 kernel/vbus/core.c create mode 100644 kernel/vbus/devclass.c create mode 100644 kernel/vbus/map.c create mode 100644 kernel/vbus/map.h create mode 100644 kernel/vbus/vbus.h
Documentation/vbus.txt new file +385 -0
@@ -0,0 +1,385 @@ + +Virtual-Bus: +====================== +Author: Gregory Haskins <[email protected]> + + + + +What is it? +-------------------- + +Virtual-Bus is a kernel based IO resource container technology. It is modeled +on a concept similar to the Linux Device-Model (LDM), where we have buses, +devices, and drivers as the primary actors. However, VBUS has several +distinctions when contrasted with LDM: + + 1) "Busses" in LDM are relatively static and global to the kernel (e.g. + "PCI", "USB", etc). VBUS buses are arbitrarily created and destroyed + dynamically, and are not globally visible. Instead they are defined as + visible only to a specific subset of the system (the contained context). + 2) "Devices" in LDM are typically tangible physical (or sometimes logical) + devices. VBUS devices are purely software abstractions (which may or + may not have one or more physical devices behind them). Devices may + also be arbitrarily created or destroyed by software/administrative action + as opposed to by a hardware discovery mechanism. + 3) "Drivers" in LDM sit within the same kernel context as the busses and + devices they interact with. VBUS drivers live in a foreign + context (such as userspace, or a virtual-machine guest). + +The idea is that a vbus is created to contain access to some IO services. +Virtual devices are then instantiated and linked to a bus to grant access to +drivers actively present on the bus. Drivers will only have visibility to +devices present on their respective bus, and nothing else. + +Virtual devices are defined by modules which register a deviceclass with the +system. A deviceclass simply represents a type of device that _may_ be +instantiated into a device, should an administrator wish to do so. Once +this has happened, the device may be associated with one or more buses where +it will become visible to all clients of those respective buses. + +Why do we need this? +---------------------- + +There are various reasons why such a construct may be useful. One of the +most interesting use cases is for virtualization, such as KVM. Hypervisors +today provide virtualized IO resources to a guest, but this is often at a cost +in both latency and throughput compared to bare metal performance. Utilizing +para-virtual resources instead of emulated devices helps to mitigate this +penalty, but even these techniques to date have not fully realized the +potential of the underlying bare-metal hardware. + +Some of the performance differential is unavoidable just given the extra +processing that occurs due to the deeper stack (guest+host). However, some of +this overhead is a direct result of the rather indirect path most hypervisors +use to route IO. For instance, KVM uses PIO faults from the guest to trigger +a guest->host-kernel->host-userspace->host-kernel sequence of events. +Contrast this to a typical userspace application on the host which must only +traverse app->kernel for most IO. + +The fact is that the linux kernel is already great at managing access to IO +resources. Therefore, if you have a hypervisor that is based on the linux +kernel, is there some way that we can allow the hypervisor to manage IO +directly instead of forcing this convoluted path? + +The short answer is: "not yet" ;) + +In order to use such a concept, we need some new facilties. For one, we +need to be able to define containers with their corresponding access-control so +that guests do not have unmitigated access to anything they wish. Second, +we also need to define some forms of memory access that is uniform in the face +of various clients (e.g. "copy_to_user()" cannot be assumed to work for, say, +a KVM vcpu context). Lastly, we need to provide access to these resources in +a way that makes sense for the application, such as asynchronous communication +paths and minimizing context switches. + +So we introduce VBUS as a framework to provide such facilities. The net +result is a *substantial* reduction in IO overhead, even when compared to +state of the art para-virtualization techniques (such as virtio-net). + +How do I use it? +------------------------ + +There are two components to utilizing a virtual-bus. One is the +administrative function (creating and configuring a bus and its devices). The +other is the consumption of the resources on the bus by a client (e.g. a +virtual machine, or a userspace application). The former occurs on the host +kernel by means of interacting with various special filesystems (e.g. sysfs, +configfs, etc). The latter occurs by means of a "vbus connector" which must +be developed specifically to bridge a particular environment. To date, we +have developed such connectors for host-userspace and kvm-guests. Conceivably +we could develop other connectors as needs arise (e.g. lguest, xen, +guest-userspace, etc). This document deals with the administrative interface. +Details about developing a connector are out of scope for this document. + +Interacting with vbus +------------------------ + +The first step is to enable virtual-bus support (CONFIG_VBUS) as well as any +desired vbus-device modules (e.g. CONFIG_VBUS_VENETTAP), and ensure that your +environment mounts both sysfs and configfs somewhere in the filesystem. This +document will assume they are mounted to /sys and /config, respectively. + +VBUS will create a top-level directory "vbus" in each of the two respective +filesystems. At boot-up, they will look like the following: + +/sys/vbus/ +|-- deviceclass +|-- devices +|-- instances +`-- version + +/config/vbus/ +|-- devices +`-- instances + +Following their respective roles, /config/vbus is for userspace to manage the +lifetime of some number of objects/attributes. This is in contrast to +/sys/vbus which is a reflection of objects managed by the kernel. It is +assumed the reader is already familiar with these two facilities, so we will +not go into depth about their general operation. Suffice to say that vbus +consists of objects that are managed both by userspace and the kernel. +Modification of objects via /config/vbus will typically be reflected in the +/sys/vbus area. + +It all starts with a deviceclass +-------------------------------- + +Before you can do anything useful with vbus, you need some registered +deviceclasses. A deviceclass provides the implementation of a specific type +of virtual device. A deviceclass will typically be registered by loading a +kernel-module. Once loaded, the available device types are enumerated under +/sys/vbus/deviceclass. For example, we will load our "venet-tap" module, +which provides network services: + +# modprobe venet-tap +# tree /sys/vbus +/sys/vbus +|-- deviceclass +| `-- venet-tap +|-- devices +|-- instances +`-- version + +An administrative agent should be able to enumerate /sys/vbus/deviceclass to +determine what services are available on a given platform. + +Create the container +------------------- + +The next step is to create a new container. In vbus, this comes in the form +of a vbus-instance and it is created by a simple "mkdir" in the +/config/vbus/instances area. The only requirement is that the instance is +given a host-wide unique name. This may be some kind of association to the +application (e.g. the unique VM GUID) or it can be arbitrary. For the +purposes of example, we will let $(uuidgen) generate a random UUID for us. + +# mkdir /config/vbus/instances/$(uuidgen) +# tree /sys/vbus/ +/sys/vbus/ +|-- deviceclass +| `-- venet-tap +|-- devices +|-- instances +| `-- beb4df8f-7483-4028-b3f7-767512e2a18c +| |-- devices +| `-- members +`-- version + +So we can see that we have now created a vbus called + + "beb4df8f-7483-4028-b3f7-767512e2a18c" + +in the /config area, and it was immediately reflected in the +/sys/vbus/instances area as well (with a few subobjects of its own: "devices" +and "members"). The "devices" object denotes any devices that are present on +the bus (in this case: none). Likewise, "members" denotes the pids of any +tasks that are members of the bus (in this case: none). We will come back to +this later. For now, we move on to the next step + +Create a device instance +------------------------ + +Devices are instantiated by again utilizing the /config/vbus configfs area. +They are represented as root-level objects under /config/vbus/devices as +opposed to bus subordinate objects specifically to allow greater flexibility +in the association of a device. For instance, it may be desirable to have +a single device that spans multiple VMs (consider an ethernet switch, or +a shared disk for a cluster). Therefore, device lifecycles are managed by +creating/deleting objects in /config/vbus/devices. + +Note: Creating a device instance is actually a two step process: We need to +give the device instance a unique name, and we also need to give it a specific +device type. It is hard to express both parameters using standard filesystem +operations like mkdir, so the design decision was made to require performing +the operation in two steps. + +Our first step is to create a unique instance. We will again utilize +$(uuidgen) to yield an arbitrary name. Any name will suffice as long as it is +unqie on this particular host. + +# mkdir /config/vbus/devices/$(uuidgen) +# tree /sys/vbus +/sys/vbus +|-- deviceclass +| `-- venet-tap +|-- devices +| `-- 6a1aff24-5dc0-4aea-9c35-435daef90e55 +| `-- interfaces +|-- instances +| `-- beb4df8f-7483-4028-b3f7-767512e2a18c +| |-- devices +| `-- members +`-- version + +At this point we have created a partial instance, since we have not yet +assigned a type to the device. Even so, we can see that some state has +changed under /sys/vbus/devices. We now have an instance named + + 6a1aff24-5dc0-4aea-9c35-435daef90e55 + +and it has a single subordinate object: "interfaces". This object in +particular is provided by the infrastructure, though do note that a +deviceclass may also provide its own attributes/objects once it is created. + +We will go ahead and give this device a type to complete its construction. We +do this by setting the /config/vbus/devices/$devname/type attribute with a +valid deviceclass type: + +# echo foo > /config/vbus/devices/6a1aff24-5dc0-4aea-9c35-435daef90e55/type +bash: echo: write error: No such file or directory + +Oops! What happened? "foo" is not a valid deviceclass. We need to consult +the /sys/vbus/deviceclass area to find out what our options are: + +# tree /sys/vbus/deviceclass/ +/sys/vbus/deviceclass/ +`-- venet-tap + +Lets try again: + +# echo venet-tap > /config/vbus/devices/6a1aff24-5dc0-4aea-9c35-435daef90e55/type +# tree /sys/vbus/ +/sys/vbus/ +|-- deviceclass +| `-- venet-tap +|-- devices +| `-- 6a1aff24-5dc0-4aea-9c35-435daef90e55 +| |-- class -> ../../deviceclass/venet-tap +| |-- client_mac +| |-- enabled +| |-- host_mac +| |-- ifname +| `-- interfaces +|-- instances +| `-- beb4df8f-7483-4028-b3f7-767512e2a18c +| |-- devices +| `-- members +`-- version + +Ok, that looks better. And note that /sys/vbus/devices now has some more +subordinate objects. Most of those were registered when the venet-tap +deviceclass was given a chance to create an instance of itself. Those +attributes are a property of the venet-tap and therefore are out of scope +for this document. Please see the documentation that accompanies a particular +module for more details. + +Put the device on the bus +------------------------- + +The next administrative step is to associate our new device with our bus. +This is accomplished using a symbolic link from the bus instance to our device +instance. + +ln -s /config/vbus/devices/6a1aff24-5dc0-4aea-9c35-435daef90e55/ /config/vbus/instances/beb4df8f-7483-4028-b3f7-767512e2a18c/ +# tree /sys/vbus/ +/sys/vbus/ +|-- deviceclass +| `-- venet-tap +|-- devices +| `-- 6a1aff24-5dc0-4aea-9c35-435daef90e55 +| |-- class -> ../../deviceclass/venet-tap +| |-- client_mac +| |-- enabled +| |-- host_mac +| |-- ifname +| `-- interfaces +| `-- 0 -> ../../../instances/beb4df8f-7483-4028-b3f7-767512e2a18c/devices/0 +|-- instances +| `-- beb4df8f-7483-4028-b3f7-767512e2a18c +| |-- devices +| | `-- 0 +| | |-- device -> ../../../../devices/6a1aff24-5dc0-4aea-9c35-435daef90e55 +| | `-- type +| `-- members +`-- version + +We can now see that the device indicates that it has an interface registered +to a bus: + +/sys/vbus/devices/6a1aff24-5dc0-4aea-9c35-435daef90e55/interfaces/ +`-- 0 -> ../../../instances/beb4df8f-7483-4028-b3f7-767512e2a18c/devices/0 + +Likewise, we can see that the bus has a device listed (id = "0"): + +/sys/vbus/instances/beb4df8f-7483-4028-b3f7-767512e2a18c/devices/ +`-- 0 + |-- device -> ../../../../devices/6a1aff24-5dc0-4aea-9c35-435daef90e55 + `-- type + +At this point, our container is ready for use. However, it currently has 0 +members, so lets fix that + +Add some members +-------------------- + +Membership is controlled by an attribute: /proc/$pid/vbus. A pid can only be +a member of one (or zero) busses at a time. To establish membership, we set +the name of the bus, like so: + +# echo beb4df8f-7483-4028-b3f7-767512e2a18c > /proc/self/vbus +# tree /sys/vbus/ +/sys/vbus/ +|-- deviceclass +| `-- venet-tap +|-- devices +| `-- 6a1aff24-5dc0-4aea-9c35-435daef90e55 +| |-- class -> ../../deviceclass/venet-tap +| |-- client_mac +| |-- enabled +| |-- host_mac +| |-- ifname +| `-- interfaces +| `-- 0 -> ../../../instances/beb4df8f-7483-4028-b3f7-767512e2a18c/devices/0 +|-- instances +| `-- beb4df8f-7483-4028-b3f7-767512e2a18c +| |-- devices +| | `-- 0 +| | |-- device -> ../../../../devices/6a1aff24-5dc0-4aea-9c35-435daef90e55 +| | `-- type +| `-- members +| |-- 4382 +| `-- 4588 +`-- version + +Woah! Why are there two members? VBUS membership is inherited by forked +tasks. Therefore 4382 is the pid of our shell (which we set via /proc/self), +and 4588 is the pid of the forked/exec'ed "tree" process. This property can +be useful for having things like qemu set up the bus and then forking each +vcpu which will inherit access. + +At this point, we are ready to roll. Pid 4382 has access to a virtual-bus +namespace with one device, id=0. Its type is: + +# cat /sys/vbus/instances/beb4df8f-7483-4028-b3f7-767512e2a18c/devices/0/type +virtual-ethernet + +"virtual-ethernet"? Why is it not "venet-tap"? Device-classes are allowed to +register their interfaces under an id that is not required to be the same as +their deviceclass. This supports device polymorphism. For instance, +consider that an interface "virtual-ethernet" may provide basic 802.x packet +exchange. However, we could have various implementations of a device that +supports the 802.x interface, while having various implementations behind +them. + +For instance, "venet-tap" might act like a tuntap module, while +"venet-loopback" would loop packets back and "venet-switch" would form a +layer-2 domain among the participating guests. All three modules would +presumably support the same basic 802.x interface, yet all three have +completely different implementations. + +Drivers on this particular bus would see this instance id=0 as a type +"virtual-ethernet" even though the underlying implementation happens to be a +tap device. This means a single driver that supports the protocol advertised +by the "virtual-ethernet" type would be able to support the plethera of +available device types that we may wish to create. + +Teardown: +--------------- + +We can descontruct a vbus container doing pretty much the opposite of what we +did to create it. Echo "0" into /proc/self/vbus, rm the symlink between the +bus and device, and rmdir the bus and device objects. Once that is done, we +can even rmmod the venet-tap module. Note that the infrastructure will +maintain a module-ref while it is configured in a container, so be sure to +completely tear down the vbus/device before trying this.
arch/x86/Kconfig +2 -0
@@ -1978,6 +1978,8 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" +source "kernel/vbus/Kconfig" + endmenu
fs/proc/base.c +96 -0
114 lines not on this page · raw message
include/linux/sched.h +4 -0
@@ -98,6 +98,7 @@ struct robust_list_head;struct bio ;struct bts_tracer ;struct fs_struct ; +struct vbus ;/* * List of flags we want to share for kernel threads,
@@ -1339,6 +1340,9 @@ struct task_struct {struct held_lock held_locks[MAX_LOCK_DEPTH ];gfp_t lockdep_reclaim_gfp;#endif +#ifdef CONFIG_VBUS +struct vbus *vbus; +#endif /* journalling filesystem info */ void *journal_info;
include/linux/vbus.h new file +147 -0
147 lines not on this page · raw message
include/linux/vbus_device.h new file +417 -0
417 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -95,6 +95,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += trace/ obj-$(CONFIG_TRACING) += trace/ obj-$(CONFIG_SMP) += sched_cpupri.o obj-$(CONFIG_SLOW_WORK) += slow-work.o +obj-$(CONFIG_VBUS) += vbus/ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/exit.c +2 -0
@@ -49,6 +49,7 @@#include <linux/fs_struct.h> #include <linux/init_task.h> #include <trace/sched.h> +#include <linux/vbus.h> #include <asm/uaccess.h> #include <asm/unistd.h>
@@ -966,6 +967,7 @@ NORET_TYPE void do_exit(long code)check_stack_usage ();exit_thread ();cgroup_exit (tsk,1 ); +task_vbus_disassociate (tsk);if (group_dead && tsk->signal->leader)disassociate_ctty (1 );
kernel/fork.c +2 -0
@@ -63,6 +63,7 @@#include <linux/fs_struct.h> #include <trace/sched.h> #include <linux/magic.h> +#include <linux/vbus.h> #include <asm/pgtable.h> #include <asm/pgalloc.h>
@@ -1266,6 +1267,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,write_unlock_irq (&tasklist_lock);proc_fork_connector (p);cgroup_post_fork (p); +fork_vbus (p);return p; bad_fork_free_graph:
kernel/vbus/Kconfig new file +14 -0
@@ -0,0 +1,14 @@ +# +# Virtual-Bus (VBus) configuration +# + +config VBUS + bool "Virtual Bus" + select CONFIGFS_FS + select SHM_SIGNAL + default n + help + Provides a mechansism for declaring virtual-bus objects and binding + various tasks and devices which reside on the bus. + + If unsure, say N
kernel/vbus/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o
kernel/vbus/attribute.c new file +52 -0
52 lines not on this page · raw message
kernel/vbus/config.c new file +275 -0
275 lines not on this page · raw message
kernel/vbus/core.c new file +567 -0
567 lines not on this page · raw message
kernel/vbus/devclass.c new file +124 -0
124 lines not on this page · raw message
kernel/vbus/map.c new file +72 -0
72 lines not on this page · raw message
kernel/vbus/map.h new file +41 -0
41 lines not on this page · raw message
kernel/vbus/vbus.h new file +116 -0
116 lines not on this page · raw message
RFC PATCH v3 3/17 vbus: add connection-client helper infrastructure
In reply to Gregory HaskinsWe expect to have various types of connection-clients (e.g. userspace, kvm, etc), each of which is likely to have common access patterns and marshalling duties. Therefore we create a "client" API to simplify client development by helping with mundane tasks such as handle-2-pointer translation, etc.
Special thanks to Pat Mullaney for suggesting the optimization to pass a cookie object down during DEVICESHM operations to save lookup overhead on the event channel.
---
include/linux/vbus_client.h | 115 +++++++++ kernel/vbus/Makefile | 2 kernel/vbus/client.c | 543 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 659 insertions(+), 1 deletions(-) create mode 100644 include/linux/vbus_client.h create mode 100644 kernel/vbus/client.c
include/linux/vbus_client.h new file +115 -0
@@ -0,0 +1,115 @@ +/* +* Copyright 2009 Novell. All Rights Reserved. +* +* Virtual-Bus - Client interface +* +* We expect to have various types of connection-clients (e.g. userspace, +* kvm, etc). Each client will be connecting from some environment outside +* of the kernel, and therefore will not have direct access to the API as +* presented in ./linux/vbus.h. There will undoubtedly be some parameter +* marshalling that must occur, as well as common patterns for the handling +* of those marshalled parameters (e.g. translating a handle into a pointer, +* etc). +* +* Therefore this "client" API is provided to simplify the development +* of any clients. Of course, a client is free to bypass this API entirely +* and communicate with the direct VBUS API if desired. +* +* Author: +* Gregory Haskins <[email protected]> +* +* This file is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINUX_VBUS_CLIENT_H +#define _LINUX_VBUS_CLIENT_H + +#include <linux/types.h> +#include <linux/compiler.h> + +struct vbus_deviceopen { +__u32 devid; +__u32 version;/* device ABI version */ +__u64 handle;/* return value for devh */ +}; + +struct vbus_devicecall { +__u64 devh;/* device-handle (returned from DEVICEOPEN */ +__u32 func; +__u32 len; +__u32 flags; +__u64 datap; +}; + +struct vbus_deviceshm { +__u64 devh;/* device-handle (returned from DEVICEOPEN */ +__u32 id; +__u32 len; +__u32 flags; +struct { +__u32 offset; +__u32 prio; +__u64 cookie;/* token to pass back when signaling client */ + } signal; +__u64 datap; +__u64 handle;/* return value for signaling from client to kernel */ +}; + +#ifdef __KERNEL__ + +#include <linux/ioq.h> +#include <linux/module.h> +#include <asm/atomic.h> + +struct vbus_client ; + +struct vbus_client_ops { +int (*deviceopen)(struct vbus_client *client,struct vbus_memctx *ctx, +__u32 devid,__u32 version,__u64 *devh); +int (*deviceclose)(struct vbus_client *client,__u64 devh); +int (*devicecall)(struct vbus_client *client, +__u64 devh,__u32 func, +void *data,__u32 len,__u32 flags); +int (*deviceshm)(struct vbus_client *client, +__u64 devh,__u32 id, +struct vbus_shm *shm,struct shm_signal *signal, +__u32 flags,__u64 *handle); +int (*shmsignal)(struct vbus_client *client,__u64 handle); +void (*release)(struct vbus_client *client); +}; + +struct vbus_client { +atomic_t refs; +struct vbus_client_ops *ops; +}; + +static inline void vbus_client_get (struct vbus_client *client) +{ +atomic_inc (&client->refs); +} + +static inline void vbus_client_put (struct vbus_client *client) +{ +if (atomic_dec_and_test (&client->refs)) + client->ops->release (client); +} + +struct vbus_client *vbus_client_attach (struct vbus *bus); + +extern struct vbus_memctx *current_memctx; +struct vbus_memctx *task_memctx_alloc (struct task_struct *task); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_VBUS_CLIENT_H */
kernel/vbus/Makefile +1 -1
@@ -1 +1 @@ -obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o +obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o client.o
kernel/vbus/client.c new file +543 -0
543 lines not on this page · raw message
RFC PATCH v3 4/17 vbus: add bus-registration notifiers
In reply to Gregory HaskinsWe need to get hotswap events in environments which cannot use existing facilities (e.g. inotify). So we add a notifier-chain to allow client callbacks whenever an interface is {un}registered.
---
include/linux/vbus.h | 15 +++++++++++++ kernel/vbus/core.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/vbus/vbus.h | 1 + 3 files changed, 75 insertions(+), 0 deletions(-)
include/linux/vbus.h +15 -0
@@ -29,6 +29,7 @@#include <linux/sched.h> #include <linux/rcupdate.h> #include <linux/vbus_device.h> +#include <linux/notifier.h> struct vbus ;struct task_struct ;
@@ -137,6 +138,20 @@ static inline void task_vbus_disassociate(struct task_struct *p) } } +enum { +VBUS_EVENT_DEVADD , +VBUS_EVENT_DEVDROP , +}; + +struct vbus_event_devadd { +const char *type; +unsigned long id; +}; + +int vbus_notifier_register (struct vbus *vbus,struct notifier_block *nb); +int vbus_notifier_unregister (struct vbus *vbus,struct notifier_block *nb); + +#else /* CONFIG_VBUS */ #define fork_vbus (p) do { } while (0)
kernel/vbus/core.c +59 -0
89 lines not on this page · raw message
kernel/vbus/vbus.h +1 -0
@@ -51,6 +51,7 @@ struct vbus {struct vbus_subdir members;unsigned long next_id;struct rb_node node; +struct raw_notifier_head notifier; };struct vbus_member {
RFC PATCH v3 5/17 vbus: add a "vbus-proxy" bus model for vbus_driver objects
In reply to Gregory HaskinsThis 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.
---
include/linux/vbus_driver.h | 73 +++++++++++++++++++++ kernel/vbus/Kconfig | 9 +++ kernel/vbus/Makefile | 4 + kernel/vbus/proxy.c | 152 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 0 deletions(-) create mode 100644 include/linux/vbus_driver.h create mode 100644 kernel/vbus/proxy.c
include/linux/vbus_driver.h new file +73 -0
@@ -0,0 +1,73 @@ +/* +* Copyright 2009 Novell. All Rights Reserved. +* +* Mediates access to a host VBUS from a guest kernel by providing a +* global view of all VBUS devices +* +* Author: +* Gregory Haskins <[email protected]> +* +* This file is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINUX_VBUS_DRIVER_H +#define _LINUX_VBUS_DRIVER_H + +#include <linux/device.h> +#include <linux/shm_signal.h> + +struct vbus_device_proxy ; +struct vbus_driver ; + +struct vbus_device_proxy_ops { +int (*open)(struct vbus_device_proxy *dev,int version,int flags); +int (*close)(struct vbus_device_proxy *dev,int flags); +int (*shm)(struct vbus_device_proxy *dev,int id,int prio, +void *ptr,size_t len, +struct shm_signal_desc *sigdesc,struct shm_signal **signal, +int flags); +int (*call)(struct vbus_device_proxy *dev,u32 func, +void *data,size_t len,int flags); +void (*release)(struct vbus_device_proxy *dev); +}; + +struct vbus_device_proxy { +char *type; +u64 id; +void *priv;/* Used by drivers */ +struct vbus_device_proxy_ops *ops; +struct device dev; +}; + +int vbus_device_proxy_register (struct vbus_device_proxy *dev); +void vbus_device_proxy_unregister (struct vbus_device_proxy *dev); + +struct vbus_device_proxy *vbus_device_proxy_find (u64 id); + +struct vbus_driver_ops { +int (*probe)(struct vbus_device_proxy *dev); +int (*remove)(struct vbus_device_proxy *dev); +}; + +struct vbus_driver { +char *type; +struct module *owner; +struct vbus_driver_ops *ops; +struct device_driver drv; +}; + +int vbus_driver_register (struct vbus_driver *drv); +void vbus_driver_unregister (struct vbus_driver *drv); + +#endif /* _LINUX_VBUS_DRIVER_H */
kernel/vbus/Kconfig +9 -0
@@ -12,3 +12,12 @@ config VBUS various tasks and devices which reside on the bus. If unsure, say N + +config VBUS_DRIVERS + tristate "VBUS Driver support" + default n + help + Adds support for a virtual bus model for proxying drivers. + + If unsure, say N +
kernel/vbus/Makefile +4 -0
@@ -1 +1,5 @@ obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o client.o + +vbus-proxy-objs += proxy.o +obj-$(CONFIG_VBUS_DRIVERS) += vbus-proxy.o +
kernel/vbus/proxy.c new file +152 -0
152 lines not on this page · raw message
RFC PATCH v3 6/17 ioq: Add basic definitions for a shared-memory, lockless queue
In reply to Gregory HaskinsWe can map these over VBUS shared memory (or really any shared-memory architecture if it supports shm-signals) to allow asynchronous communication between two end-points. Memory is synchronized using pure barriers (i.e. lockless), so IOQs are friendly in many contexts, even if the memory is remote.
---
include/linux/ioq.h | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig | 12 + lib/Makefile | 1 lib/ioq.c | 298 +++++++++++++++++++++++++++++++++++++ 4 files changed, 721 insertions(+), 0 deletions(-) create mode 100644 include/linux/ioq.h create mode 100644 lib/ioq.c
include/linux/ioq.h new file +410 -0
@@ -0,0 +1,410 @@ +/* +* Copyright 2009 Novell. All Rights Reserved. +* +* IOQ is a generic shared-memory, lockless queue mechanism. It can be used +* in a variety of ways, though its intended purpose is to become the +* asynchronous communication path for virtual-bus drivers. +* +* The following are a list of key design points: +* +* #) All shared-memory is always allocated on explicitly one side of the +* link. This typically would be the guest side in a VM/VMM scenario. +* #) Each IOQ has the concept of "north" and "south" locales, where +* north denotes the memory-owner side (e.g. guest). +* #) An IOQ is manipulated using an iterator idiom. +* #) Provides a bi-directional signaling/notification infrastructure on +* a per-queue basis, which includes an event mitigation strategy +* to reduce boundary switching. +* #) The signaling path is abstracted so that various technologies and +* topologies can define their own specific implementation while sharing +* the basic structures and code. +* +* Author: +* Gregory Haskins <[email protected]> +* +* This file is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINUX_IOQ_H +#define _LINUX_IOQ_H + +#include <asm/types.h> +#include <linux/shm_signal.h> + +/* +*--------- +* The following structures represent data that is shared across boundaries +* which may be quite disparate from one another (e.g. Windows vs Linux, +* 32 vs 64 bit, etc). Therefore, care has been taken to make sure they +* present data in a manner that is independent of the environment. +*----------- +*/ +struct ioq_ring_desc { +__u64 cookie;/* for arbitrary use by north-side */ +__u64 ptr; +__u64 len; +__u8 valid; +__u8 sown;/* South owned = 1, North owned = 0 */ +}; + +#define IOQ_RING_MAGIC 0x47fa2fe4 +#define IOQ_RING_VER 4 + +struct ioq_ring_idx { +__u32 head;/* 0 based index to head of ptr array */ +__u32 tail;/* 0 based index to tail of ptr array */ +__u8 full; +}; + +enum ioq_locality { + ioq_locality_north, + ioq_locality_south, +}; + +struct ioq_ring_head { +__u32 magic; +__u32 ver; +struct shm_signal_desc signal; +struct ioq_ring_idx idx[2 ]; +__u32 count; +struct ioq_ring_desc ring[1 ];/* "count" elements will be allocated */ +}; + +#define IOQ_HEAD_DESC_SIZE (count) \ + (sizeof(struct ioq_ring_head) + sizeof(struct ioq_ring_desc) * (count - 1)) + +/* --- END SHARED STRUCTURES --- */ + +#ifdef __KERNEL__ + +#include <linux/sched.h> +#include <linux/wait.h> +#include <linux/interrupt.h> +#include <linux/shm_signal.h> +#include <asm/atomic.h> + +enum ioq_idx_type { + ioq_idxtype_valid, + ioq_idxtype_inuse, + ioq_idxtype_both, + ioq_idxtype_invalid, +}; + +enum ioq_seek_type { + ioq_seek_tail, + ioq_seek_next, + ioq_seek_head, + ioq_seek_set +}; + +struct ioq_iterator { +struct ioq *ioq; +struct ioq_ring_idx *idx; +u32 pos; +struct ioq_ring_desc *desc; +int update:1 ; +int dualidx:1 ; +int flipowner:1 ; +}; + +struct ioq_notifier { +void (*signal)(struct ioq_notifier *); +}; + +struct ioq_ops { +void (*release)(struct ioq *ioq); +}; + +struct ioq { +struct ioq_ops *ops; + +atomic_t refs; +enum ioq_locality locale; +struct ioq_ring_head *head_desc; +struct ioq_ring_desc *ring; +struct shm_signal *signal; +wait_queue_head_t wq; +struct ioq_notifier *notifier; +size_t count; +struct shm_signal_notifier shm_notifier; +}; + +#define IOQ_ITER_AUTOUPDATE (1 << 0) +#define IOQ_ITER_NOFLIPOWNER (1 << 1) + +/** +* ioq_init() - initialize an IOQ +* @ioq: IOQ context +* +* Initializes IOQ context before first use +* +**/ +void ioq_init (struct ioq *ioq, +struct ioq_ops *ops, +enum ioq_locality locale, +struct ioq_ring_head *head, +struct shm_signal *signal, +size_t count); + +/** +* ioq_get() - acquire an IOQ context reference +* @ioq: IOQ context +* +**/ +static inline struct ioq *ioq_get (struct ioq *ioq) +{ +atomic_inc (&ioq->refs); + +return ioq; +} + +/** +* ioq_put() - release an IOQ context reference +* @ioq: IOQ context +* +**/ +static inline void ioq_put (struct ioq *ioq) +{ +if (atomic_dec_and_test (&ioq->refs)) { +shm_signal_put (ioq->signal); + ioq->ops->release (ioq); + } +} + +/** +* ioq_notify_enable() - enables local notifications on an IOQ +* @ioq: IOQ context +* @flags: Reserved for future use, must be 0 +* +* Enables/unmasks the registered ioq_notifier (if applicable) and waitq to +* receive wakeups whenever the remote side performs an ioq_signal() operation. +* A notification will be dispatched immediately if any pending signals have +* already been issued prior to invoking this call. +* +* This is synonymous with unmasking an interrupt. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +static inline int ioq_notify_enable (struct ioq *ioq,int flags) +{ +return shm_signal_enable (ioq->signal,0 ); +} + +/** +* ioq_notify_disable() - disable local notifications on an IOQ +* @ioq: IOQ context +* @flags: Reserved for future use, must be 0 +* +* Disables/masks the registered ioq_notifier (if applicable) and waitq +* from receiving any further notifications. Any subsequent calls to +* ioq_signal() by the remote side will update the ring as dirty, but +* will not traverse the locale boundary and will not invoke the notifier +* callback or wakeup the waitq. Signals delivered while masked will +* be deferred until ioq_notify_enable() is invoked +* +* This is synonymous with masking an interrupt +* +* Returns: success = 0, <0 = ERRNO +* +**/ +static inline int ioq_notify_disable (struct ioq *ioq,int flags) +{ +return shm_signal_disable (ioq->signal,0 ); +} + +/** +* ioq_signal() - notify the remote side about ring changes +* @ioq: IOQ context +* @flags: Reserved for future use, must be 0 +* +* Marks the ring state as "dirty" and, if enabled, will traverse +* a locale boundary to invoke a remote notification. The remote +* side controls whether the notification should be delivered via +* the ioq_notify_enable/disable() interface. +* +* The specifics of how to traverse a locale boundary are abstracted +* by the ioq_ops->signal() interface and provided by a particular +* implementation. However, typically going north to south would be +* something like a syscall/hypercall, and going south to north would be +* something like a posix-signal/guest-interrupt. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +static inline int ioq_signal (struct ioq *ioq,int flags) +{ +return shm_signal_inject (ioq->signal,0 ); +} + +/** +* ioq_count() - counts the number of outstanding descriptors in an index +* @ioq: IOQ context +* @type: Specifies the index type +* (*) valid: the descriptor is valid. This is usually +* used to keep track of descriptors that may not +* be carrying a useful payload, but still need to +* be tracked carefully. +* (*) inuse: Descriptors that carry useful payload +* +* Returns: +* (*) >=0: # of descriptors outstanding in the index +* (*) <0 = ERRNO +* +**/ +int ioq_count (struct ioq *ioq,enum ioq_idx_type type); + +/** +* ioq_remain() - counts the number of remaining descriptors in an index +* @ioq: IOQ context +* @type: Specifies the index type +* (*) valid: the descriptor is valid. This is usually +* used to keep track of descriptors that may not +* be carrying a useful payload, but still need to +* be tracked carefully. +* (*) inuse: Descriptors that carry useful payload +* +* This is the converse of ioq_count(). This function returns the number +* of "free" descriptors left in a particular index +* +* Returns: +* (*) >=0: # of descriptors remaining in the index +* (*) <0 = ERRNO +* +**/ +int ioq_remain (struct ioq *ioq,enum ioq_idx_type type); + +/** +* ioq_size() - counts the maximum number of descriptors in an ring +* @ioq: IOQ context +* +* This function returns the maximum number of descriptors supported in +* a ring, regardless of their current state (free or inuse). +* +* Returns: +* (*) >=0: total # of descriptors in the ring +* (*) <0 = ERRNO +* +**/ +int ioq_size (struct ioq *ioq); + +/** +* ioq_full() - determines if a specific index is "full" +* @ioq: IOQ context +* @type: Specifies the index type +* (*) valid: the descriptor is valid. This is usually +* used to keep track of descriptors that may not +* be carrying a useful payload, but still need to +* be tracked carefully. +* (*) inuse: Descriptors that carry useful payload +* +* Returns: +* (*) 0: index is not full +* (*) 1: index is full +* (*) <0 = ERRNO +* +**/ +int ioq_full (struct ioq *ioq,enum ioq_idx_type type); + +/** +* ioq_empty() - determines if a specific index is "empty" +* @ioq: IOQ context +* @type: Specifies the index type +* (*) valid: the descriptor is valid. This is usually +* used to keep track of descriptors that may not +* be carrying a useful payload, but still need to +* be tracked carefully. +* (*) inuse: Descriptors that carry useful payload +* +* Returns: +* (*) 0: index is not empty +* (*) 1: index is empty +* (*) <0 = ERRNO +* +**/ +static inline int ioq_empty (struct ioq *ioq,enum ioq_idx_type type) +{ +return !ioq_count (ioq, type); +} + +/** +* ioq_iter_init() - initialize an iterator for IOQ descriptor traversal +* @ioq: IOQ context to iterate on +* @iter: Iterator context to init (usually from stack) +* @type: Specifies the index type to iterate against +* (*) valid: iterate against the "valid" index +* (*) inuse: iterate against the "inuse" index +* (*) both: iterate against both indexes simultaneously +* @flags: Bitfield with 0 or more bits set to alter behavior +* (*) autoupdate: automatically signal the remote side +* whenever the iterator pushes/pops to a new desc +* (*) noflipowner: do not flip the ownership bit during +* a push/pop operation +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int ioq_iter_init (struct ioq *ioq,struct ioq_iterator *iter, +enum ioq_idx_type type,int flags); + +/** +* ioq_iter_seek() - seek to a specific location in the IOQ ring +* @iter: Iterator context (must be initialized with ioq_iter_init) +* @type: Specifies the type of seek operation +* (*) tail: seek to the absolute tail, offset is ignored +* (*) next: seek to the relative next, offset is ignored +* (*) head: seek to the absolute head, offset is ignored +* (*) set: seek to the absolute offset +* @offset: Offset for ioq_seek_set operations +* @flags: Reserved for future use, must be 0 +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int ioq_iter_seek (struct ioq_iterator *iter,enum ioq_seek_type type, +long offset,int flags); + +/** +* ioq_iter_push() - push the tail pointer forward +* @iter: Iterator context (must be initialized with ioq_iter_init) +* @flags: Reserved for future use, must be 0 +* +* This function will simultaneously advance the tail ptr in the current +* index (valid/inuse, as specified in the ioq_iter_init) as well as +* perform a seek(next) operation. This effectively "pushes" a new pointer +* onto the tail of the index. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int ioq_iter_push (struct ioq_iterator *iter,int flags); + +/** +* ioq_iter_pop() - pop the head pointer from the ring +* @iter: Iterator context (must be initialized with ioq_iter_init) +* @flags: Reserved for future use, must be 0 +* +* This function will simultaneously advance the head ptr in the current +* index (valid/inuse, as specified in the ioq_iter_init) as well as +* perform a seek(next) operation. This effectively "pops" a pointer +* from the head of the index. +* +* Returns: success = 0, <0 = ERRNO +* +**/ +int ioq_iter_pop (struct ioq_iterator *iter,int flags); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_IOQ_H */
lib/Kconfig +12 -0
@@ -200,4 +200,16 @@ config SHM_SIGNAL If unsure, say N +config IOQ + boolean "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 the low-level + communication path for paravirtualized drivers. + + If unsure, say N + endmenu
lib/Makefile +1 -0
@@ -76,6 +76,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 +298 -0
298 lines not on this page · raw message
RFC PATCH v3 7/17 ioq: add vbus helpers
In reply to Gregory HaskinsIt will be common to map an IOQ over the VBUS shared-memory interfaces, so lets generalize their setup so we can reuse the pattern.
---
include/linux/vbus_device.h | 7 +++ include/linux/vbus_driver.h | 7 +++ kernel/vbus/Kconfig | 2 + kernel/vbus/Makefile | 1 kernel/vbus/proxy.c | 64 +++++++++++++++++++++++++++++++ kernel/vbus/shm-ioq.c | 89 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 0 deletions(-) create mode 100644 kernel/vbus/shm-ioq.c
include/linux/vbus_device.h +7 -0
@@ -102,6 +102,7 @@#include <linux/configfs.h> #include <linux/rbtree.h> #include <linux/shm_signal.h> +#include <linux/ioq.h> #include <linux/vbus.h> #include <asm/atomic.h>
@@ -414,4 +415,10 @@ static inline void vbus_connection_put(struct vbus_connection *conn) conn->ops->release(conn); } +/* +* device-side IOQ helper - dereferences device-shm as an IOQ +*/ +int vbus_shm_ioq_attach (struct vbus_shm *shm,struct shm_signal *signal, +int maxcount,struct ioq **ioq); +#endif /* _LINUX_VBUS_DEVICE_H */
include/linux/vbus_driver.h +7 -0
@@ -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 */
kernel/vbus/Kconfig +2 -0
@@ -6,6 +6,7 @@ config VBUS bool "Virtual Bus" select CONFIGFS_FS select SHM_SIGNAL + select IOQ default n help Provides a mechansism for declaring virtual-bus objects and binding
@@ -15,6 +16,7 @@ config VBUS config VBUS_DRIVERS tristate "VBUS Driver support" + select IOQ default n help Adds support for a virtual bus model for proxying drivers.
kernel/vbus/Makefile +1 -0
@@ -1,4 +1,5 @@ obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o client.o +obj-$(CONFIG_VBUS) += shm-ioq.o vbus-proxy-objs += proxy.o obj-$(CONFIG_VBUS_DRIVERS) += vbus-proxy.o
kernel/vbus/proxy.c +64 -0
67 lines not on this page · raw message
kernel/vbus/shm-ioq.c new file +89 -0
89 lines not on this page · raw message
RFC PATCH v3 8/17 venet: add the ABI definitions for an 802.x packet interface
In reply to Gregory Haskins---
include/linux/venet.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-) create mode 100644 include/linux/venet.h
include/linux/venet.h new file +47 -0
@@ -0,0 +1,47 @@ +/* +* Copyright 2008 Novell. All Rights Reserved. +* +* Virtual-Ethernet adapter +* +* Author: +* Gregory Haskins <[email protected]> +* +* This file is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINUX_VENET_H +#define _LINUX_VENET_H + +#define VENET_VERSION 1 + +#define VENET_TYPE "virtual-ethernet" + +#define VENET_QUEUE_RX 0 +#define VENET_QUEUE_TX 1 + +struct venet_capabilities { +__u32 gid; +__u32 bits; +}; + +/* CAPABILITIES-GROUP 0 */ +/* #define VENET_CAP_FOO 0 (No capabilities defined yet, for now) */ + +#define VENET_FUNC_LINKUP 0 +#define VENET_FUNC_LINKDOWN 1 +#define VENET_FUNC_MACQUERY 2 +#define VENET_FUNC_NEGCAP 3/* negotiate capabilities */ +#define VENET_FUNC_FLUSHRX 4 + +#endif /* _LINUX_VENET_H */
RFC PATCH v3 9/17 net: Add vbus_enet driver
In reply to Gregory Haskins---
drivers/net/Kconfig | 13 + drivers/net/Makefile | 1 drivers/net/vbus-enet.c | 672 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 686 insertions(+), 0 deletions(-) create mode 100644 drivers/net/vbus-enet.c
drivers/net/Kconfig +13 -0
@@ -3155,4 +3155,17 @@ 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 "Virtual Ethernet Driver" + depends on VBUS_DRIVERS + help + A virtualized 802.x network device based on the VBUS interface. + It can be used with any hypervisor/kernel that supports the + vbus protocol. + +config VBUS_ENET_DEBUG + bool "Enable Debugging" + depends on VBUS_ENET + default n + endif # NETDEVICES
drivers/net/Makefile +1 -0
@@ -268,6 +268,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
RFC PATCH v3 10/17 venet-tap: Adds a "venet" compatible "tap" device to VBUS
In reply to Gregory HaskinsThis module is similar in concept to a "tuntap". A tuntap module provides a netif() interface on one side, and a char-dev interface on the other. Packets that ingress on one interface, egress on the other (and vice versa).
This module offers a similar concept, except that it substitues the char-dev for a VBUS/IOQ interface. This allows a VBUS compatible entity (e.g. userspace or a guest) to directly inject and receive packets from the host/kernel stack.
Thanks to Pat Mullaney for contributing the maxcount modification
---
drivers/Makefile | 1 drivers/vbus/devices/Kconfig | 17 drivers/vbus/devices/Makefile | 1 drivers/vbus/devices/venet-tap.c | 1387 ++++++++++++++++++++++++++++++++++++++ kernel/vbus/Kconfig | 13 5 files changed, 1419 insertions(+), 0 deletions(-) create mode 100644 drivers/vbus/devices/Kconfig create mode 100644 drivers/vbus/devices/Makefile create mode 100644 drivers/vbus/devices/venet-tap.c
drivers/Makefile +1 -0
@@ -107,3 +107,4 @@ obj-$(CONFIG_SSB) += ssb/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ +obj-$(CONFIG_VBUS_DEVICES) += vbus/devices/
drivers/vbus/devices/Kconfig new file +17 -0
@@ -0,0 +1,17 @@ +# +# Virtual-Bus (VBus) configuration +# + +config VBUS_VENETTAP + tristate "Virtual-Bus Ethernet Tap Device" + depends on VBUS_DEVICES + default n + help + Provides a virtual ethernet adapter to a vbus, which in turn + manifests itself as a standard netif based adapter to the + kernel. It can be used similarly to a "tuntap" device, + except that the char-dev transport is replaced with a vbus/ioq + interface. + + If unsure, say N +
drivers/vbus/devices/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_VBUS_VENETTAP) += venet-tap.o
drivers/vbus/devices/venet-tap.c new file +1387 -0
1,387 lines not on this page · raw message
kernel/vbus/Kconfig +13 -0
@@ -14,6 +14,17 @@ config VBUS If unsure, say N +config VBUS_DEVICES + bool "Virtual-Bus Devices" + depends on VBUS + default n + help + Provides device-class modules for instantiation on a virtual-bus + + If unsure, say N + +source "drivers/vbus/devices/Kconfig" + config VBUS_DRIVERS tristate "VBUS Driver support" select IOQ
@@ -23,3 +34,5 @@ config VBUS_DRIVERS If unsure, say N + +
RFC PATCH v3 11/17 venet-tap: add the ability to set the client's mac address via sysfs
In reply to Gregory HaskinsFrom: Patrick Mullaney <[email protected]>
---
drivers/vbus/devices/venet-tap.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)
drivers/vbus/devices/venet-tap.c +34 -1
@@ -1214,6 +1214,39 @@ host_mac_show(struct vbus_device *dev, struct vbus_device_attribute *attr,static struct vbus_device_attribute attr_hmac =__ATTR_RO (host_mac); + +static ssize_t +cmac_store (struct vbus_device *dev,struct vbus_device_attribute *attr, +const char *buf,size_t count) +{ +struct venettap *priv =vdev_to_priv (dev); +const char *pbuf = buf; +unsigned int uc; +int i; + +/* +* Format 00:11:22:33:44:55 +*/ +if (count !=18 ) +return -EINVAL ; + +for (i =2 ; i <17 ; i +=3 ) { +if (pbuf[i] !=':' ) +return -EINVAL ; + } + +if (priv->vbus.opened) +return -EINVAL ; + +for (i =0 ; i <ETH_ALEN ; i++) { +sscanf (pbuf,"%x" , &uc); + pbuf = pbuf +3 ; + priv->cmac[i] = (u8 )uc; + } + +return count; +} +static ssize_t client_mac_show (struct vbus_device *dev,struct vbus_device_attribute *attr,char *buf)
@@ -1224,7 +1257,7 @@ client_mac_show(struct vbus_device *dev, struct vbus_device_attribute *attr, }static struct vbus_device_attribute attr_cmac = -__ATTR_RO (client_mac); +__ATTR (client_mac,S_IRUGO |S_IWUSR , client_mac_show, cmac_store); static ssize_t enabled_show(struct vbus_device *dev, struct vbus_device_attribute *attr,
RFC PATCH v3 12/17 venet: add scatter-gather support
In reply to Gregory Haskins---
drivers/net/vbus-enet.c | 248 +++++++++++++++++++++++++++++++++++++++++++++-- include/linux/venet.h | 39 +++++++ 2 files changed, 274 insertions(+), 13 deletions(-)
drivers/net/vbus-enet.c +237 -11
@@ -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,46 @@ 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 |VENET_CAP_UFO ); + } + + 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 +775,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 +809,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 +852,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
@@ -35,8 +35,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
RFC PATCH v3 13/17 venettap: add scatter-gather support
In reply to Gregory Haskins---
drivers/vbus/devices/venet-tap.c | 235 +++++++++++++++++++++++++++++++++++++- 1 files changed, 228 insertions(+), 7 deletions(-)
drivers/vbus/devices/venet-tap.c +228 -7
@@ -81,6 +81,13 @@ enum { TX_IOQ_CONGESTED, }; +struct venettap ; + +struct venettap_rx_ops { +int (*decode)(struct venettap *priv,void *ptr,int len); +int (*import)(struct venettap *,struct sk_buff *,void *,int ); +}; +struct venettap {spinlock_t lock;unsigned char hmac[ETH_ALEN ];/* host-mac */
@@ -108,7 +115,13 @@ struct venettap {struct vbus_memctx *ctx;struct venettap_queue rxq;struct venettap_queue txq; +struct venettap_rx_ops *rx_ops;wait_queue_head_t rx_empty; +struct { +struct venet_sg *desc; +size_t len; +int enabled:1 ; + } sg; int connected:1; int opened:1; int link:1;
@@ -289,6 +302,183 @@ venettap_change_mtu(struct net_device *dev, int new_mtu) }/* +* --------------------------- +* Scatter-Gather support +* --------------------------- +*/ + +/* assumes reference to priv->vbus.conn held */ +static int +venettap_sg_decode (struct venettap *priv,void *ptr,int len) +{ +struct venet_sg *vsg; +struct vbus_memctx *ctx; +int ret; + +/* +* SG is enabled, so we need to pull in the venet_sg +* header before we can interpret the rest of the +* packet +* +* FIXME: Make sure this is not too big +*/ +if (unlikely (len > priv->vbus.sg.len)) { +kfree (priv->vbus.sg.desc); + priv->vbus.sg.desc =kzalloc (len,GFP_KERNEL ); + } + + vsg = priv->vbus.sg.desc; + ctx = priv->vbus.ctx; + + ret = ctx->ops->copy_from (ctx, vsg, ptr, len); +BUG_ON (ret); + +/* +* Non GSO type packets should be constrained by the MTU setting +* on the host +*/ +if (!(vsg->flags &VENET_SG_FLAG_GSO ) + && (vsg->len > (priv->netif.dev->mtu +ETH_HLEN ))) +return -1 ; + +return vsg->len; +} + +/* +* venettap_sg_import - import an skb in scatter-gather mode +* +* assumes reference to priv->vbus.conn held +*/ +static int +venettap_sg_import (struct venettap *priv,struct sk_buff *skb, +void *ptr,int len) +{ +struct venet_sg *vsg = priv->vbus.sg.desc; +struct vbus_memctx *ctx = priv->vbus.ctx; +int remain = len; +int ret; +int i; + +PDEBUG ("Importing %d bytes in %d segments\n" , len, vsg->count); + +for (i =0 ; i < vsg->count; i++) { +struct venet_iov *iov = &vsg->iov[i]; + +if (remain < iov->len) +return -EINVAL ; + +PDEBUG ("Segment %d: %p/%d\n" , i, iov->ptr, iov->len); + + ret = ctx->ops->copy_from (ctx,skb_tail_pointer (skb), + (void *)iov->ptr, + iov->len); +if (ret) +return -EFAULT ; + +skb_put (skb, iov->len); + remain -= iov->len; + } + +if (vsg->flags &VENET_SG_FLAG_NEEDS_CSUM + && !skb_partial_csum_set (skb, vsg->csum.start, vsg->csum.offset)) +return -EINVAL ; + +if (vsg->flags &VENET_SG_FLAG_GSO ) { +struct skb_shared_info *sinfo =skb_shinfo (skb); + +PDEBUG ("GSO packet detected\n" ); + +switch (vsg->gso.type) { +case VENET_GSO_TYPE_TCPV4 : + sinfo->gso_type =SKB_GSO_TCPV4 ; +break ; +case VENET_GSO_TYPE_TCPV6 : + sinfo->gso_type =SKB_GSO_TCPV6 ; +break ; +case VENET_GSO_TYPE_UDP : + sinfo->gso_type =SKB_GSO_UDP ; +break ; +default : +PDEBUG ("Illegal GSO type: %d\n" , vsg->gso.type); + priv->netif.stats.rx_frame_errors++; +kfree_skb (skb); +return -EINVAL ; + } + +if (vsg->flags &VENET_SG_FLAG_ECN ) + sinfo->gso_type |=SKB_GSO_TCP_ECN ; + + sinfo->gso_size = vsg->gso.size; +if (skb_shinfo (skb)->gso_size ==0 ) { +PDEBUG ("Illegal GSO size: %d\n" , vsg->gso.size); + priv->netif.stats.rx_frame_errors++; +kfree_skb (skb); +return -EINVAL ; + } + +/* Header must be checked, and gso_segs computed. */ +skb_shinfo (skb)->gso_type |=SKB_GSO_DODGY ; +skb_shinfo (skb)->gso_segs =0 ; + } + +return 0 ; +} + +static struct venettap_rx_ops venettap_sg_rx_ops = { + .decode = venettap_sg_decode, + .import = venettap_sg_import, +}; + +/* +* --------------------------- +* Flat (non Scatter-Gather) support +* --------------------------- +*/ + +/* assumes reference to priv->vbus.conn held */ +static int +venettap_flat_decode (struct venettap *priv,void *ptr,int len) +{ +size_t maxlen = priv->netif.dev->mtu +ETH_HLEN ; + +if (len > maxlen) +return -1 ; + +/* +* If SG is *not* enabled, the length is simply the +* descriptor length +*/ + +return len; +} + +/* +* venettap_rx_flat - import an skb in non scatter-gather mode +* +* assumes reference to priv->vbus.conn held +*/ +static int +venettap_flat_import (struct venettap *priv,struct sk_buff *skb, +void *ptr,int len) +{ +struct vbus_memctx *ctx = priv->vbus.ctx; +int ret; + + ret = ctx->ops->copy_from (ctx,skb_tail_pointer (skb), ptr, len); +if (ret) +return -EFAULT ; + +skb_put (skb, len); + +return 0 ; +} + +static struct venettap_rx_ops venettap_flat_rx_ops = { + .decode = venettap_flat_decode, + .import = venettap_flat_import, +}; + +/* * The poll implementation. */ static int
@@ -302,6 +492,7 @@ venettap_rx(struct venettap *priv)int ret;unsigned long flags;struct vbus_connection *conn; +struct venettap_rx_ops *rx_ops;PDEBUG ("polling...\n" );
@@ -325,6 +516,8 @@ venettap_rx(struct venettap *priv) ioq = priv->vbus.rxq.queue; ctx = priv->vbus.ctx; + rx_ops = priv->vbus.rx_ops; +spin_unlock_irqrestore (&priv->lock, flags);/* We want to iterate on the head of the in-use index */
@@ -339,11 +532,14 @@ venettap_rx(struct venettap *priv)* the north side */ while (iter.desc->sown) { -size_t len = iter.desc->len; -size_t maxlen = priv->netif.dev->mtu +ETH_HLEN ;struct sk_buff *skb =NULL ; +size_t len; -if (unlikely (len > maxlen)) { + len = rx_ops->decode (priv, + (void *)iter.desc->ptr, + iter.desc->len); + +if (unlikely (len <0 )) { priv->netif.stats.rx_errors++; priv->netif.stats.rx_length_errors++; goto next;
@@ -361,10 +557,8 @@ venettap_rx(struct venettap *priv)/* align IP on 16B boundary */ skb_reserve (skb,2 ); - ret = ctx->ops->copy_from (ctx, skb->data, - (void *)iter.desc->ptr, - len); -if (unlikely (ret)) { + ret = rx_ops->import (priv, skb, (void *)iter.desc->ptr, len); +if (unlikely (ret <0 )) { priv->netif.stats.rx_errors++; goto next; }
@@ -845,6 +1039,23 @@ venettap_macquery(struct venettap *priv, void *data, unsigned long len)return 0 ; } +static u32 +venettap_negcap_sg (struct venettap *priv,u32 requested) +{ +u32 available =VENET_CAP_SG |VENET_CAP_TSO4 |VENET_CAP_TSO6 + |VENET_CAP_ECN ; +u32 ret; + + ret = available & requested; + +if (ret &VENET_CAP_SG ) { + priv->vbus.sg.enabled = true; + priv->vbus.rx_ops = &venettap_sg_rx_ops; + } + +return ret; +} +/* * Negotiate Capabilities - This function is provided so that the * interface may be extended without breaking ABI compatability
@@ -872,6 +1083,9 @@ venettap_negcap(struct venettap *priv, void *data, unsigned long len)return -EFAULT ;switch (caps.gid) { +case VENET_CAP_GROUP_SG : + caps.bits =venettap_negcap_sg (priv, caps.bits); +break ;default : caps.bits =0 ;break ;
@@ -1056,6 +1270,12 @@ venettap_vlink_release(struct vbus_connection *conn)vbus_memctx_put (priv->vbus.ctx);kobject_put (priv->vbus.dev.kobj); + + priv->vbus.sg.enabled = false; + priv->vbus.rx_ops = &venettap_flat_rx_ops; +kfree (priv->vbus.sg.desc); + priv->vbus.sg.desc =NULL ; + priv->vbus.sg.len =0 ; }static struct vbus_connection_ops venettap_vbus_link_ops = {
@@ -1368,6 +1588,7 @@ venettap_device_create(struct vbus_devclass *dc, _vdev->ops = &venettap_device_ops; _vdev->attrs = &venettap_attr_group; + priv->vbus.rx_ops = &venettap_flat_rx_ops;init_waitqueue_head (&priv->vbus.rx_empty);/*
RFC PATCH v3 14/17 kvm: Add VBUS support to the host
In reply to Gregory HaskinsThis patch adds support for guest access to a VBUS assigned to the same context as the VM. It utilizes a IOQ+IRQ to move events from host->guest, and provides a hypercall interface to move events guest->host.
Special thanks to Alex Tsariounov for submitting patches for cleaning up some sloppy warnings I had left in the code.
---
arch/x86/include/asm/kvm_para.h | 1 arch/x86/kvm/Kconfig | 9 arch/x86/kvm/Makefile | 3 arch/x86/kvm/x86.c | 6 arch/x86/kvm/x86.h | 12 include/linux/kvm.h | 7 include/linux/kvm_host.h | 26 + include/linux/kvm_para.h | 58 ++ virt/kvm/kvm_main.c | 10 virt/kvm/vbus.c | 1392 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 1524 insertions(+), 0 deletions(-) create mode 100644 virt/kvm/vbus.c
arch/x86/include/asm/kvm_para.h +1 -0
@@ -13,6 +13,7 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +#define KVM_FEATURE_VBUS 3#define MSR_KVM_WALL_CLOCK 0x11#define MSR_KVM_SYSTEM_TIME 0x12
arch/x86/kvm/Kconfig +9 -0
@@ -69,6 +69,15 @@ config KVM_TRACE relayfs. Note the ABI is not considered stable and will be modified in future updates. +config KVM_HOST_VBUS + bool "KVM virtual-bus (VBUS) host-side support" + depends on KVM + select VBUS + default n + ---help--- + This option enables host-side support for accessing virtual-bus + devices. + # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source drivers/lguest/Kconfig
arch/x86/kvm/Makefile +3 -0
@@ -15,6 +15,9 @@ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \ i8254.o +ifeq ($(CONFIG_KVM_HOST_VBUS),y) +kvm-objs += $(addprefix ../../../virt/kvm/, vbus.o) +endif obj-$(CONFIG_KVM) += kvm.o kvm-intel-objs = vmx.o obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
arch/x86/kvm/x86.c +6 -0
@@ -1040,6 +1040,9 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_IOMMU : r =iommu_found ();break ; +case KVM_CAP_VBUS : + r =kvm_vbus_support (); +break ;default : r =0 ;break ;
@@ -2830,6 +2833,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)case KVM_HC_MMU_OP : r =kvm_pv_mmu_op (vcpu, a0,hc_gpa (vcpu, a1, a2), &ret);break ; +case KVM_HC_VBUS : + ret =kvm_vbus_hc (vcpu, a0, a1, a2); +break ;default : ret = -KVM_ENOSYS ;break ;
arch/x86/kvm/x86.h +12 -0
@@ -3,6 +3,18 @@#include <linux/kvm_host.h> +#ifdef CONFIG_KVM_HOST_VBUS +static inline int kvm_vbus_support (void ) +{ +return 1 ; +} +#else +static inline int kvm_vbus_support (void ) +{ +return 0 ; +} +#endif +static inline void kvm_clear_exception_queue (struct kvm_vcpu *vcpu) { vcpu->arch.exception.pending = false;
include/linux/kvm.h +7 -0
@@ -409,6 +409,7 @@ struct kvm_trace_rec {#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT#define KVM_CAP_DEVICE_DEASSIGNMENT 27#endif +#define KVM_CAP_VBUS 28#ifdef KVM_CAP_IRQ_ROUTING
@@ -448,6 +449,11 @@ struct kvm_irq_routing {#endif +struct kvm_vbus_gsi { +__u32 queue; +__u32 gsi; +}; +/* * ioctls for VM fds */
@@ -485,6 +491,7 @@ struct kvm_irq_routing {#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \ struct kvm_assigned_pci_dev) +#define KVM_VBUS_ASSIGN_GSI _IOW(KVMIO, 0x73, struct kvm_vbus_gsi)/* * ioctls for vcpu fds
include/linux/kvm_host.h +26 -0
@@ -134,6 +134,9 @@ struct kvm {struct list_head vm_list;struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus; +#ifdef CONFIG_KVM_HOST_VBUS +struct kvm_vbus *kvbus; +#endif struct kvm_vm_stat stat;struct kvm_arch arch;atomic_t users_count;
@@ -512,4 +515,27 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}#endif +#ifdef CONFIG_KVM_HOST_VBUS + +int kvm_vbus_hc (struct kvm_vcpu *vcpu,int nr,gpa_t gpa,size_t len); +void kvm_vbus_release (struct kvm_vbus *kvbus); +int kvm_vbus_assign_gsi (struct kvm *kvm,int queue,int gsi); + +#else /* CONFIG_KVM_HOST_VBUS */ + +static inline int +kvm_vbus_hc (struct kvm_vcpu *vcpu,int nr,gpa_t gpa,size_t len) +{ +return -EINVAL ; +} + +#define kvm_vbus_release (kvbus) do {} while (0) + +static inline int kvm_vbus_assign_gsi (struct kvm *kvm,int queue,int gsi) +{ +return -EINVAL ; +} + +#endif /* CONFIG_KVM_HOST_VBUS */ +#endif
include/linux/kvm_para.h +58 -0
64 lines not on this page · raw message
virt/kvm/kvm_main.c +10 -0
@@ -901,6 +901,7 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) {struct kvm *kvm = filp->private_data; +kvm_vbus_release (kvm->kvbus);kvm_put_kvm (kvm);return 0 ; }
@@ -1920,6 +1921,15 @@ static long kvm_vm_ioctl(struct file *filp, break; }#endif +case KVM_VBUS_ASSIGN_GSI : { +struct kvm_vbus_gsi data; + + r = -EFAULT ; +if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_vbus_assign_gsi (kvm, data.queue, data.gsi); +break ; + }default : r =kvm_arch_vm_ioctl (filp, ioctl, arg); }
virt/kvm/vbus.c new file +1392 -0
1,392 lines not on this page · raw message
RFC PATCH v3 15/17 kvm: Add guest-side support for VBUS
In reply to Gregory HaskinsThis adds a driver to interface between the host VBUS support, and the guest-vbus bus model.
---
arch/x86/Kconfig | 9 + drivers/Makefile | 1 drivers/vbus/proxy/Makefile | 2 drivers/vbus/proxy/kvm.c | 751 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 763 insertions(+), 0 deletions(-) create mode 100644 drivers/vbus/proxy/Makefile create mode 100644 drivers/vbus/proxy/kvm.c
arch/x86/Kconfig +9 -0
@@ -486,6 +486,15 @@ config KVM_GUEST This option enables various optimizations for running under the KVM hypervisor. +config KVM_GUEST_VBUS + tristate "KVM virtual-bus (VBUS) guest-side support" + depends on KVM_GUEST + select VBUS_DRIVERS + default y + ---help--- + This option enables guest-side support for accessing virtual-bus + devices. + source "arch/x86/lguest/Kconfig" config PARAVIRT
drivers/Makefile +1 -0
@@ -108,3 +108,4 @@ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ obj-$(CONFIG_VBUS_DEVICES) += vbus/devices/ +obj-$(CONFIG_VBUS_DRIVERS) += vbus/proxy/
drivers/vbus/proxy/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +kvm-guest-vbus-objs += kvm.o +obj-$(CONFIG_KVM_GUEST_VBUS) += kvm-guest-vbus.o
drivers/vbus/proxy/kvm.c new file +751 -0
751 lines not on this page · raw message
RFC PATCH v3 16/17 vbus: add a userspace connector
In reply to Gregory HaskinsThis allows userspace applications to access vbus devices
---
include/linux/vbus.h | 4 include/linux/vbus_client.h | 2 include/linux/vbus_userspace.h | 48 ++++ kernel/vbus/Kconfig | 10 + kernel/vbus/Makefile | 2 kernel/vbus/userspace-client.c | 485 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 550 insertions(+), 1 deletions(-) create mode 100644 include/linux/vbus_userspace.h create mode 100644 kernel/vbus/userspace-client.c
include/linux/vbus.h +4 -0
@@ -23,6 +23,8 @@#ifndef _LINUX_VBUS_H#define _LINUX_VBUS_H +#ifdef __KERNEL__ +#ifdef CONFIG_VBUS #include <linux/module.h>
@@ -159,4 +161,6 @@ int vbus_notifier_unregister(struct vbus *vbus, struct notifier_block *nb);#endif /* CONFIG_VBUS */ +#endif /* __KERNEL__ */ +#endif /* _LINUX_VBUS_H */
include/linux/vbus_client.h +1 -1
@@ -35,7 +35,7 @@#ifndef _LINUX_VBUS_CLIENT_H#define _LINUX_VBUS_CLIENT_H -#include <linux/types.h> +#include <asm/types.h> #include <linux/compiler.h> struct vbus_deviceopen {
include/linux/vbus_userspace.h new file +48 -0
48 lines not on this page · raw message
kernel/vbus/Kconfig +10 -0
@@ -25,6 +25,16 @@ config VBUS_DEVICES source "drivers/vbus/devices/Kconfig" +config VBUS_USERSPACE + tristate "Virtual-Bus userspace client support" + depends on VBUS + default y + help + Provides facilities for userspace applications to access virtual- + bus objects. + + If unsure, say N + config VBUS_DRIVERS tristate "VBUS Driver support" select IOQ
kernel/vbus/Makefile +2 -0
@@ -4,3 +4,5 @@ obj-$(CONFIG_VBUS) += shm-ioq.o vbus-proxy-objs += proxy.o obj-$(CONFIG_VBUS_DRIVERS) += vbus-proxy.o +vbus-userspace-objs += userspace-client.o +obj-$(CONFIG_VBUS_USERSPACE) += vbus-userspace.o
kernel/vbus/userspace-client.c new file +485 -0
485 lines not on this page · raw message
RFC PATCH v3 17/17 virtio: add a vbus transport
In reply to Gregory HaskinsWe add a new virtio transport for accessing backends located on vbus. This complements the existing transports for virtio-pci, virtio-s390, and virtio-lguest that already exist.
---
drivers/virtio/Kconfig | 15 + drivers/virtio/Makefile | 1 drivers/virtio/virtio_vbus.c | 496 +++++++++++++++++++++++++++++++++ include/linux/virtio_vbus.h | 163 +++++++++++ kernel/vbus/Kconfig | 8 + kernel/vbus/Makefile | 3 kernel/vbus/virtio.c | 627 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1313 insertions(+), 0 deletions(-) create mode 100644 drivers/virtio/virtio_vbus.c create mode 100644 include/linux/virtio_vbus.h create mode 100644 kernel/vbus/virtio.c
drivers/virtio/Kconfig +15 -0
@@ -23,6 +23,21 @@ config VIRTIO_PCI If unsure, say M. +config VIRTIO_VBUS + tristate "VBUS driver for virtio devices (EXPERIMENTAL)" + depends on VBUS_DRIVERS && EXPERIMENTAL + select VIRTIO + select VIRTIO_RING + ---help--- + This drivers provides support for virtio based paravirtual device + drivers over VBUS. This requires that your VMM has appropriate VBUS + virtio backends. + + Currently, the ABI is not considered stable so there is no guarantee + that this version of the driver will work with your VMM. + + If unsure, say M. + config VIRTIO_BALLOON tristate "Virtio balloon driver (EXPERIMENTAL)" select VIRTIO
drivers/virtio/Makefile +1 -0
@@ -1,4 +1,5 @@ obj-$(CONFIG_VIRTIO) += virtio.o obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o +obj-$(CONFIG_VIRTIO_VBUS) += virtio_vbus.o obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
drivers/virtio/virtio_vbus.c new file +496 -0
496 lines not on this page · raw message
include/linux/virtio_vbus.h new file +163 -0
163 lines not on this page · raw message
kernel/vbus/Kconfig +8 -0
@@ -14,6 +14,14 @@ config VBUS If unsure, say N +config VBUS_VIRTIO_BACKEND + tristate "Virtio VBUS Backend" + depends on VIRTIO_RING + depends on VBUS + default n + help + Provides backend support for virtio devices over vbus + config VBUS_DEVICES bool "Virtual-Bus Devices" depends on VBUS
kernel/vbus/Makefile +3 -0
@@ -1,6 +1,9 @@ obj-$(CONFIG_VBUS) += core.o devclass.o config.o attribute.o map.o client.o obj-$(CONFIG_VBUS) += shm-ioq.o +virtio-backend-objs += virtio.o +obj-$(CONFIG_VBUS_VIRTIO_BACKEND) += virtio-backend.o + vbus-proxy-objs += proxy.o obj-$(CONFIG_VBUS_DRIVERS) += vbus-proxy.o
kernel/vbus/virtio.c new file +627 -0
627 lines not on this page · raw message
Hi Gregory,
I'd like to try Your vbus patches, but compiling 2.6.30-rc2 (or 2.6.30-rc5) fails
with following error:drivers/vbus/proxy/kvm-guest-vbus: struct pci_device_id is 32 bytes. The last of 1 is:0xda 0x11 0x00 0x00 0x00 0x20 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
FATAL: drivers/vbus/proxy/kvm-guest-vbus: struct pci_device_id is not terminated with a NULL entry!
Do You have any idea on what might be wrong?
thanks a lot in advance...
BR
nik
Quoted 221 lines · Gregory Haskins
RFC: Virtual-Bus (applies to v2.6.30-rc2)
----------------------Virtual-Bus is a Linux-kernel based virtual IO resource container technology. It allows you to declare virtualized device models directly within a host kernel that can be uniformly accessed from a variety of environments, such as KVM, userspace, lguest, Xen, etc. The goal is to reduce overhead while still preserving proper isolation to achieve maximum throughput and latency from your IO subsystem. It is installed on the host and configured using simple filesystem operations like "mkdir" to create a new container, "ln -s" to associate a device with a container, and "echo" to configure the device thanks to integration with configfs/sysfs. Therefore, managing a virtual-bus does not require special userspace tools.
Why would we want this?
----------------------We believe that a combination of in-kernel models, coupled with optimizations in various areas such as reducing the number of context switches and executing the algorithms in parallel on modern multicore CPUs will result in the best possible IO performance for technologies such as virtualization. This facility aims to provide the framework for building such constructs in in software in the most efficient way we believe is possible.
Preliminary Results:
-----------------------As a test, we wrote a virtual-ethernet backend and a Linux driver (called venet) and tested the setup with v2.6.29 on two 8-core
x86_64boxes with Chelsio T3 10GE connected back to back via cross over. We measured bare-metal performance, as well as a kvm guest (running the same kernel) connected to the T3 via a linux-bridge+tap configuration with a 1500 MTU. The results are as follows:Bare metal : tput = 4078Mb/s, round-trip = 25593pps (39us rtt)
Virtio-net (PCI) : tput = 4003Mb/s, round-trip = 320pps (3125us rtt)
Venet (VBUS): tput = 4050Mb/s, round-trip = 15255 (65us rtt)When we jump to 9000 byte MTU, the situation looks similar
Bare metal : tput = 9717Mb/s, round-trip = 30396pps (33us rtt)
Virtio-net (PCI) : tput = 4578Mb/s, round-trip = 249pps (4016us rtt)
Venet (VBUS): tput = 5802Mb/s, round-trip = 15127 (66us rtt)Note that to be fair, part of the latency response from virtio-pci is due to the way that the driver/backend coalesces packets, and not a true limitation of the userspace path as the results may imply. Anthony Liguori is already looking into improving this based on the results we presented here, and is making good headway.
Also note that as of v2, we support a virtio-vbus transport, and therefore will soon be able to compare "Virtio-net (VBUS)" as an additional target in the near future once we have developed a virtio-net backend for the host. This virtio-net(pci) to virtio-net(vbus) comparison is probably more interesting than comparing to Venet as it would be more apples to apples. Also it would be nice to only need one PV driver per IO subsystem in the long term.
Changes
v2->v3:
------------------*) VBUS now renders as a PCI/MSI device instead of via cpuid/dynirq *) Dropped dynirq (replaced with MSI facility)
*) Dropped "reset" patch in favor of more reliably detecting reset via BUSOPEN *) Incorporated more review feedback from Stephen Hemminger on vbus-enet
driver
*) Added support for setting the guests MAC during host config (Pat Mullaney) *) Cleaned up documentation per feedback from Ben Hutchings
*) Numerous small tweaks to clean up things like warnings, comments, etc.
(Alex Tsariounov, Greg Haskins)
*) FixedKconfigdependency problem with virtio-vbus with feedback from
Peter Morreale.Changes
v1->v2:*) Incorporated review feedback from Stephen Hemminger on vbus-enet driver *) Added support for connecting to vbus devices from userspace *) Added support for a virtio-vbus transport to allow virtio drivers to
work with vbus (needs testing and backend models).Todo:
*) Beef up the userspace event channel ABI to support different event types *) Add memory-registration support
*) Develop some virtio backend devices.
*) Supportethtool_opsfor venet.
*) Convert from MSI to MSIX to truely support multiple vectors---------------------------------------
For more details, please see our Wiki at
http://developer.novell.com/wiki/index.php/Virtual-bus
---
Gregory Haskins (16):
virtio: add a vbus transport
vbus: add a userspace connector
kvm: Add guest-side support for VBUS
kvm: Add VBUS support to the host
venettap: add scatter-gather support
venet: add scatter-gather support
venet-tap: Adds a "venet" compatible "tap" device to VBUS
net: Addvbus_enetdriver
venet: add the ABI definitions for an 802.x packet interface
ioq: add vbus helpers
ioq: Add basic definitions for a shared-memory, lockless queue
vbus: add a "vbus-proxy" bus model forvbus_driverobjects
vbus: add bus-registration notifiers
vbus: add connection-client helper infrastructure
vbus: add virtual-bus definitions
shm-signal: shared-memory signalsPatrick Mullaney (1):
venet-tap: add the ability to set the client's mac address via sysfsDocumentation/vbus.txt | 385 +++++++++ arch/x86/Kconfig | 11 arch/x86/include/asm/kvm_para.h | 1 arch/x86/kvm/Kconfig | 9 arch/x86/kvm/Makefile | 3 arch/x86/kvm/x86.c | 6 arch/x86/kvm/x86.h | 12 drivers/Makefile | 2 drivers/net/Kconfig | 13 drivers/net/Makefile | 1 drivers/net/vbus-enet.c | 898 +++++++++++++++++++++ drivers/vbus/devices/Kconfig | 17 drivers/vbus/devices/Makefile | 1 drivers/vbus/devices/venet-tap.c | 1641 ++++++++++++++++++++++++++++++++++++++ drivers/vbus/proxy/Makefile | 2 drivers/vbus/proxy/kvm.c | 751 +++++++++++++++++ drivers/virtio/Kconfig | 15 drivers/virtio/Makefile | 1 drivers/virtio/virtio_vbus.c | 496 +++++++++++ fs/proc/base.c | 96 ++ include/linux/ioq.h | 410 +++++++++ include/linux/kvm.h | 7 include/linux/kvm_host.h | 26 + include/linux/kvm_para.h | 58 + include/linux/sched.h | 4 include/linux/shm_signal.h | 188 ++++ include/linux/vbus.h | 166 ++++ include/linux/vbus_client.h | 115 +++ include/linux/vbus_device.h | 424 ++++++++++ include/linux/vbus_driver.h | 80 ++ include/linux/vbus_userspace.h | 48 + include/linux/venet.h | 82 ++ include/linux/virtio_vbus.h | 163 ++++ kernel/Makefile | 1 kernel/exit.c | 2 kernel/fork.c | 2 kernel/vbus/Kconfig | 56 + kernel/vbus/Makefile | 11 kernel/vbus/attribute.c | 52 + kernel/vbus/client.c | 543 +++++++++++++ kernel/vbus/config.c | 275 ++++++ kernel/vbus/core.c | 626 ++++++++++++++ kernel/vbus/devclass.c | 124 +++ kernel/vbus/map.c | 72 ++ kernel/vbus/map.h | 41 + kernel/vbus/proxy.c | 216 +++++ kernel/vbus/shm-ioq.c | 89 ++ kernel/vbus/userspace-client.c | 485 +++++++++++ kernel/vbus/vbus.h | 117 +++ kernel/vbus/virtio.c | 627 +++++++++++++++ lib/Kconfig | 21 lib/Makefile | 2 lib/ioq.c | 298 +++++++ lib/shm_signal.c | 186 ++++ virt/kvm/kvm_main.c | 10 virt/kvm/vbus.c | 1392 ++++++++++++++++++++++++++++++++ 56 files changed, 11380 insertions(+), 0 deletions(-) create mode 100644 Documentation/vbus.txt create mode 100644 drivers/net/vbus-enet.c create mode 100644 drivers/vbus/devices/Kconfig create mode 100644 drivers/vbus/devices/Makefile create mode 100644 drivers/vbus/devices/venet-tap.c create mode 100644 drivers/vbus/proxy/Makefile create mode 100644 drivers/vbus/proxy/kvm.c create mode 100644 drivers/virtio/virtio_vbus.c create mode 100644 include/linux/ioq.h create mode 100644 include/linux/shm_signal.h create mode 100644 include/linux/vbus.h create mode 100644 include/linux/vbus_client.h create mode 100644 include/linux/vbus_device.h create mode 100644 include/linux/vbus_driver.h create mode 100644 include/linux/vbus_userspace.h create mode 100644 include/linux/venet.h create mode 100644 include/linux/virtio_vbus.h create mode 100644 kernel/vbus/Kconfig create mode 100644 kernel/vbus/Makefile create mode 100644 kernel/vbus/attribute.c create mode 100644 kernel/vbus/client.c create mode 100644 kernel/vbus/config.c create mode 100644 kernel/vbus/core.c create mode 100644 kernel/vbus/devclass.c create mode 100644 kernel/vbus/map.c create mode 100644 kernel/vbus/map.h create mode 100644 kernel/vbus/proxy.c create mode 100644 kernel/vbus/shm-ioq.c create mode 100644 kernel/vbus/userspace-client.c create mode 100644 kernel/vbus/vbus.h create mode 100644 kernel/vbus/virtio.c create mode 100644 lib/ioq.c create mode 100644 lib/shm_signal.c create mode 100644 virt/kvm/vbus.cSignature · 5 lines
-- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Signature · 14 lines
------------------------------------- Nikola CIPRICH LinuxBox.cz, s.r.o. 28. rijna 168, 709 01 Ostrava tel.: +420 596 603 142 fax: +420 596 621 273 mobil: +420 777 093 799 www.linuxbox.cz mobil servis: +420 737 238 656 email servis: [email protected] -------------------------------------
Quoted 11 lines · Nikola Ciprich
Hi Gregory,
I'd like to try Your vbus patches, but compiling 2.6.30-rc2 (or 2.6.30-rc5) fails
with following error:drivers/vbus/proxy/kvm-guest-vbus: structpci_device_idis 32 bytes. The last of 1 is:0xda0x110x000x000x000x200x000x000xff0xff0xff0xff0xff0xff0xff0xff0x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x00
FATAL:drivers/vbus/proxy/kvm-guest-vbus: structpci_device_idis not terminated with a NULL entry!Do You have any idea on what might be wrong?
thanks a lot in advance...
Hi Nik,
I haven't seen that error with vbus itself, but oddly enough I just
encountered something similar when I was working on a different series
(nullio). The fix there was trivial, and I suspect it will be here as
well. What I am more confused on is why this suddenly started happening.... I will get back to you with a fix.
Regards,
-Greg