kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gregory Haskins <ghaskins@novell.com>
To: linux-kernel@vger.kernel.org
Cc: agraf@suse.de, pmullaney@novell.com, pmorreale@novell.com,
	anthony@codemonkey.ws, rusty@rustcorp.com.au,
	netdev@vger.kernel.org, kvm@vger.kernel.org
Subject: [RFC PATCH 03/17] vbus: add connection-client helper infrastructure
Date: Tue, 31 Mar 2009 14:43:02 -0400	[thread overview]
Message-ID: <20090331184302.28333.18745.stgit@dev.haskins.net> (raw)
In-Reply-To: <20090331184057.28333.77287.stgit@dev.haskins.net>

We 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.

Signed-off-by: Gregory Haskins <ghaskins@novell.com>
---

 include/linux/vbus_client.h |  115 +++++++++
 kernel/vbus/Makefile        |    2 
 kernel/vbus/client.c        |  527 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 643 insertions(+), 1 deletions(-)
 create mode 100644 include/linux/vbus_client.h
 create mode 100644 kernel/vbus/client.c

diff --git a/include/linux/vbus_client.h b/include/linux/vbus_client.h
new file mode 100644
index 0000000..62dab78
--- /dev/null
+++ b/include/linux/vbus_client.h
@@ -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 <ghaskins@novell.com>
+ *
+ * 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 */
diff --git a/kernel/vbus/Makefile b/kernel/vbus/Makefile
index 367f65b..4d440e5 100644
--- a/kernel/vbus/Makefile
+++ b/kernel/vbus/Makefile
@@ -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
diff --git a/kernel/vbus/client.c b/kernel/vbus/client.c
new file mode 100644
index 0000000..ff8d6df
--- /dev/null
+++ b/kernel/vbus/client.c
@@ -0,0 +1,527 @@
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/uaccess.h>
+#include <linux/vbus.h>
+#include <linux/vbus_client.h>
+#include "vbus.h"
+
+static int
+nodeptr_item_compare(struct rb_node *lhs, struct rb_node *rhs)
+{
+	unsigned long l = (unsigned long)lhs;
+	unsigned long r = (unsigned long)rhs;
+
+	return l - r;
+}
+
+static int
+nodeptr_key_compare(const void *key, struct rb_node *node)
+{
+	unsigned long item = (unsigned long)node;
+	unsigned long _key = *(unsigned long *)key;
+
+	return _key - item;
+}
+
+static struct map_ops nodeptr_map_ops = {
+	.key_compare = &nodeptr_key_compare,
+	.item_compare = &nodeptr_item_compare,
+};
+
+struct _signal {
+	atomic_t refs;
+	struct rb_node node;
+	struct list_head list;
+	struct shm_signal *signal;
+};
+
+struct _connection {
+	atomic_t refs;
+	struct rb_node node;
+	struct list_head signals;
+	struct vbus_connection *conn;
+};
+
+static inline void _signal_get(struct _signal *_signal)
+{
+	atomic_inc(&_signal->refs);
+}
+
+static inline void _signal_put(struct _signal *_signal)
+{
+	if (atomic_dec_and_test(&_signal->refs)) {
+		shm_signal_put(_signal->signal);
+		kfree(_signal);
+	}
+}
+
+static inline void conn_get(struct _connection *_conn)
+{
+	atomic_inc(&_conn->refs);
+}
+
+static inline void conn_put(struct _connection *_conn)
+{
+	if (atomic_dec_and_test(&_conn->refs)) {
+		struct _signal *_signal, *tmp;
+
+		list_for_each_entry_safe(_signal, tmp, &_conn->signals,
+					 list) {
+			list_del(&_signal->list);
+			_signal_put(_signal);
+		}
+
+		vbus_connection_put(_conn->conn);
+		kfree(_conn);
+	}
+}
+
+struct _client {
+	struct mutex lock;
+	struct map conn_map;
+	struct map signal_map;
+	struct vbus *vbus;
+	struct vbus_client client;
+};
+
+struct _connection *to_conn(struct rb_node *node)
+{
+	return node ? container_of(node, struct _connection, node) : NULL;
+}
+
+static struct _signal *to_signal(struct rb_node *node)
+{
+	return node ? container_of(node, struct _signal, node) : NULL;
+}
+
+static struct _client *to_client(struct vbus_client *client)
+{
+	return container_of(client, struct _client, client);
+}
+
+static struct _connection *
+connection_find(struct _client *c, unsigned long devid)
+{
+	struct _connection *_conn;
+
+	/*
+	 * We could, in theory, cast devid to _conn->node, but this would
+	 * be pretty stupid to trust.  Therefore, we must validate that
+	 * the pointer is legit by seeing if it exists in our conn_map
+	 */
+
+	mutex_lock(&c->lock);
+
+	_conn = to_conn(map_find(&c->conn_map, &devid));
+	if (likely(_conn))
+		conn_get(_conn);
+
+	mutex_unlock(&c->lock);
+
+	return _conn;
+}
+
+static int
+_deviceopen(struct vbus_client *client, struct vbus_memctx *ctx,
+	    __u32 devid, __u32 version, __u64 *devh)
+{
+	struct _client *c = to_client(client);
+	struct vbus_connection *conn;
+	struct _connection *_conn;
+	struct vbus_device_interface *intf = NULL;
+	int ret;
+
+	/*
+	 * We only get here if the device has never been opened before,
+	 * so we need to create a new connection
+	 */
+	ret = vbus_interface_find(c->vbus, devid, &intf);
+	if (ret < 0)
+		return ret;
+
+	ret = intf->ops->open(intf, ctx, version, &conn);
+	kobject_put(&intf->kobj);
+	if (ret < 0)
+		return ret;
+
+	_conn = kzalloc(sizeof(*_conn), GFP_KERNEL);
+	if (!_conn) {
+		vbus_connection_put(conn);
+		return -ENOMEM;
+	}
+
+	atomic_set(&_conn->refs, 1);
+	_conn->conn = conn;
+
+	INIT_LIST_HEAD(&_conn->signals);
+
+	mutex_lock(&c->lock);
+	ret = map_add(&c->conn_map, &_conn->node);
+	mutex_unlock(&c->lock);
+
+	if (ret < 0) {
+		conn_put(_conn);
+		return ret;
+	}
+
+	/* in theory, &_conn->node should be unique */
+	*devh = (__u64)&_conn->node;
+
+	return 0;
+
+}
+
+/*
+ * Assumes client->lock is held (or we are releasing and dont need to lock)
+ */
+static void
+conn_del(struct _client *c, struct _connection *_conn)
+{
+	struct _signal *_signal, *tmp;
+
+	/* Delete and release each opened queue */
+	list_for_each_entry_safe(_signal, tmp, &_conn->signals, list) {
+		map_del(&c->signal_map, &_signal->node);
+		_signal_put(_signal);
+	}
+
+	map_del(&c->conn_map, &_conn->node);
+}
+
+static int
+_deviceclose(struct vbus_client *client, __u64 devh)
+{
+	struct _client *c = to_client(client);
+	struct _connection *_conn;
+
+	mutex_lock(&c->lock);
+
+	_conn = to_conn(map_find(&c->conn_map, &devh));
+	if (likely(_conn))
+		conn_del(c, _conn);
+
+	mutex_unlock(&c->lock);
+
+	if (unlikely(!_conn))
+		return -ENOENT;
+
+	/* this _put is the compliment to the _get performed at _deviceopen */
+	conn_put(_conn);
+
+	return 0;
+}
+
+static int
+_devicecall(struct vbus_client *client,
+	    __u64 devh, __u32 func, void *data, __u32 len, __u32 flags)
+{
+	struct _client *c = to_client(client);
+	struct _connection *_conn;
+	struct vbus_connection *conn;
+	int ret;
+
+	_conn = connection_find(c, devh);
+	if (!_conn)
+		return -ENOENT;
+
+	conn = _conn->conn;
+
+	ret = conn->ops->call(conn, func, data, len, flags);
+
+	conn_put(_conn);
+
+	return ret;
+}
+
+static int
+_deviceshm(struct vbus_client *client,
+	   __u64 devh,
+	   __u32 id,
+	   struct vbus_shm *shm,
+	   struct shm_signal *signal,
+	   __u32 flags,
+	   __u64 *handle)
+{
+	struct _client *c = to_client(client);
+	struct _signal *_signal = NULL;
+	struct _connection *_conn;
+	struct vbus_connection *conn;
+	int ret;
+
+	*handle = 0;
+
+	_conn = connection_find(c, devh);
+	if (!_conn)
+		return -ENOENT;
+
+	conn = _conn->conn;
+
+	ret = conn->ops->shm(conn, id, shm, signal, flags);
+	if (ret < 0) {
+		conn_put(_conn);
+		return ret;
+	}
+
+	if (signal) {
+		_signal = kzalloc(sizeof(*_signal), GFP_KERNEL);
+		if (!_signal) {
+			conn_put(_conn);
+			return -ENOMEM;
+		}
+
+		 /* one for map-ref, one for list-ref */
+		atomic_set(&_signal->refs, 2);
+		_signal->signal = signal;
+		shm_signal_get(signal);
+
+		mutex_lock(&c->lock);
+		ret = map_add(&c->signal_map, &_signal->node);
+		list_add_tail(&_signal->list, &_conn->signals);
+		mutex_unlock(&c->lock);
+
+		if (!ret)
+			*handle = (__u64)&_signal->node;
+	}
+
+	conn_put(_conn);
+
+	return 0;
+}
+
+static int
+_shmsignal(struct vbus_client *client, __u64 handle)
+{
+	struct _client *c = to_client(client);
+	struct _signal *_signal;
+
+	mutex_lock(&c->lock);
+
+	_signal = to_signal(map_find(&c->signal_map, &handle));
+	if (likely(_signal))
+		_signal_get(_signal);
+
+	mutex_unlock(&c->lock);
+
+	if (!_signal)
+		return -ENOENT;
+
+	_shm_signal_wakeup(_signal->signal);
+
+	_signal_put(_signal);
+
+	return 0;
+}
+
+static void
+_release(struct vbus_client *client)
+{
+	struct _client *c = to_client(client);
+	struct rb_node *node;
+
+	/* Drop all of our open connections */
+	while ((node = rb_first(&c->conn_map.root))) {
+		struct _connection *_conn = to_conn(node);
+
+		conn_del(c, _conn);
+		conn_put(_conn);
+	}
+
+	vbus_put(c->vbus);
+	kfree(c);
+}
+
+struct vbus_client_ops _client_ops = {
+	.deviceopen  = _deviceopen,
+	.deviceclose = _deviceclose,
+	.devicecall  = _devicecall,
+	.deviceshm   = _deviceshm,
+	.shmsignal   = _shmsignal,
+	.release     = _release,
+};
+
+struct vbus_client *vbus_client_attach(struct vbus *vbus)
+{
+	struct _client *c;
+
+	BUG_ON(!vbus);
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return NULL;
+
+	atomic_set(&c->client.refs, 1);
+	c->client.ops = &_client_ops;
+
+	mutex_init(&c->lock);
+	map_init(&c->conn_map, &nodeptr_map_ops);
+	map_init(&c->signal_map, &nodeptr_map_ops);
+	c->vbus = vbus_get(vbus);
+
+	return &c->client;
+}
+EXPORT_SYMBOL_GPL(vbus_client_attach);
+
+/*
+ * memory context helpers
+ */
+
+static unsigned long
+current_memctx_copy_to(struct vbus_memctx *ctx, void *dst, const void *src,
+		       unsigned long len)
+{
+	return copy_to_user(dst, src, len);
+}
+
+static unsigned long
+current_memctx_copy_from(struct vbus_memctx *ctx, void *dst, const void *src,
+			 unsigned long len)
+{
+	return copy_from_user(dst, src, len);
+}
+
+static void
+current_memctx_release(struct vbus_memctx *ctx)
+{
+	panic("dropped last reference to current_memctx");
+}
+
+static struct vbus_memctx_ops current_memctx_ops = {
+	.copy_to   = &current_memctx_copy_to,
+	.copy_from = &current_memctx_copy_from,
+	.release   = &current_memctx_release,
+};
+
+static struct vbus_memctx _current_memctx =
+	VBUS_MEMCTX_INIT((&current_memctx_ops));
+
+struct vbus_memctx *current_memctx = &_current_memctx;
+
+/*
+ * task_mem allows you to have a copy_from_user/copy_to_user like
+ * environment, except that it supports copying to tasks other
+ * than "current" as ctu/cfu() do
+ */
+struct task_memctx {
+	struct task_struct *task;
+	struct vbus_memctx ctx;
+};
+
+static struct task_memctx *to_task_memctx(struct vbus_memctx *ctx)
+{
+	return container_of(ctx, struct task_memctx, ctx);
+}
+
+static unsigned long
+task_memctx_copy_to(struct vbus_memctx *ctx, void *dst, const void *src,
+		    unsigned long n)
+{
+	struct task_memctx *tm = to_task_memctx(ctx);
+	struct task_struct *p = tm->task;
+
+	while (n) {
+		unsigned long offset = ((unsigned long)dst)%PAGE_SIZE;
+		unsigned long len = PAGE_SIZE - offset;
+		int ret;
+		struct page *pg;
+		void *maddr;
+
+		if (len > n)
+			len = n;
+
+		down_read(&p->mm->mmap_sem);
+		ret = get_user_pages(p, p->mm,
+				     (unsigned long)dst, 1, 1, 0, &pg, NULL);
+
+		if (ret != 1) {
+			up_read(&p->mm->mmap_sem);
+			break;
+		}
+
+		maddr = kmap_atomic(pg, KM_USER0);
+		memcpy(maddr + offset, src, len);
+		kunmap_atomic(maddr, KM_USER0);
+		set_page_dirty_lock(pg);
+		put_page(pg);
+		up_read(&p->mm->mmap_sem);
+
+		src += len;
+		dst += len;
+		n -= len;
+	}
+
+	return n;
+}
+
+static unsigned long
+task_memctx_copy_from(struct vbus_memctx *ctx, void *dst, const void *src,
+		      unsigned long n)
+{
+	struct task_memctx *tm = to_task_memctx(ctx);
+	struct task_struct *p = tm->task;
+
+	while (n) {
+		unsigned long offset = ((unsigned long)src)%PAGE_SIZE;
+		unsigned long len = PAGE_SIZE - offset;
+		int ret;
+		struct page *pg;
+		void *maddr;
+
+		if (len > n)
+			len = n;
+
+		down_read(&p->mm->mmap_sem);
+		ret = get_user_pages(p, p->mm,
+				     (unsigned long)src, 1, 1, 0, &pg, NULL);
+
+		if (ret != 1) {
+			up_read(&p->mm->mmap_sem);
+			break;
+		}
+
+		maddr = kmap_atomic(pg, KM_USER0);
+		memcpy(dst, maddr + offset, len);
+		kunmap_atomic(maddr, KM_USER0);
+		put_page(pg);
+		up_read(&p->mm->mmap_sem);
+
+		src += len;
+		dst += len;
+		n -= len;
+	}
+
+	return n;
+}
+
+static void
+task_memctx_release(struct vbus_memctx *ctx)
+{
+	struct task_memctx *tm = to_task_memctx(ctx);
+
+	put_task_struct(tm->task);
+	kfree(tm);
+}
+
+static struct vbus_memctx_ops task_memctx_ops = {
+	.copy_to   = &task_memctx_copy_to,
+	.copy_from = &task_memctx_copy_from,
+	.release   = &task_memctx_release,
+};
+
+struct vbus_memctx *task_memctx_alloc(struct task_struct *task)
+{
+	struct task_memctx *tm;
+
+	tm = kzalloc(sizeof(*tm), GFP_KERNEL);
+	if (!tm)
+		return NULL;
+
+	get_task_struct(task);
+
+	tm->task = task;
+	vbus_memctx_init(&tm->ctx, &task_memctx_ops);
+
+	return &tm->ctx;
+}
+EXPORT_SYMBOL_GPL(task_memctx_alloc);


  parent reply	other threads:[~2009-03-31 18:43 UTC|newest]

Thread overview: 146+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-31 18:42 [RFC PATCH 00/17] virtual-bus Gregory Haskins
2009-03-31 18:42 ` [RFC PATCH 01/17] shm-signal: shared-memory signals Gregory Haskins
2009-03-31 20:44   ` Avi Kivity
2009-03-31 20:58     ` Gregory Haskins
2009-03-31 21:05       ` Avi Kivity
2009-04-01 12:12         ` Gregory Haskins
2009-04-01 12:24           ` Avi Kivity
2009-04-01 13:57             ` Gregory Haskins
2009-03-31 18:42 ` [RFC PATCH 02/17] vbus: add virtual-bus definitions Gregory Haskins
2009-04-02 16:06   ` Ben Hutchings
2009-04-02 18:13     ` Gregory Haskins
2009-03-31 18:43 ` Gregory Haskins [this message]
2009-03-31 18:43 ` [RFC PATCH 04/17] vbus: add bus-registration notifiers Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 05/17] vbus: add a "vbus-proxy" bus model for vbus_driver objects Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 06/17] ioq: Add basic definitions for a shared-memory, lockless queue Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 07/17] ioq: add vbus helpers Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 08/17] venet: add the ABI definitions for an 802.x packet interface Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 09/17] net: Add vbus_enet driver Gregory Haskins
2009-03-31 20:39   ` Stephen Hemminger
2009-04-02 11:43     ` Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 10/17] venet-tap: Adds a "venet" compatible "tap" device to VBUS Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 11/17] venet: add scatter-gather support Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 12/17] venettap: " Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 13/17] x86: allow the irq->vector translation to be determined outside of ioapic Gregory Haskins
2009-03-31 19:16   ` Alan Cox
2009-03-31 20:02     ` Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 14/17] kvm: add a reset capability Gregory Haskins
2009-03-31 19:22   ` Avi Kivity
2009-03-31 20:02     ` Gregory Haskins
2009-03-31 20:18       ` Avi Kivity
2009-03-31 20:37         ` Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 15/17] kvm: add dynamic IRQ support Gregory Haskins
2009-03-31 19:20   ` Avi Kivity
2009-03-31 19:39     ` Gregory Haskins
2009-03-31 20:13       ` Avi Kivity
2009-03-31 20:32         ` Gregory Haskins
2009-03-31 20:59           ` Avi Kivity
2009-03-31 18:44 ` [RFC PATCH 16/17] kvm: Add VBUS support to the host Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 17/17] kvm: Add guest-side support for VBUS Gregory Haskins
2009-03-31 20:18 ` [RFC PATCH 00/17] virtual-bus Andi Kleen
2009-04-01 12:03   ` Gregory Haskins
2009-04-01 13:23     ` Andi Kleen
2009-04-01 14:19       ` Gregory Haskins
2009-04-01 14:42         ` Gregory Haskins
2009-04-01 17:01         ` Andi Kleen
2009-04-01 18:45           ` Anthony Liguori
2009-04-01 20:40             ` Chris Wright
2009-04-01 21:11               ` Gregory Haskins
2009-04-01 21:28                 ` Chris Wright
2009-04-01 22:10                   ` Gregory Haskins
2009-04-02  6:00                     ` Chris Wright
2009-04-02  3:11               ` Herbert Xu
2009-04-01 21:09             ` Gregory Haskins
2009-04-02  0:29               ` Anthony Liguori
2009-04-02  3:11                 ` Gregory Haskins
2009-04-02  6:51               ` Avi Kivity
2009-04-02  8:52                 ` Herbert Xu
2009-04-02  9:02                   ` Avi Kivity
2009-04-02  9:16                     ` Herbert Xu
2009-04-02  9:27                       ` Avi Kivity
2009-04-02  9:29                         ` Herbert Xu
2009-04-02  9:33                           ` Herbert Xu
2009-04-02  9:38                           ` Avi Kivity
2009-04-02  9:41                             ` Herbert Xu
2009-04-02  9:43                               ` Avi Kivity
2009-04-02  9:44                                 ` Herbert Xu
2009-04-02 11:06                             ` Gregory Haskins
2009-04-02 11:59                               ` Avi Kivity
2009-04-02 12:30                                 ` Gregory Haskins
2009-04-02 12:43                                   ` Avi Kivity
2009-04-02 13:03                                     ` Gregory Haskins
2009-04-02 12:13                               ` Rusty Russell
2009-04-02 12:50                                 ` Gregory Haskins
2009-04-02 12:52                                   ` Gregory Haskins
2009-04-02 13:07                                   ` Avi Kivity
2009-04-02 13:22                                     ` Gregory Haskins
2009-04-02 13:27                                       ` Avi Kivity
2009-04-02 14:05                                         ` Gregory Haskins
2009-04-02 14:50                                     ` Herbert Xu
2009-04-02 15:00                                       ` Avi Kivity
2009-04-02 15:40                                         ` Herbert Xu
2009-04-02 15:57                                           ` Avi Kivity
2009-04-02 16:09                                             ` Herbert Xu
2009-04-02 16:54                                               ` Avi Kivity
2009-04-02 17:06                                                 ` Herbert Xu
2009-04-02 17:17                                                   ` Herbert Xu
2009-04-03 12:25                                                   ` Avi Kivity
2009-04-02 15:10                                 ` Michael S. Tsirkin
2009-04-03  4:43                                   ` Jeremy Fitzhardinge
2009-04-02 10:55                     ` Gregory Haskins
2009-04-02 11:48                       ` Avi Kivity
2009-04-03 10:58                     ` Gerd Hoffmann
2009-04-03 11:03                       ` Avi Kivity
2009-04-03 11:12                         ` Herbert Xu
2009-04-03 11:46                           ` Avi Kivity
2009-04-03 11:48                             ` Herbert Xu
2009-04-03 11:54                               ` Avi Kivity
2009-04-03 11:55                                 ` Herbert Xu
2009-04-03 12:02                                   ` Avi Kivity
2009-04-03 13:05                                     ` Herbert Xu
2009-04-03 11:18                       ` Andi Kleen
2009-04-03 11:34                         ` Herbert Xu
2009-04-03 11:46                         ` Avi Kivity
2009-04-03 11:28                       ` Gregory Haskins
2009-04-02 10:46                 ` Gregory Haskins
2009-04-02 11:43                   ` Avi Kivity
2009-04-02 12:22                     ` Gregory Haskins
2009-04-02 12:42                       ` Avi Kivity
2009-04-02 12:54                         ` Gregory Haskins
2009-04-02 13:08                           ` Avi Kivity
2009-04-02 13:36                             ` Gregory Haskins
2009-04-02 13:45                               ` Avi Kivity
2009-04-02 14:24                                 ` Gregory Haskins
2009-04-02 14:32                                   ` Avi Kivity
2009-04-02 14:41                                     ` Avi Kivity
2009-04-02 14:49                                       ` Anthony Liguori
2009-04-02 16:09                                         ` Anthony Liguori
2009-04-02 16:19                                           ` Avi Kivity
2009-04-02 18:18                                             ` Anthony Liguori
2009-04-03  1:11                                               ` Herbert Xu
2009-04-20 18:02                                               ` Alex Williamson
2009-04-03 12:03                                           ` Gregory Haskins
2009-04-03 12:15                                             ` Avi Kivity
2009-04-03 13:13                                               ` Gregory Haskins
2009-04-03 13:37                                                 ` Avi Kivity
2009-04-03 16:28                                                   ` Gregory Haskins
2009-04-05 10:00                                                     ` Avi Kivity
2009-04-02  3:09             ` Herbert Xu
2009-04-02  6:46               ` Avi Kivity
2009-04-02  8:54                 ` Herbert Xu
2009-04-02  9:03                   ` Avi Kivity
2009-04-02  9:05                     ` Herbert Xu
2009-04-01 20:29           ` Gregory Haskins
2009-04-01 22:23             ` Andi Kleen
2009-04-01 23:05               ` Gregory Haskins
2009-04-01  6:08 ` Rusty Russell
2009-04-01 11:35   ` Gregory Haskins
2009-04-02  1:24     ` Rusty Russell
2009-04-02  2:27       ` Gregory Haskins
2009-04-01 16:10   ` Anthony Liguori
2009-04-05  3:44     ` Rusty Russell
2009-04-05  8:06       ` Avi Kivity
2009-04-05 14:13       ` Anthony Liguori
2009-04-05 16:10         ` Avi Kivity
2009-04-05 16:45           ` Anthony Liguori
2009-04-02  3:15   ` Herbert Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090331184302.28333.18745.stgit@dev.haskins.net \
    --to=ghaskins@novell.com \
    --cc=agraf@suse.de \
    --cc=anthony@codemonkey.ws \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pmorreale@novell.com \
    --cc=pmullaney@novell.com \
    --cc=rusty@rustcorp.com.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).