* [RFC PATCH 0/9] PV device infrastructure v2
@ 2007-08-14 23:33 Gregory Haskins
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:33 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
This series incorporates all of v1 plus the following changes based on
feedback to date:
*) s/ioq_iter/ioq_iter_init
*) removed unecessary desc->offset
*) utilized create_irq() to actually assign interrupt resource
*) removed inadvertant cleanup of whitespace from series
*) added memory barriers in strategic locations
*) misc cleanups I can't quite remember at this time ;)
Notably missing:
*) ioq_iter_push/pop have not been rolled into ioq_iter_seek
*) kmap_atomic is still in use as I don't have a clear understanding of how to
support this properly.
*) still not using bus_register/device_register
Regards,
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* [RFC PATCH 1/9] IOQ: Adding basic definitions for IO-Queue logic
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
@ 2007-08-14 23:33 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 2/9] PARAVIRTUALIZATION: Add support for a bus abstraction Gregory Haskins
` (8 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:33 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
IOQ is a generic shared-memory-queue mechanism that happens to be friendly
to virtualization boundaries. Note that it is not virtualization specific
due to its flexible transport layer.
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
include/linux/ioq.h | 176 +++++++++++++++++++++++++++++++++++++++
lib/Kconfig | 11 ++
lib/Makefile | 1
lib/ioq.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 416 insertions(+), 0 deletions(-)
diff --git a/include/linux/ioq.h b/include/linux/ioq.h
new file mode 100644
index 0000000..d3a18a1
--- /dev/null
+++ b/include/linux/ioq.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * 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. Note that it is not virtualization specific
+ * due to its flexible signaling layer.
+ *
+ * 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.
+ * #) The code has the concept of "north" and "south" where north denotes the
+ * memory-owner side (e.g. guest).
+ * #) A IOQ is "created" on the north side (which generates a unique ID), and
+ * is "connected" on the remote side via its ID. The facilitates call-path
+ * setup in a manner that is friendly across VM/VMM boundaries.
+ * #) An IOQ is manipulated using an iterator idiom.
+ * #) A "IOQ Manager" abstraction handles the translation between two
+ * endpoints. E.g. allocating "north" memory, signaling, translating
+ * addresses (e.g. GPA to PA)
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 <linux/sched.h>
+#include <linux/wait.h>
+#include <asm/types.h>
+
+struct ioq_mgr;
+
+/*
+ *---------
+ * 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.
+ *-----------
+ */
+typedef u64 ioq_id_t;
+
+struct ioq_ring_desc {
+ u64 cookie; /* for arbitrary use by north-side */
+ u64 ptr;
+ u64 len;
+ u64 alen;
+ u8 valid;
+ u8 sown; /* South owned = 1, North owned = 0 */
+};
+
+#define IOQ_RING_MAGIC 0x47fa2fe4
+#define IOQ_RING_VER 1
+
+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;
+};
+
+struct ioq_irq {
+ u8 enabled;
+ u8 pending;
+};
+
+enum ioq_locality {
+ ioq_locality_north,
+ ioq_locality_south,
+};
+
+struct ioq_ring_head {
+ u32 magic;
+ u32 ver;
+ ioq_id_t id;
+ u32 count;
+ u64 ptr; /* ptr to array of ioq_ring_desc[count] */
+ struct ioq_ring_idx idx[2];
+ struct ioq_irq irq[2];
+ u8 padding[16];
+};
+
+/* --- END SHARED STRUCTURES --- */
+
+enum ioq_idx_type {
+ ioq_idxtype_valid,
+ ioq_idxtype_inuse,
+ 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;
+};
+
+int ioq_iter_seek(struct ioq_iterator *iter, enum ioq_seek_type type,
+ long offset, int flags);
+int ioq_iter_push(struct ioq_iterator *iter, int flags);
+int ioq_iter_pop(struct ioq_iterator *iter, int flags);
+
+struct ioq_notifier {
+ void (*signal)(struct ioq_notifier*);
+};
+
+struct ioq {
+ void (*destroy)(struct ioq *ioq);
+ int (*signal)(struct ioq *ioq);
+
+ ioq_id_t id;
+ enum ioq_locality locale;
+ struct ioq_mgr *mgr;
+ struct ioq_ring_head *head_desc;
+ struct ioq_ring_desc *ring;
+ wait_queue_head_t wq;
+ struct ioq_notifier *notifier;
+};
+
+static inline void ioq_init(struct ioq *ioq)
+{
+ memset(ioq, 0, sizeof(*ioq));
+ init_waitqueue_head(&ioq->wq);
+}
+
+int ioq_start(struct ioq *ioq, int flags);
+int ioq_stop(struct ioq *ioq, int flags);
+int ioq_signal(struct ioq *ioq, int flags);
+void ioq_wakeup(struct ioq *ioq); /* This should only be used internally */
+int ioq_count(struct ioq *ioq, enum ioq_idx_type type);
+int ioq_full(struct ioq *ioq, enum ioq_idx_type type);
+
+static inline int ioq_empty(struct ioq *ioq, enum ioq_idx_type type)
+{
+ return !ioq_count(ioq, type);
+}
+
+
+
+#define IOQ_ITER_AUTOUPDATE (1 << 0)
+int ioq_iter_init(struct ioq *ioq, struct ioq_iterator *iter,
+ enum ioq_idx_type type, int flags);
+
+struct ioq_mgr {
+ int (*create)(struct ioq_mgr *t, struct ioq **ioq,
+ size_t ringsize, int flags);
+ int (*connect)(struct ioq_mgr *t, ioq_id_t id, struct ioq **ioq,
+ int flags);
+};
+
+
+#endif /* _LINUX_IOQ_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e7ae6b..65c6d5d 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -124,4 +124,15 @@ config HAS_DMA
depends on !NO_DMA
default y
+config IOQ
+ boolean "IO-Queue library - Generic shared-memory queue"
+ 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
diff --git a/lib/Makefile b/lib/Makefile
index c8c8e20..2bf3b5d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -56,6 +56,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_IOQ) += ioq.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
diff --git a/lib/ioq.c b/lib/ioq.c
new file mode 100644
index 0000000..b9ef75e
--- /dev/null
+++ b/lib/ioq.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * See include/linux/ioq.h for documentation
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/ioq.h>
+#include <asm/bitops.h>
+#include <linux/module.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+static int ioq_iter_setpos(struct ioq_iterator *iter, u32 pos)
+{
+ struct ioq *ioq = iter->ioq;
+
+ BUG_ON(pos >= ioq->head_desc->count);
+
+ iter->pos = pos;
+ iter->desc = &ioq->ring[pos];
+
+ return 0;
+}
+
+int ioq_iter_seek(struct ioq_iterator *iter, enum ioq_seek_type type,
+ long offset, int flags)
+{
+ struct ioq_ring_head *head_desc = iter->ioq->head_desc;
+ struct ioq_ring_idx *idx = iter->idx;
+ u32 pos;
+
+ switch (type) {
+ case ioq_seek_next:
+ pos = iter->pos + 1;
+ pos %= head_desc->count;
+ break;
+ case ioq_seek_tail:
+ pos = idx->tail;
+ break;
+ case ioq_seek_head:
+ pos = idx->head;
+ break;
+ case ioq_seek_set:
+ if (offset >= head_desc->count)
+ return -1;
+ pos = offset;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ioq_iter_setpos(iter, pos);
+}
+EXPORT_SYMBOL(ioq_iter_seek);
+
+static int ioq_ring_count(struct ioq_ring_idx *idx, int count)
+{
+ if (idx->full && (idx->head == idx->tail))
+ return count;
+ else if (idx->head >= idx->tail)
+ return idx->head - idx->tail;
+ else
+ return (idx->head + count) - idx->tail;
+}
+
+int ioq_iter_push(struct ioq_iterator *iter, int flags)
+{
+ struct ioq_ring_head *head_desc = iter->ioq->head_desc;
+ struct ioq_ring_idx *idx = iter->idx;
+ int ret = -ENOSPC;
+
+ /*
+ * Its only valid to push if we are currently pointed at the head
+ */
+ if (iter->pos != idx->head)
+ return -EINVAL;
+
+ if (ioq_ring_count(idx, head_desc->count) < head_desc->count) {
+ idx->head++;
+ idx->head %= head_desc->count;
+
+ if (idx->head == idx->tail)
+ idx->full = 1;
+
+ mb();
+
+ ret = ioq_iter_seek(iter, ioq_seek_next, 0, flags);
+
+ if (iter->update)
+ ioq_signal(iter->ioq, 0);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(ioq_iter_push);
+
+int ioq_iter_pop(struct ioq_iterator *iter, int flags)
+{
+ struct ioq_ring_head *head_desc = iter->ioq->head_desc;
+ struct ioq_ring_idx *idx = iter->idx;
+ int ret = -ENOSPC;
+
+ /*
+ * Its only valid to pop if we are currently pointed at the tail
+ */
+ if (iter->pos != idx->tail)
+ return -EINVAL;
+
+ if (ioq_ring_count(idx, head_desc->count) != 0) {
+ idx->tail++;
+ idx->tail %= head_desc->count;
+
+ idx->full = 0;
+
+ mb();
+
+ ret = ioq_iter_seek(iter, ioq_seek_next, 0, flags);
+
+ if (iter->update)
+ ioq_signal(iter->ioq, 0);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(ioq_iter_pop);
+
+int ioq_iter_init(struct ioq *ioq, struct ioq_iterator *iter,
+ enum ioq_idx_type type, int flags)
+{
+ BUG_ON((type < 0) || (type >= ioq_idxtype_invalid));
+
+ iter->ioq = ioq;
+ iter->update = (flags & IOQ_ITER_AUTOUPDATE);
+ iter->idx = &ioq->head_desc->idx[type];
+ iter->pos = -1;
+ iter->desc = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(ioq_iter_init);
+
+int ioq_start(struct ioq *ioq, int flags)
+{
+ struct ioq_irq *irq = &ioq->head_desc->irq[ioq->locale];
+
+ irq->enabled = 1;
+ mb();
+
+ if (irq->pending)
+ ioq_wakeup(ioq);
+
+ return 0;
+}
+EXPORT_SYMBOL(ioq_start);
+
+int ioq_stop(struct ioq *ioq, int flags)
+{
+ struct ioq_irq *irq = &ioq->head_desc->irq[ioq->locale];
+
+ irq->enabled = 0;
+ mb();
+
+ return 0;
+}
+EXPORT_SYMBOL(ioq_stop);
+
+int ioq_signal(struct ioq *ioq, int flags)
+{
+ /* Load the irq structure from the other locale */
+ struct ioq_irq *irq = &ioq->head_desc->irq[!ioq->locale];
+
+ irq->pending = 1;
+ mb();
+
+ if (irq->enabled)
+ ioq->signal(ioq);
+
+ return 0;
+}
+EXPORT_SYMBOL(ioq_signal);
+
+int ioq_count(struct ioq *ioq, enum ioq_idx_type type)
+{
+ BUG_ON((type < 0) || (type >= ioq_idxtype_invalid));
+
+ return ioq_ring_count(&ioq->head_desc->idx[type], ioq->head_desc->count);
+}
+EXPORT_SYMBOL(ioq_count);
+
+int ioq_full(struct ioq *ioq, enum ioq_idx_type type)
+{
+ BUG_ON((type < 0) || (type >= ioq_idxtype_invalid));
+
+ return ioq->head_desc->idx[type].full;
+}
+EXPORT_SYMBOL(ioq_full);
+
+void ioq_wakeup(struct ioq *ioq)
+{
+ struct ioq_irq *irq = &ioq->head_desc->irq[ioq->locale];
+
+ irq->pending = 0;
+ mb();
+
+ wake_up(&ioq->wq);
+ if (ioq->notifier)
+ ioq->notifier->signal(ioq->notifier);
+}
+EXPORT_SYMBOL(ioq_wakeup);
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 2/9] PARAVIRTUALIZATION: Add support for a bus abstraction
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-14 23:33 ` [RFC PATCH 1/9] IOQ: Adding basic definitions for IO-Queue logic Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 3/9] IRQ: Export create_irq/destroy_irq Gregory Haskins
` (7 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
PV usually comes in two flavors: device PV, and "core" PV. The existing PV
ops deal in terms of the latter. However, it would be useful to add an
interface for a virtual bus with provisions for discovery/configuration of
backend PV devices. Often times it is desirable to run PV devices even if the
entire core is not operating with PVOPS. Therefore, we introduce a separate
interface to deal with the devices.
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
include/linux/pvbus.h | 43 +++++++++++++++++++++++++++++++++++++++++++
kernel/Makefile | 2 +-
kernel/pvbus.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 1 deletions(-)
diff --git a/include/linux/pvbus.h b/include/linux/pvbus.h
new file mode 100644
index 0000000..edfe185
--- /dev/null
+++ b/include/linux/pvbus.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Paravirtualized-Bus
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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_PVBUS_H
+#define _LINUX_PVBUS_H
+
+#include <linux/ioq.h>
+
+struct pvbus_dev {
+ u64 instance;
+ u32 version;
+};
+
+struct pvbus_ops {
+ int (*enumerate)(const char *dev, struct pvbus_dev inst[],
+ size_t *cnt, int flags);
+ int (*call)(u64 inst, u32 func, void *data, size_t len, int flags);
+
+ struct ioq_mgr *ioqmgr;
+};
+
+extern struct pvbus_ops *pvbus_ops;
+
+#endif /* */
diff --git a/kernel/Makefile b/kernel/Makefile
index 642d427..3008163 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
- hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
+ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o pvbus.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
diff --git a/kernel/pvbus.c b/kernel/pvbus.c
new file mode 100644
index 0000000..e638a69
--- /dev/null
+++ b/kernel/pvbus.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Paravirtualized-Bus
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/pvbus.h>
+
+int native_enumerate(const char *dev, struct pvbus_dev inst[],
+ size_t *cnt, int flags)
+{
+ return -ENOSYS;
+}
+
+int native_call(u64 inst, u32 func, void *data, size_t len, int flags)
+{
+ return -ENOSYS;
+}
+
+static struct pvbus_ops native_pvbus = {
+ .enumerate = native_enumerate,
+ .call = native_call,
+ .ioqmgr = NULL,
+};
+
+/* This will get reassigned if a PV compatible platform is detected */
+struct pvbus_ops *pvbus_ops = &native_pvbus;
+EXPORT_SYMBOL(pvbus_ops);
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 3/9] IRQ: Export create_irq/destroy_irq
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-14 23:33 ` [RFC PATCH 1/9] IOQ: Adding basic definitions for IO-Queue logic Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 2/9] PARAVIRTUALIZATION: Add support for a bus abstraction Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 4/9] KVM: Add a guest side driver for IOQ Gregory Haskins
` (6 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
arch/x86_64/kernel/io_apic.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d8bfe31..6bf8794 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1849,6 +1849,7 @@ int create_irq(void)
}
return irq;
}
+EXPORT_SYMBOL(create_irq);
void destroy_irq(unsigned int irq)
{
@@ -1860,6 +1861,7 @@ void destroy_irq(unsigned int irq)
__clear_irq_vector(irq);
spin_unlock_irqrestore(&vector_lock, flags);
}
+EXPORT_SYMBOL(destroy_irq);
/*
* MSI mesage composition
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 4/9] KVM: Add a guest side driver for IOQ
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (2 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 3/9] IRQ: Export create_irq/destroy_irq Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 5/9] KVM: Add a gpa_to_hva helper function Gregory Haskins
` (5 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/kvm/Kconfig | 27 +++++-
drivers/kvm/Makefile | 3 -
drivers/kvm/ioq.h | 39 +++++++++
drivers/kvm/ioq_guest.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
drivers/kvm/pvbus.h | 41 ++++++++++
drivers/kvm/pvbus_guest.c | 189 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/kvm.h | 4 +
7 files changed, 487 insertions(+), 8 deletions(-)
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 22d0eb4..cba03d2 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -47,16 +47,31 @@ config KVM_BALLOON
The driver inflate/deflate guest physical memory on demand.
This ability provides memory over commit for the host
-config KVM_NET
- tristate "Para virtual network device"
- depends on KVM
- ---help---
- Provides support for guest paravirtualization networking
-
config KVM_NET_HOST
tristate "Para virtual network host device"
depends on KVM
---help---
Provides support for host paravirtualization networking
+config KVM_GUEST
+ bool "KVM Guest support"
+ depends on X86
+ default y
+
+config KVM_PVBUS_GUEST
+ tristate "Paravirtualized Bus (PVBUS) support"
+ depends on KVM_GUEST
+ select IOQ
+ ---help---
+ PVBUS is an infrastructure for generic PV drivers to take advantage
+ of an underlying hypervisor without having to understand the details
+ of the hypervisor itself. You only need this option if you plan to
+ run this kernel as a KVM guest.
+
+config KVM_NET
+ tristate "Para virtual network device"
+ depends on KVM && KVM_GUEST
+ ---help---
+ Provides support for guest paravirtualization networking
+
endif # VIRTUALIZATION
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index 92600d8..c6a59bb 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -14,4 +14,5 @@ kvm-net-objs = kvm_net.o
obj-$(CONFIG_KVM_NET) += kvm-net.o
kvm-net-host-objs = kvm_net_host.o
obj-$(CONFIG_KVM_NET_HOST) += kvm_net_host.o
-
+kvm-pvbus-objs := ioq_guest.o pvbus_guest.o
+obj-$(CONFIG_KVM_PVBUS_GUEST) += kvm-pvbus.o
diff --git a/drivers/kvm/ioq.h b/drivers/kvm/ioq.h
new file mode 100644
index 0000000..7e955f1
--- /dev/null
+++ b/drivers/kvm/ioq.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * See include/linux/ioq.h for documentation
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 _KVM_IOQ_H_
+#define _KVM_IOQ_H_
+
+#include <linux/ioq.h>
+
+#define IOQHC_REGISTER 1
+#define IOQHC_UNREGISTER 2
+#define IOQHC_SIGNAL 3
+
+struct ioq_register {
+ ioq_id_t id;
+ u32 irq;
+ u64 ring;
+};
+
+
+#endif /* _KVM_IOQ_H_ */
diff --git a/drivers/kvm/ioq_guest.c b/drivers/kvm/ioq_guest.c
new file mode 100644
index 0000000..f7c88aa
--- /dev/null
+++ b/drivers/kvm/ioq_guest.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * See include/linux/ioq.h for documentation
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/ioq.h>
+#include <asm/hypercall.h>
+
+#include "ioq.h"
+#include "kvm.h"
+
+struct kvmguest_ioq {
+ struct ioq ioq;
+ int irq;
+};
+
+struct kvmguest_ioq* to_ioq(struct ioq *ioq)
+{
+ return container_of(ioq, struct kvmguest_ioq, ioq);
+}
+
+static int ioq_hypercall(unsigned long nr, void *data)
+{
+ return hypercall(2, __NR_hypercall_ioq, nr, __pa(data));
+}
+
+/*
+ * ------------------
+ * interrupt handler
+ * ------------------
+ */
+irqreturn_t kvmguest_ioq_intr(int irq, void *dev)
+{
+ struct kvmguest_ioq *_ioq = to_ioq(dev);
+
+ ioq_wakeup(&_ioq->ioq);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * ------------------
+ * ioq implementation
+ * ------------------
+ */
+
+static int kvmguest_ioq_signal(struct ioq *ioq)
+{
+ return ioq_hypercall(IOQHC_SIGNAL, &ioq->id);
+}
+
+static void kvmguest_ioq_destroy(struct ioq *ioq)
+{
+ struct kvmguest_ioq *_ioq = to_ioq(ioq);
+ int ret;
+
+ ret = ioq_hypercall(IOQHC_UNREGISTER, &ioq->id);
+ BUG_ON (ret < 0);
+
+ free_irq(_ioq->irq, NULL);
+ destroy_irq(_ioq->irq);
+
+ kfree(_ioq->ioq.ring);
+ kfree(_ioq->ioq.head_desc);
+ kfree(_ioq);
+}
+
+/*
+ * ------------------
+ * ioqmgr implementation
+ * ------------------
+ */
+static int kvmguest_ioq_register(struct kvmguest_ioq *ioq, ioq_id_t id,
+ int irq, void *ring)
+{
+ struct ioq_register data = {
+ .id = id,
+ .irq = irq,
+ .ring = (u64)__pa(ring),
+ };
+
+ return ioq_hypercall(IOQHC_REGISTER, &data);
+}
+
+static int kvmguest_ioq_create(struct ioq_mgr *t, struct ioq **ioq,
+ size_t ringsize, int flags)
+{
+ struct kvmguest_ioq *_ioq = NULL;
+ struct ioq_ring_head *head_desc = NULL;
+ void *ring = NULL;
+ size_t ringlen = sizeof(struct ioq_ring_desc) * ringsize;
+ int ret = -ENOMEM;
+
+ _ioq = kzalloc(sizeof(*_ioq), GFP_KERNEL);
+ if (!_ioq)
+ goto error;
+
+ head_desc = kzalloc(sizeof(*head_desc), GFP_KERNEL | GFP_DMA);
+ if (!head_desc)
+ goto error;
+
+ ring = kzalloc(ringlen, GFP_KERNEL | GFP_DMA);
+ if (!ring)
+ goto error;
+
+ head_desc->magic = IOQ_RING_MAGIC;
+ head_desc->ver = IOQ_RING_VER;
+ head_desc->id = (ioq_id_t)_ioq;
+ head_desc->count = ringsize;
+ head_desc->ptr = (u64)__pa(ring);
+
+ /* Dynamically assign a free IRQ to this resource */
+ _ioq->irq = create_irq();
+
+ ioq_init(&_ioq->ioq);
+
+ _ioq->ioq.signal = kvmguest_ioq_signal;
+ _ioq->ioq.destroy = kvmguest_ioq_destroy;
+
+ _ioq->ioq.id = head_desc->id;
+ _ioq->ioq.locale = ioq_locality_north;
+ _ioq->ioq.mgr = t;
+ _ioq->ioq.head_desc = head_desc;
+ _ioq->ioq.ring = ring;
+
+ ret = request_irq(_ioq->irq, kvmguest_ioq_intr, 0, "KVM-IOQ", _ioq);
+ if (ret < 0)
+ goto error;
+
+ ret = kvmguest_ioq_register(_ioq, _ioq->ioq.id, _ioq->irq, ring);
+ if (ret < 0)
+ goto error;
+
+ *ioq = &_ioq->ioq;
+
+ return 0;
+
+ error:
+ if (_ioq)
+ kfree(_ioq);
+ if (head_desc)
+ kfree(head_desc);
+ if (ring)
+ kfree(ring);
+
+ return ret;
+}
+
+static int kvmguest_ioq_connect(struct ioq_mgr *t, ioq_id_t id,
+ struct ioq **ioq, int flags)
+{
+ /* You cannot connect to queues on the guest */
+ return -EINVAL;
+
+}
+
+int kvmguest_ioqmgr_alloc(struct ioq_mgr **mgr)
+{
+ struct ioq_mgr *_mgr = kzalloc(sizeof(*_mgr), GFP_KERNEL);
+ if (!_mgr)
+ return -ENOMEM;
+
+ _mgr->create = kvmguest_ioq_create;
+ _mgr->connect = kvmguest_ioq_connect;
+
+ *mgr = _mgr;
+
+ return 0;
+}
+
+
+
+
+
+
diff --git a/drivers/kvm/pvbus.h b/drivers/kvm/pvbus.h
new file mode 100644
index 0000000..97b5dce
--- /dev/null
+++ b/drivers/kvm/pvbus.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 _KVM_PVBUS_H
+#define _KVM_PVBUS_H
+
+#define KVM_PVBUS_OP_ENUM 1
+#define KVM_PVBUS_OP_CALL 2
+
+struct enumerate_params {
+ u32 name_offset;
+ u32 inst_offset;
+ u32 count;
+ u8 data[1];
+};
+
+struct call_params {
+ u64 inst;
+ u32 func;
+ u64 data;
+ u64 len;
+};
+
+#endif /* _KVM_PVBUS_H */
diff --git a/drivers/kvm/pvbus_guest.c b/drivers/kvm/pvbus_guest.c
new file mode 100644
index 0000000..3003745
--- /dev/null
+++ b/drivers/kvm/pvbus_guest.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/pvbus.h>
+#include <linux/kvm_para.h>
+#include <linux/kvm.h>
+#include <linux/mm.h>
+#include <linux/ioq.h>
+
+#include <asm/hypercall.h>
+
+#include "pvbus.h"
+
+MODULE_AUTHOR ("Gregory Haskins");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1");
+
+static int kvm_pvbus_hypercall(unsigned long nr, void *data, unsigned long len)
+{
+ return hypercall(3, __NR_hypercall_pvbus, nr, __pa(data), len);
+}
+
+static int kvm_pvbus_enumerate(const char *dev, struct pvbus_dev inst[],
+ size_t *cnt, int flags)
+{
+ int ret;
+ size_t namelen = strlen(dev);
+ size_t total = sizeof(struct enumerate_params)
+ + namelen /* dont add one...extra is already in data[1] */
+ + (sizeof(struct pvbus_dev) * (*cnt));
+
+ struct enumerate_params *e = kzalloc(total, GFP_KERNEL | GFP_DMA);
+ if (!e)
+ return -ENOMEM;
+
+ e->name_offset = 0;
+ memcpy(&e->data[e->name_offset], dev, namelen);
+ e->inst_offset = namelen + 1;
+ e->count = *cnt;
+
+ ret = kvm_pvbus_hypercall(KVM_PVBUS_OP_ENUM, e, total);
+ if (ret < 0)
+ goto out;
+
+ *cnt = e->count;
+
+ if (e->count)
+ memcpy(inst, &e->data[e->inst_offset],
+ (sizeof(struct pvbus_dev) * e->count));
+
+ out:
+ kfree(e);
+
+ return ret;
+}
+
+static int kvm_pvbus_call(u64 inst, u32 func, void *data,
+ size_t len, int flags)
+{
+ struct call_params params = {
+ .inst = inst,
+ .func = func,
+ .data = (u64)__pa(data),
+ .len = len,
+ };
+
+ return kvm_pvbus_hypercall(KVM_PVBUS_OP_CALL, ¶ms, sizeof(params));
+}
+
+/*
+ * This is the vm-syscall address - to be patched by the host to
+ * VMCALL (Intel) or VMMCALL (AMD), depending on the CPU model:
+ */
+asm (
+ " .globl hypercall_addr \n"
+ " .align 4 \n"
+ " hypercall_addr: \n"
+ " movl $-38, %eax \n"
+ " ret \n"
+);
+
+extern unsigned char hypercall_addr[6];
+
+#ifndef CONFIG_X86_64
+static DEFINE_PER_CPU(struct kvm_vcpu_para_state, para_state);
+#endif
+
+static int __init kvm_pvbus_probe(void)
+{
+ struct page *hypercall_addr_page;
+ struct kvm_vcpu_para_state *para_state;
+
+#ifdef CONFIG_X86_64
+ struct page *pstate_page;
+ if ((pstate_page = alloc_page(GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ para_state = (struct kvm_vcpu_para_state*)page_address(pstate_page);
+#else
+ para_state = &per_cpu(para_state, cpu);
+#endif
+ /*
+ * Try to write to a magic MSR (which is invalid on any real CPU),
+ * and thus signal to KVM that we wish to entering para-virtualized
+ * mode:
+ */
+ para_state->guest_version = KVM_PARA_API_VERSION;
+ para_state->host_version = -1;
+ para_state->size = sizeof(*para_state);
+ para_state->ret = -1;
+
+ hypercall_addr_page = vmalloc_to_page(hypercall_addr);
+ para_state->hypercall_gpa = page_to_pfn(hypercall_addr_page)
+ << PAGE_SHIFT | offset_in_page(hypercall_addr);
+ printk(KERN_DEBUG "kvm guest: hypercall gpa is 0x%lx\n",
+ (long)para_state->hypercall_gpa);
+
+ if (wrmsr_safe(MSR_KVM_API_MAGIC, __pa(para_state), 0)) {
+ printk(KERN_INFO "KVM guest: WRMSR probe failed.\n");
+ return -1;
+ }
+
+ printk(KERN_DEBUG "kvm guest: host returned %d\n",
+ para_state->ret);
+ printk(KERN_DEBUG "kvm guest: host version: %d\n",
+ para_state->host_version);
+ printk(KERN_DEBUG "kvm guest: syscall entry: %02x %02x %02x %02x\n",
+ hypercall_addr[0], hypercall_addr[1],
+ hypercall_addr[2], hypercall_addr[3]);
+
+ if (para_state->ret) {
+ printk(KERN_ERR "kvm guest: host refused registration.\n");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+static struct pvbus_ops kvm_pvbus_ops = {
+ .enumerate = kvm_pvbus_enumerate,
+ .call = kvm_pvbus_call,
+ .ioqmgr = NULL,
+};
+
+int kvmguest_ioqmgr_alloc(struct ioq_mgr **mgr);
+
+int __init kvm_pvbus_init(void)
+{
+ int ret = kvm_pvbus_probe();
+ if (ret < 0)
+ return ret;
+
+ ret = kvmguest_ioqmgr_alloc(&kvm_pvbus_ops.ioqmgr);
+ if (ret < 0)
+ return ret;
+
+ pvbus_ops = &kvm_pvbus_ops;
+
+ return 0;
+
+}
+
+static void __exit kvm_pvbus_exit(void)
+{
+
+}
+
+module_init(kvm_pvbus_init);
+module_exit(kvm_pvbus_exit);
+
+
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 992aeec..bc2b51e 100755
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -377,13 +377,15 @@ struct kvm_pvnet_config {
* No registers are clobbered by the hypercall, except that the
* return value is in RAX.
*/
-#define KVM_NR_HYPERCALLS 5
+#define KVM_NR_HYPERCALLS 7
#define __NR_hypercall_test 0
#define __NR_hypercall_register_eth 1
#define __NR_hypercall_send_eth 2
#define __NR_hypercall_set_multicast_eth 3
#define __NR_hypercall_start_stop_eth 4
+#define __NR_hypercall_ioq 5
+#define __NR_hypercall_pvbus 6
#define __NR_hypercall_balloon (KVM_NR_HYPERCALLS + 0)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 5/9] KVM: Add a gpa_to_hva helper function
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (3 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 4/9] KVM: Add a guest side driver for IOQ Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 6/9] KVM: Add support for IOQ Gregory Haskins
` (4 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/kvm/kvm.h | 1 +
drivers/kvm/mmu.c | 12 ++++++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 9934f11..05d5be1 100755
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -475,6 +475,7 @@ void vcpu_load(struct kvm_vcpu *vcpu);
void vcpu_put(struct kvm_vcpu *vcpu);
hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa);
+void* gpa_to_hva(struct kvm *kvm, gpa_t gpa);
#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index e84c599..daaf0d2 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -766,6 +766,18 @@ hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
}
EXPORT_SYMBOL_GPL(gpa_to_hpa);
+void* gpa_to_hva(struct kvm *kvm, gpa_t gpa)
+{
+ struct page *page;
+
+ if ((gpa & HPA_ERR_MASK) == 0)
+ return NULL;
+
+ page = gfn_to_page(kvm, gpa >> PAGE_SHIFT);
+ return kmap_atomic(page, gpa & PAGE_MASK);
+}
+EXPORT_SYMBOL_GPL(gpa_to_hva);
+
hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva)
{
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 6/9] KVM: Add support for IOQ
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (4 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 5/9] KVM: Add a gpa_to_hva helper function Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 7/9] KVM: Add PVBUS support to the KVM host Gregory Haskins
` (3 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
IOQ is a shared-memory-queue interface for implmenting PV driver
communication.
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/kvm/Kconfig | 5 +
drivers/kvm/Makefile | 3
drivers/kvm/ioq.h | 12 +-
drivers/kvm/ioq_host.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/kvm/kvm.h | 5 +
drivers/kvm/kvm_main.c | 3
include/linux/kvm.h | 1
7 files changed, 393 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index cba03d2..0f81af1 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -47,6 +47,11 @@ config KVM_BALLOON
The driver inflate/deflate guest physical memory on demand.
This ability provides memory over commit for the host
+config KVM_IOQ_HOST
+ boolean "Add IOQ support to KVM"
+ depends on KVM
+ select IOQ
+
config KVM_NET_HOST
tristate "Para virtual network host device"
depends on KVM
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index c6a59bb..2095061 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -4,6 +4,9 @@
EXTRA_CFLAGS :=
kvm-objs := kvm_main.o mmu.o x86_emulate.o
+ifeq ($(CONFIG_KVM_IOQ_HOST),y)
+kvm-objs += ioq_host.o
+endif
obj-$(CONFIG_KVM) += kvm.o
kvm-intel-objs = vmx.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/drivers/kvm/ioq.h b/drivers/kvm/ioq.h
index 7e955f1..b942113 100644
--- a/drivers/kvm/ioq.h
+++ b/drivers/kvm/ioq.h
@@ -25,7 +25,17 @@
#include <linux/ioq.h>
-#define IOQHC_REGISTER 1
+struct kvm;
+
+#ifdef CONFIG_KVM_IOQ_HOST
+int kvmhost_ioqmgr_init(struct kvm *kvm);
+int kvmhost_ioqmgr_module_init(void);
+#else
+#define kvmhost_ioqmgr_init(kvm) {}
+#define kvmhost_ioqmgr_module_init() {}
+#endif
+
+#define IOQHC_REGISTER 1
#define IOQHC_UNREGISTER 2
#define IOQHC_SIGNAL 3
diff --git a/drivers/kvm/ioq_host.c b/drivers/kvm/ioq_host.c
new file mode 100644
index 0000000..413f103
--- /dev/null
+++ b/drivers/kvm/ioq_host.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * See include/linux/ioq.h for documentation
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/ioq.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/highmem.h>
+
+#include <asm/atomic.h>
+
+#include "ioq.h"
+#include "kvm.h"
+
+struct kvmhost_ioq {
+ struct ioq ioq;
+ struct rb_node node;
+ atomic_t refcnt;
+ struct kvm_vcpu *vcpu;
+ int irq;
+};
+
+struct kvmhost_map {
+ spinlock_t lock;
+ struct rb_root root;
+};
+
+struct kvmhost_ioq_mgr {
+ struct ioq_mgr mgr;
+ struct kvm *kvm;
+ struct kvmhost_map map;
+};
+
+struct kvmhost_ioq* to_ioq(struct ioq *ioq)
+{
+ return container_of(ioq, struct kvmhost_ioq, ioq);
+}
+
+struct kvmhost_ioq_mgr* to_mgr(struct ioq_mgr *mgr)
+{
+ return container_of(mgr, struct kvmhost_ioq_mgr, mgr);
+}
+
+/*
+ * ------------------
+ * rb map management
+ * ------------------
+ */
+
+static void kvmhost_map_init(struct kvmhost_map *map)
+{
+ spin_lock_init(&map->lock);
+ map->root = RB_ROOT;
+}
+
+static int kvmhost_map_register(struct kvmhost_map *map,
+ struct kvmhost_ioq *ioq)
+{
+ int ret = 0;
+ struct rb_root *root;
+ struct rb_node **new, *parent = NULL;
+
+ spin_lock(&map->lock);
+
+ root = &map->root;
+ new = &(root->rb_node);
+
+ /* Figure out where to put new node */
+ while (*new) {
+ struct kvmhost_ioq *this;
+
+ this = container_of(*new, struct kvmhost_ioq, node);
+ parent = *new;
+
+ if (ioq->ioq.id < this->ioq.id)
+ new = &((*new)->rb_left);
+ else if (ioq->ioq.id > this->ioq.id)
+ new = &((*new)->rb_right);
+ else {
+ ret = -EEXIST;
+ break;
+ }
+ }
+
+ if (!ret) {
+ /* Add new node and rebalance tree. */
+ rb_link_node(&ioq->node, parent, new);
+ rb_insert_color(&ioq->node, root);
+ }
+
+ spin_unlock(&map->lock);
+
+ return ret;
+}
+
+static struct kvmhost_ioq* kvmhost_map_find(struct kvmhost_map *map,
+ ioq_id_t id)
+{
+ struct rb_node *node;
+ struct kvmhost_ioq *ioq = NULL;
+
+ spin_lock(&map->lock);
+
+ node = map->root.rb_node;
+
+ while (node) {
+ struct kvmhost_ioq *_ioq;
+
+ _ioq = container_of(node, struct kvmhost_ioq, node);
+
+ if (ioq->ioq.id < id)
+ node = node->rb_left;
+ else if (_ioq->ioq.id > id)
+ node = node->rb_right;
+ else {
+ ioq = _ioq;
+ break;
+ }
+ }
+
+ spin_unlock(&map->lock);
+
+ return ioq;
+}
+
+static void kvmhost_map_erase(struct kvmhost_map *map,
+ struct kvmhost_ioq *ioq)
+{
+ spin_lock(&map->lock);
+ rb_erase(&ioq->node, &map->root);
+ spin_unlock(&map->lock);
+}
+
+/*
+ * ------------------
+ * ioq implementation
+ * ------------------
+ */
+
+static int kvmhost_ioq_signal(struct ioq *ioq)
+{
+ struct kvmhost_ioq *_ioq = to_ioq(ioq);
+ BUG_ON(!_ioq);
+
+ /*
+ * FIXME: Inject an interrupt to the guest for "id"
+ *
+ * We will have to decide if we will have 1:1 IOQ:IRQ, or if we
+ * will aggregate all IOQs through a single IRQ. For purposes of
+ * example, we will assume 1:1.
+ */
+
+ /* kvm_vcpu_send_interrupt(_ioq->vcpu, _ioq->irq); */
+
+ return 0;
+}
+
+static void kvmhost_ioq_destroy(struct ioq *ioq)
+{
+ struct kvmhost_ioq *_ioq = to_ioq(ioq);
+
+ if (atomic_dec_and_test(&_ioq->refcnt))
+ kfree(_ioq);
+}
+
+static struct kvmhost_ioq* kvmhost_ioq_alloc(struct ioq_mgr *t,
+ struct kvm_vcpu *vcpu,
+ ioq_id_t id, int irq, gpa_t ring)
+{
+ struct kvmhost_ioq *_ioq;
+ struct ioq *ioq;
+
+ _ioq = kzalloc(sizeof(*_ioq), GFP_KERNEL);
+ if (!_ioq)
+ return NULL;
+
+ ioq = &_ioq->ioq;
+
+ atomic_set(&_ioq->refcnt, 1);
+ _ioq->vcpu = vcpu;
+ _ioq->irq = irq;
+
+ ioq_init(&_ioq->ioq);
+
+ ioq->signal = kvmhost_ioq_signal;
+ ioq->destroy = kvmhost_ioq_destroy;
+
+ ioq->id = id;
+ ioq->locale = ioq_locality_south;
+ ioq->mgr = t;
+ ioq->head_desc = (struct ioq_ring_head*)gpa_to_hva(vcpu->kvm, ring);
+ ioq->ring = (struct ioq_ring_desc*)gpa_to_hva(vcpu->kvm,
+ ioq->head_desc->ptr);
+
+ return _ioq;
+}
+
+/*
+ * ------------------
+ * hypercall implementation
+ * ------------------
+ */
+
+static int kvmhost_ioq_hc_register(struct ioq_mgr *t, struct kvm_vcpu *vcpu,
+ ioq_id_t id, int irq, gpa_t ring)
+{
+ struct kvmhost_ioq *_ioq = kvmhost_ioq_alloc(t, vcpu, id, irq, ring);
+ int ret;
+
+ if (!_ioq)
+ return -ENOMEM;
+
+ ret = kvmhost_map_register(&to_mgr(t)->map, _ioq);
+ if (ret < 0)
+ kvmhost_ioq_destroy(&_ioq->ioq);
+
+ return 0;
+}
+
+static int kvmhost_ioq_hc_unregister(struct ioq_mgr *t, ioq_id_t id)
+{
+ struct kvmhost_ioq_mgr *_mgr = to_mgr(t);
+ struct kvmhost_ioq *_ioq = kvmhost_map_find(&_mgr->map, id);
+
+ if (!_ioq)
+ return -ENOENT;
+
+ kvmhost_map_erase(&_mgr->map, _ioq);
+ kvmhost_ioq_destroy(&_ioq->ioq);
+
+ return 0;
+}
+
+static int kvmhost_ioq_hc_signal(struct ioq_mgr *t, ioq_id_t id)
+{
+ struct kvmhost_ioq *_ioq = kvmhost_map_find(&to_mgr(t)->map, id);
+
+ if (!_ioq)
+ return -1;
+
+ ioq_wakeup(&_ioq->ioq);
+
+ return 0;
+}
+
+/*
+ * Our hypercall format will always follow with the call-id in arg[0] and
+ * a pointer to the arguments in arg[1]
+ */
+static unsigned long kvmhost_hc(struct kvm_vcpu *vcpu, unsigned long args[])
+{
+ struct ioq_mgr *t = vcpu->kvm->ioqmgr;
+ void *vdata = gpa_to_hva(vcpu->kvm, args[1]);
+ int ret = -EINVAL;
+
+ if (!vdata)
+ return -EINVAL;
+
+ /*
+ * FIXME: we need to make sure that the pointer is sane
+ * so a malicious guest cannot crash the host.
+ */
+
+ switch (args[0])
+ {
+ case IOQHC_REGISTER: {
+ struct ioq_register *data = (struct ioq_register*)vdata;
+ ret = kvmhost_ioq_hc_register(t, vcpu,
+ data->id,
+ data->irq,
+ data->ring);
+ }
+ case IOQHC_UNREGISTER: {
+ ioq_id_t *id = (ioq_id_t*)vdata;
+ ret = kvmhost_ioq_hc_unregister(t, *id);
+ }
+ case IOQHC_SIGNAL: {
+ ioq_id_t *id = (ioq_id_t*)vdata;
+ ret = kvmhost_ioq_hc_signal(t, *id);
+ }
+ }
+
+ /* FIXME: unmap the vdata? */
+
+ return ret;
+}
+
+/*
+ * ------------------
+ * ioqmgr implementation
+ * ------------------
+ */
+
+static int kvmhost_ioq_create(struct ioq_mgr *t, struct ioq **ioq,
+ size_t ringsize, int flags)
+{
+ /* You cannot create queues on the host */
+ return -EINVAL;
+}
+
+static int kvmhost_ioq_connect(struct ioq_mgr *t, ioq_id_t id,
+ struct ioq **ioq, int flags)
+{
+ struct kvmhost_ioq *_ioq = kvmhost_map_find(&to_mgr(t)->map, id);
+
+ if (!_ioq)
+ return -1;
+
+ atomic_inc(&_ioq->refcnt);
+ *ioq = &_ioq->ioq;
+
+ return 0;
+
+}
+
+int kvmhost_ioqmgr_init(struct kvm *kvm)
+{
+ struct kvmhost_ioq_mgr *_mgr = kzalloc(sizeof(*_mgr), GFP_KERNEL);
+ if (!_mgr)
+ return -ENOMEM;
+
+ _mgr->kvm = kvm;
+ kvmhost_map_init(&_mgr->map);
+
+ _mgr->mgr.create = kvmhost_ioq_create;
+ _mgr->mgr.connect = kvmhost_ioq_connect;
+
+ kvm->ioqmgr = &_mgr->mgr;
+
+ return 0;
+}
+
+__init int kvmhost_ioqmgr_module_init(void)
+{
+ struct kvm_hypercall hc;
+
+ hc.hypercall = kvmhost_hc;
+ hc.idx = __NR_hypercall_ioq;
+
+ kvm_register_hypercall(THIS_MODULE, &hc);
+
+ return 0;
+}
+
+
+
+
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 05d5be1..c38c84f 100755
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include "vmx.h"
+#include "ioq.h"
#include <linux/kvm.h>
#include <linux/kvm_para.h>
@@ -389,6 +390,10 @@ struct kvm {
struct list_head vm_list;
struct net_device *netdev;
struct file *filp;
+#ifdef CONFIG_KVM_IOQ_HOST
+ struct ioq_mgr *ioqmgr;
+#endif
+
};
struct descriptor_table {
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index f252b39..fbffd2f 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -349,6 +349,7 @@ static struct kvm *kvm_create_vm(void)
list_add(&kvm->vm_list, &vm_list);
spin_unlock(&kvm_lock);
}
+ kvmhost_ioqmgr_init(kvm);
return kvm;
}
@@ -3614,6 +3615,8 @@ static __init int kvm_init(void)
bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT;
memset(__va(bad_page_address), 0, PAGE_SIZE);
+ kvmhost_ioqmgr_module_init();
+
return 0;
out:
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index bc2b51e..2cceae3 100755
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -377,6 +377,7 @@ struct kvm_pvnet_config {
* No registers are clobbered by the hypercall, except that the
* return value is in RAX.
*/
+
#define KVM_NR_HYPERCALLS 7
#define __NR_hypercall_test 0
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 7/9] KVM: Add PVBUS support to the KVM host
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (5 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 6/9] KVM: Add support for IOQ Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 8/9] IOQ: Add an IOQ network driver Gregory Haskins
` (2 subsequent siblings)
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
PVBUS allows VMM agnostic PV drivers to discover/configure virtual resources
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/kvm/Kconfig | 10 +
drivers/kvm/Makefile | 3
drivers/kvm/kvm.h | 4
drivers/kvm/kvm_main.c | 4
drivers/kvm/pvbus_host.c | 466 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/kvm/pvbus_host.h | 66 +++++++
6 files changed, 553 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 0f81af1..cb674bb 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -52,6 +52,16 @@ config KVM_IOQ_HOST
depends on KVM
select IOQ
+config KVM_PVBUS_HOST
+ boolean "Paravirtualized Bus (PVBUS) host support"
+ depends on KVM
+ select KVM_IOQ_HOST
+ ---help---
+ PVBUS is an infrastructure for generic PV drivers to take advantage
+ of an underlying hypervisor without having to understand the details
+ of the hypervisor itself. You only need this option if you plan to
+ run PVBUS based PV guests in KVM.
+
config KVM_NET_HOST
tristate "Para virtual network host device"
depends on KVM
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index 2095061..8926fa9 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -7,6 +7,9 @@ kvm-objs := kvm_main.o mmu.o x86_emulate.o
ifeq ($(CONFIG_KVM_IOQ_HOST),y)
kvm-objs += ioq_host.o
endif
+ifeq ($(CONFIG_KVM_PVBUS_HOST),y)
+kvm-objs += pvbus_host.o
+endif
obj-$(CONFIG_KVM) += kvm.o
kvm-intel-objs = vmx.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index c38c84f..8dc9ac3 100755
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
+#include <linux/pvbus.h>
#include "vmx.h"
#include "ioq.h"
@@ -393,6 +394,9 @@ struct kvm {
#ifdef CONFIG_KVM_IOQ_HOST
struct ioq_mgr *ioqmgr;
#endif
+#ifdef CONFIG_KVM_PVBUS_HOST
+ struct kvm_pvbus *pvbus;
+#endif
};
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index fbffd2f..d35ce8d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -44,6 +44,7 @@
#include "x86_emulate.h"
#include "segment_descriptor.h"
+#include "pvbus_host.h"
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
@@ -350,6 +351,7 @@ static struct kvm *kvm_create_vm(void)
spin_unlock(&kvm_lock);
}
kvmhost_ioqmgr_init(kvm);
+ kvm_pvbus_init(kvm);
return kvm;
}
@@ -3616,6 +3618,7 @@ static __init int kvm_init(void)
memset(__va(bad_page_address), 0, PAGE_SIZE);
kvmhost_ioqmgr_module_init();
+ kvm_pvbus_module_init();
return 0;
@@ -3637,6 +3640,7 @@ static __exit void kvm_exit(void)
mntput(kvmfs_mnt);
unregister_filesystem(&kvm_fs_type);
kvm_mmu_module_exit();
+ kvm_pvbus_module_exit();
}
module_init(kvm_init)
diff --git a/drivers/kvm/pvbus_host.c b/drivers/kvm/pvbus_host.c
new file mode 100644
index 0000000..44d81f3
--- /dev/null
+++ b/drivers/kvm/pvbus_host.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/highmem.h>
+
+#include "pvbus.h"
+#include "pvbus_host.h"
+#include "kvm.h"
+
+struct pvbus_map {
+ int (*compare)(const void *left, const void *right);
+ const void* (*getkey)(struct rb_node *node);
+
+ spinlock_t lock;
+ struct rb_root root;
+};
+
+struct _pv_devtype {
+ struct kvm_pv_devtype *item;
+ struct rb_node node;
+ struct list_head devlist;
+};
+
+struct _pv_device {
+ struct kvm_pv_device *item;
+ struct rb_node node;
+ struct list_head list;
+ struct _pv_devtype *parent;
+};
+
+static struct pvbus_map pvbus_typemap; /* stores globally available types */
+
+struct kvm_pvbus {
+ spinlock_t lock;
+ struct pvbus_map typemap; /* stores locally instantiated types */
+ struct pvbus_map devmap;
+};
+
+/*
+ * ------------------
+ * generic rb map management
+ * ------------------
+ */
+
+static void pvbus_map_init(struct pvbus_map *map)
+{
+ spin_lock_init(&map->lock);
+ map->root = RB_ROOT;
+}
+
+static int pvbus_map_register(struct pvbus_map *map, struct rb_node *node)
+{
+ int ret = 0;
+ struct rb_root *root;
+ struct rb_node **new, *parent = NULL;
+
+ spin_lock(&map->lock);
+
+ root = &map->root;
+ new = &(root->rb_node);
+
+ /* Figure out where to put new node */
+ while (*new) {
+ int result = map->compare(map->getkey(node),
+ map->getkey(*new));
+
+ parent = *new;
+
+ if (result < 0)
+ new = &((*new)->rb_left);
+ else if (result > 0)
+ new = &((*new)->rb_right);
+ else {
+ ret = -EEXIST;
+ break;
+ }
+ }
+
+ if (!ret) {
+ /* Add new node and rebalance tree. */
+ rb_link_node(node, parent, new);
+ rb_insert_color(node, root);
+ }
+
+ spin_unlock(&map->lock);
+
+ return ret;
+}
+
+static struct rb_node* pvbus_map_find(struct pvbus_map *map, const void *key)
+{
+ struct rb_node *node;
+
+ spin_lock(&map->lock);
+
+ node = map->root.rb_node;
+
+ while (node) {
+ int result = map->compare(map->getkey(node), key);
+
+ if (result < 0)
+ node = node->rb_left;
+ else if (result > 0)
+ node = node->rb_right;
+ else {
+ break;
+ }
+ }
+
+ spin_unlock(&map->lock);
+
+ return node;
+}
+
+static void pvbus_map_erase(struct pvbus_map *map, struct rb_node *node)
+{
+ spin_lock(&map->lock);
+ rb_erase(node, &map->root);
+ spin_unlock(&map->lock);
+}
+
+/*
+ * ------------------
+ * pv_devtype rb map
+ * ------------------
+ */
+static int pv_devtype_map_compare(const void *left, const void *right)
+{
+ return strcmp((char*)left, (char*)right);
+}
+
+static const void* pv_devtype_map_getkey(struct rb_node *node)
+{
+ struct _pv_devtype *dt;
+
+ dt = container_of(node, struct _pv_devtype, node);
+
+ return dt->item->name;
+}
+
+static void pv_devtype_map_init(struct pvbus_map *map)
+{
+ pvbus_map_init(map);
+
+ map->compare = pv_devtype_map_compare;
+ map->getkey = pv_devtype_map_getkey;
+}
+
+static struct _pv_devtype* devtype_map_find(struct pvbus_map *map,
+ const void *key)
+{
+ struct rb_node *node = pvbus_map_find(map, key);
+ if (!node)
+ return NULL;
+
+ return container_of(node, struct _pv_devtype, node);
+}
+
+/*
+ * ------------------
+ * pv_device rb map
+ * ------------------
+ */
+static int pv_device_map_compare(const void *left, const void *right)
+{
+ u64 lid = *(const u64*)left;
+ u64 rid = *(const u64*)right;
+
+ return lid - rid;
+}
+
+static const void* pv_device_map_getkey(struct rb_node *node)
+{
+ struct _pv_device *dev;
+
+ dev = container_of(node, struct _pv_device, node);
+
+ return &dev->item->id;
+}
+
+static void pv_device_map_init(struct pvbus_map *map)
+{
+ pvbus_map_init(map);
+
+ map->compare = pv_device_map_compare;
+ map->getkey = pv_device_map_getkey;
+}
+
+static struct _pv_device* device_map_find(struct pvbus_map *map,
+ const void *key)
+{
+ struct rb_node *node = pvbus_map_find(map, key);
+ if (!node)
+ return NULL;
+
+ return container_of(node, struct _pv_device, node);
+}
+
+/*
+ * ------------------
+ * hypercall implementation
+ * ------------------
+ */
+
+static int kvm_pvbus_enumerate(struct kvm_pvbus *pvbus,
+ const char* name,
+ struct pvbus_dev inst[],
+ u32 *cnt)
+{
+ struct _pv_devtype *_devtype;
+ struct list_head *pos;
+ u32 avail = *cnt;
+
+ *cnt = 0;
+
+ _devtype = devtype_map_find(&pvbus->typemap, name);
+ if (!_devtype)
+ return -ENOENT;
+
+ list_for_each(pos, &_devtype->devlist) {
+
+ /*
+ * If avail drops to 0 or below, it means we have more
+ * instances than the client has space for. So we simply stop
+ * recording new instances, but allow the loop to continue to
+ * get an accurate count.
+ */
+ if (avail > 0) {
+ struct _pv_device *_dev;
+ struct kvm_pv_device *dev;
+
+ _dev = container_of(pos, struct _pv_device, list);
+ dev = _dev->item;
+
+ inst[*cnt].instance = dev->id;
+ inst[*cnt].version = dev->ver;
+ }
+
+ (*cnt)++;
+ avail--;
+
+ }
+
+ /*
+ * We fail the call if we ran out of space to give the caller the
+ * opportunity to call again with a larger array
+ */
+ if (avail < 0)
+ return -ENOSPC;
+
+ return 0;
+}
+
+static int kvm_pvbus_call(struct kvm_pvbus *pvbus,
+ u64 instance, u32 func, void *data, size_t len)
+{
+ struct kvm_pv_device *dev;
+ struct _pv_device *_dev = device_map_find(&pvbus->devmap,
+ &instance);
+ if (!_dev)
+ return -ENOENT;
+
+ dev = _dev->item;
+
+ return dev->call(dev, func, data, len);
+}
+
+/*
+ * Our hypercall format will always follow with the call-id in arg[0],
+ * a pointer to the arguments in arg[1], and the argument length in arg[2]
+ */
+static unsigned long kvm_pvbus_hc(struct kvm_vcpu *vcpu,
+ unsigned long args[])
+{
+ struct kvm_pvbus *pvbus = vcpu->kvm->pvbus;
+ void *vdata = (void*)gpa_to_hva(vcpu->kvm, args[1]);
+ int ret = -EINVAL;
+
+ /* FIXME: We need to validate vdata so that malicious guests cannot
+ cause the host to segfault */
+
+ switch (args[0])
+ {
+ case KVM_PVBUS_OP_ENUM: {
+ struct enumerate_params *params;
+ struct pvbus_dev *inst;
+
+ params = (struct enumerate_params*)vdata;
+
+ inst = (struct pvbus_dev*)¶ms->data[params->inst_offset];
+
+ ret = kvm_pvbus_enumerate(pvbus,
+ ¶ms->data[params->name_offset],
+ inst,
+ ¶ms->count);
+ }
+ case KVM_PVBUS_OP_CALL: {
+ struct call_params *params;
+ void *data;
+
+ params = (struct call_params*)vdata;
+ data = gpa_to_hva(vcpu->kvm, params->data);
+
+ /*
+ * FIXME: Again, we should validate that
+ *
+ * params->data to params->data+len
+ *
+ * is a valid region owned by the guest
+ */
+
+ ret = kvm_pvbus_call(pvbus, params->inst, params->func,
+ data, params->len);
+
+ /* FIXME: Do we need to unmap the data */
+ }
+ }
+
+ /* FIXME: Do we need to kunmap the vdata? */
+
+ return ret;
+}
+
+int kvm_pvbus_registertype(struct kvm_pv_devtype *devtype)
+{
+ struct _pv_devtype *_devtype = kzalloc(sizeof(*_devtype), GFP_KERNEL);
+ if (!_devtype)
+ return -ENOMEM;
+
+ _devtype->item = devtype;
+ INIT_LIST_HEAD(&_devtype->devlist);
+
+ return pvbus_map_register(&pvbus_typemap, &_devtype->node);
+}
+EXPORT_SYMBOL_GPL(kvm_pvbus_registertype);
+
+int kvm_pvbus_unregistertype(const char *name)
+{
+ /* FIXME: */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_pvbus_unregistertype);
+
+int kvm_pvbus_createinstance(struct kvm *kvm, const char *name,
+ const char *cfg, u64 *id)
+{
+ struct kvm_pvbus *pvbus = kvm->pvbus;
+ struct _pv_devtype *_devtype;
+ struct kvm_pv_devtype *devtype;
+ struct _pv_device *_dev;
+ struct kvm_pv_device *dev;
+ u64 _id;
+ int ret;
+
+ _devtype = devtype_map_find(&pvbus->typemap, name);
+ if (!_devtype) {
+ struct _pv_devtype *gdevtype;
+ /*
+ * If we get here it could be because this is the first
+ * time this devtype has been accessed by this particular
+ * vm. So we need to check the global typemap also
+ */
+ gdevtype = devtype_map_find(&pvbus_typemap, name);
+ if (!gdevtype)
+ /* I guess this is plain old fashioned not present */
+ return -ENOENT;
+
+ /* Else, we need to promote this devtype to the current VM */
+ _devtype = kzalloc(sizeof(*_devtype), GFP_KERNEL);
+ _devtype->item = gdevtype->item;
+ INIT_LIST_HEAD(&_devtype->devlist);
+
+ /* Note that we register it with the pvbus context */
+ ret = pvbus_map_register(&pvbus->typemap, &_devtype->node);
+ if (ret < 0)
+ return ret;
+ }
+
+ devtype = _devtype->item;
+
+ _dev = kzalloc(sizeof(*_dev), GFP_KERNEL);
+ if (!_dev)
+ return -ENOMEM;
+
+ /* We just use the pointer address as a unique id */
+ _id = (u64)_dev;
+
+ ret = devtype->create(kvm, devtype, _id, cfg, &dev);
+ if (ret < 0)
+ goto out_err;
+
+ _dev->item = dev;
+ INIT_LIST_HEAD(&_dev->list);
+ _dev->parent = _devtype;
+
+ pvbus_map_register(&pvbus->devmap, &_dev->node);
+ list_add_tail(&_devtype->devlist, &_dev->list);
+
+ *id = _id;
+
+ return 0;
+
+ out_err:
+ kfree(_dev);
+
+ return ret;
+}
+
+int kvm_pvbus_init(struct kvm *kvm)
+{
+ struct kvm_pvbus *pvbus = kzalloc(sizeof(*pvbus), GFP_KERNEL);
+ if (!pvbus)
+ return -ENOMEM;
+
+ spin_lock_init(&pvbus->lock);
+ pv_devtype_map_init(&pvbus->typemap);
+ pv_device_map_init(&pvbus->devmap);
+
+ kvm->pvbus = pvbus;
+
+ return 0;
+}
+
+__init int kvm_pvbus_module_init(void)
+{
+ struct kvm_hypercall hc;
+
+ pv_devtype_map_init(&pvbus_typemap);
+
+ /* Register our hypercall */
+ hc.hypercall = kvm_pvbus_hc;
+ hc.idx = __NR_hypercall_pvbus;
+
+ kvm_register_hypercall(THIS_MODULE, &hc);
+
+ return 0;
+}
+
+ __exit void kvm_pvbus_module_exit(void)
+{
+ /* FIXME: Unregister our hypercall */
+}
+
+
+
+
diff --git a/drivers/kvm/pvbus_host.h b/drivers/kvm/pvbus_host.h
new file mode 100644
index 0000000..a3cc7a0
--- /dev/null
+++ b/drivers/kvm/pvbus_host.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 _KVM_PVBUS_HOST_H
+#define _KVM_PVBUS_HOST_H
+
+#include <linux/rbtree.h>
+
+#ifdef CONFIG_KVM_PVBUS_HOST
+
+struct kvm;
+
+struct kvm_pvbus;
+
+struct kvm_pv_device {
+ int (*call)(struct kvm_pv_device *t, u32 func, void *data, size_t len);
+ void (*destroy)(struct kvm_pv_device *t);
+
+ u64 id;
+ u32 ver;
+
+};
+
+struct kvm_pv_devtype {
+ int (*create)(struct kvm *kvm,
+ struct kvm_pv_devtype *t, u64 id, const char *cfg,
+ struct kvm_pv_device **dev);
+ void (*destroy)(struct kvm_pv_devtype *t);
+
+ const char *name;
+};
+
+int kvm_pvbus_init(struct kvm *kvm);
+int kvm_pvbus_module_init(void);
+void kvm_pvbus_module_exit(void);
+int kvm_pvbus_registertype(struct kvm_pv_devtype *devtype);
+int kvm_pvbus_unregistertype(const char *name);
+int kvm_pvbus_createinstance(struct kvm *kvm, const char *name,
+ const char *config, u64 *id);
+
+#else /* CONFIG_KVM_PVBUS_HOST */
+
+#define kvm_pvbus_init(kvm) {}
+#define kvm_pvbus_module_init() {}
+#define kvm_pvbus_module_exit() {}
+
+#endif /* CONFIG_KVM_PVBUS_HOST */
+
+#endif /* _KVM_PVBUS_HOST_H */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 8/9] IOQ: Add an IOQ network driver
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (6 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 7/9] KVM: Add PVBUS support to the KVM host Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 9/9] KVM: Add an IOQNET backend driver Gregory Haskins
2007-08-15 2:50 ` [RFC PATCH 0/9] PV device infrastructure v2 Avi Kivity
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/net/Kconfig | 4
drivers/net/Makefile | 2
drivers/net/ioqnet.c | 631 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/ioqnet.h | 42 +++
4 files changed, 679 insertions(+), 0 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index fb99cd4..eb46c07 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2947,6 +2947,10 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
+config IOQNET
+ tristate "IOQ based paravirtualized network driver"
+ select IOQ
+
endif #NETDEVICES
config NETPOLL
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa..f1b4916 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -224,6 +224,8 @@ obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_IOQNET) += ioqnet.o
+
obj-$(CONFIG_FS_ENET) += fs_enet/
obj-$(CONFIG_NETXEN_NIC) += netxen/
diff --git a/drivers/net/ioqnet.c b/drivers/net/ioqnet.c
new file mode 100644
index 0000000..5500631
--- /dev/null
+++ b/drivers/net/ioqnet.c
@@ -0,0 +1,631 @@
+/*
+ * ioqnet - A paravirtualized network device based on the IOQ interface
+ *
+ * Copyright (C) 2007 Novell, Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * Derived from the SNULL example from the book "Linux Device
+ * Drivers" by Alessandro Rubini and Jonathan Corbet, published
+ * by O'Reilly & Associates.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/slab.h> /* kmalloc() */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/in.h>
+#include <linux/netdevice.h> /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h> /* struct iphdr */
+#include <linux/tcp.h> /* struct tcphdr */
+#include <linux/skbuff.h>
+#include <linux/ioq.h>
+#include <linux/pvbus.h>
+
+#include <linux/in6.h>
+#include <asm/checksum.h>
+
+#include <linux/ioqnet.h>
+
+MODULE_AUTHOR("Gregory Haskins");
+MODULE_LICENSE("GPL");
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef IOQNET_DEBUG
+# define PDEBUG(fmt, args...) printk( KERN_DEBUG "ioqnet: " fmt, ## args)
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+#endif
+
+static int timeout = 5; /* In jiffies */
+module_param(timeout, int, 0);
+
+#define RX_RINGLEN 64
+#define TX_RINGLEN 64
+#define TX_PTRS_PER_DESC 64
+
+struct ioqnet_queue {
+ struct ioq *queue;
+ struct ioq_notifier notifier;
+};
+
+struct ioqnet_tx_desc {
+ struct sk_buff *skb;
+ struct ioqnet_tx_ptr data[TX_PTRS_PER_DESC];
+};
+
+struct ioqnet_priv {
+ spinlock_t lock;
+ struct net_device *dev;
+ struct net_device_stats stats;
+ struct ioqnet_queue rxq;
+ struct ioqnet_queue txq;
+ struct tasklet_struct txtask;
+ u64 pvb_instance;
+};
+
+static int ioqnet_queue_init(struct ioqnet_priv *priv,
+ struct ioqnet_queue *q,
+ size_t ringsize,
+ void (*func)(struct ioq_notifier*))
+{
+ int ret = pvbus_ops->ioqmgr->create(pvbus_ops->ioqmgr,
+ &q->queue, ringsize, 0);
+ if (ret < 0)
+ return ret;
+
+ q->notifier.signal = func;
+
+ return 0;
+}
+
+/*
+ * Enable and disable receive interrupts.
+ */
+static void ioqnet_rx_ints(struct net_device *dev, int enable)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq *ioq = priv->rxq.queue;
+ if (enable)
+ ioq_start(ioq, 0);
+ else
+ ioq_stop(ioq, 0);
+}
+
+static void ioqnet_alloc_rx_desc(struct ioq_ring_desc *desc, size_t len)
+{
+ struct sk_buff *skb = dev_alloc_skb(len + 2);
+ BUG_ON(!skb);
+
+ skb_reserve(skb, 2); /* align IP on 16B boundary */
+
+ desc->cookie = (u64)skb;
+ desc->ptr = (u64)__pa(skb->data);
+ desc->len = len; /* total length */
+ desc->alen = 0; /* actual length - to be filled in by host */
+
+ mb();
+ desc->valid = 1;
+ desc->sown = 1; /* give ownership to the south */
+ mb();
+}
+
+static void ioqnet_setup_rx(struct ioqnet_priv *priv)
+{
+ struct ioq *ioq = priv->rxq.queue;
+ struct ioq_iterator iter;
+ int ret;
+ int i;
+
+ /*
+ * We want to iterate on the "valid" index. By default the iterator
+ * will not "autoupdate" which means it will not hypercall the host
+ * with our changes. This is good, because we are really just
+ * initializing stuff here anyway. Note that you can always manually
+ * signal the host with ioq_signal() if the autoupdate feature is not
+ * used.
+ */
+ ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * Seek to the head of the valid index (which should be our first
+ * item, since the queue is brand-new)
+ */
+ ret = ioq_iter_seek(&iter, ioq_seek_head, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * Now populate each descriptor with an empty SKB and mark it valid
+ */
+ for (i = 0; i < RX_RINGLEN; ++i) {
+ ioqnet_alloc_rx_desc(iter.desc, priv->dev->mtu);
+
+ /*
+ * This push operation will simultaneously advance the
+ * valid-head index and increment our position in the queue
+ * by one.
+ */
+ ret = ioq_iter_push(&iter, 0);
+ BUG_ON(ret < 0);
+ }
+}
+
+static void ioqnet_setup_tx(struct ioqnet_priv *priv)
+{
+ struct ioq *ioq = priv->txq.queue;
+ struct ioq_iterator iter;
+ int ret;
+ int i;
+
+ /*
+ * We setup the tx-desc in a similar way to how we did the rx SKBs
+ */
+ ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_head, 0, 0);
+ BUG_ON(ret < 0);
+
+ for (i = 0; i < TX_RINGLEN; ++i) {
+ struct ioq_ring_desc *desc = iter.desc;
+ struct ioqnet_tx_desc *txdesc = kzalloc(sizeof(*txdesc),
+ GFP_KERNEL | GFP_DMA);
+
+ desc->cookie = (u64)txdesc;
+ desc->ptr = (u64)__pa(&txdesc->data[0]);
+ desc->len = TX_PTRS_PER_DESC; /* "len" is "count" */
+ desc->alen = 0;
+ desc->valid = 0; /* mark it "invalid" since payload empty */
+ desc->sown = 0; /* retain ownership until "inuse" */
+
+ /*
+ * One big difference between the RX and TX ring is that
+ * we are going to do an "iter++" here instead of an
+ * "iter->push()". That is because we don't want to actually
+ * advance the valid-index. We use the valid index to
+ * determine the difference between outstanding consumed and
+ * outstanding unconsumed packets
+ */
+ ret = ioq_iter_seek(&iter, ioq_seek_next, 0, 0);
+ BUG_ON(ret < 0);
+ }
+}
+
+/*
+ * Open and close
+ */
+
+int ioqnet_open(struct net_device *dev)
+{
+ netif_start_queue(dev);
+ return 0;
+}
+
+int ioqnet_release(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ return 0;
+}
+
+/*
+ * Configuration changes (passed on by ifconfig)
+ */
+int ioqnet_config(struct net_device *dev, struct ifmap *map)
+{
+ if (dev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
+
+ /* Don't allow changing the I/O address */
+ if (map->base_addr != dev->base_addr) {
+ printk(KERN_WARNING "ioqnet: Can't change I/O address\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* ignore other fields */
+ return 0;
+}
+
+/*
+ * The poll implementation.
+ */
+static int ioqnet_poll(struct net_device *dev, int *budget)
+{
+ int npackets = 0, quota = min(dev->quota, *budget);
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq_iterator iter;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* We want to iterate on the tail of the in-use index */
+ ret = ioq_iter_init(priv->rxq.queue, &iter, ioq_idxtype_inuse, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_tail, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * We stop if we have met the quota or there are no more packets.
+ * The EOM is indicated by finding a packet that is still owned by
+ * the south side
+ */
+ while ((npackets < quota) && (!iter.desc->sown)) {
+ struct sk_buff *skb = (struct sk_buff*)iter.desc->cookie;
+
+ skb_push(skb, iter.desc->alen);
+
+ /* Maintain stats */
+ npackets++;
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += iter.desc->alen;
+
+ /* Pass the buffer up to the stack */
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_receive_skb(skb);
+
+ mb();
+
+ /* Grab a new buffer to put in the ring */
+ ioqnet_alloc_rx_desc(iter.desc, dev->mtu);
+
+ /* Advance the in-use tail */
+ ret = ioq_iter_pop(&iter, 0);
+ BUG_ON(ret < 0);
+
+ /* Toggle the lock */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
+ }
+
+ /*
+ * If we processed all packets, we're done; tell the kernel and
+ * reenable ints
+ */
+ *budget -= npackets;
+ dev->quota -= npackets;
+ if (ioq_empty(priv->rxq.queue, ioq_idxtype_inuse)) {
+ /* FIXME: there is a race with enabling interrupts */
+ netif_rx_complete(dev);
+ ioqnet_rx_ints(dev, 1);
+ ret = 0;
+ } else
+ /* We couldn't process everything. */
+ ret = 1;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* And let the south side know that we changed the rx-queue */
+ ioq_signal(priv->rxq.queue, 0);
+
+ return ret;
+}
+
+/*
+ * Transmit a packet (called by the kernel)
+ */
+int ioqnet_tx_start(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq_iterator viter;
+ struct ioq_iterator uiter;
+ struct ioqnet_tx_desc *txdesc;
+ int ret;
+ int i;
+ unsigned long flags;
+
+ if (skb->len < ETH_ZLEN)
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (ioq_full(priv->txq.queue, ioq_idxtype_valid)) {
+ /*
+ * We must flow-control the kernel by disabling the queue
+ */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_stop_queue(dev);
+ return 0;
+ }
+
+ /*
+ * We want to iterate on the head of both the "inuse" and "valid" index
+ */
+ ret = ioq_iter_init(priv->txq.queue, &viter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+ ret = ioq_iter_init(priv->txq.queue, &uiter, ioq_idxtype_inuse, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&viter, ioq_seek_head, 0, 0);
+ BUG_ON(ret < 0);
+ ret = ioq_iter_seek(&uiter, ioq_seek_head, 0, 0);
+ BUG_ON(ret < 0);
+
+ /* The head pointers should move in lockstep */
+ BUG_ON(uiter.pos != viter.pos);
+
+ dev->trans_start = jiffies; /* save the timestamp */
+ skb_get(skb); /* add a refcount */
+
+ txdesc = (struct ioqnet_tx_desc*)uiter.desc->cookie;
+
+ for (i = 0; i < 1; ++i) { /* Someday we will support SG */
+ txdesc->data[i].len = (u64)skb->len;
+ txdesc->data[i].data = (u64)__pa(skb->data);
+
+ uiter.desc->alen++;
+ }
+
+ txdesc->skb = skb; /* save the skb for future release */
+
+ mb();
+ uiter.desc->valid = 1;
+ uiter.desc->sown = 1; /* give ownership to the south */
+ mb();
+
+ /* Advance both indexes together */
+ ret = ioq_iter_push(&viter, 0);
+ BUG_ON(ret < 0);
+ ret = ioq_iter_push(&uiter, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * This will signal the south side to consume the packet
+ */
+ ioq_signal(priv->txq.queue, 0);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+/*
+ * called by the tx interrupt handler to indicate that one or more packets
+ * have been consumed
+ */
+void ioqnet_tx_complete(unsigned long data)
+{
+ struct ioqnet_priv *priv = (struct ioqnet_priv*)data;
+ struct ioq_iterator iter;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* We want to iterate on the tail of the valid index */
+ ret = ioq_iter_init(priv->rxq.queue, &iter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_tail, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * We are done once we find the first packet either invalid or still
+ * owned by the south-side
+ */
+ while (iter.desc->valid && !iter.desc->sown) {
+ struct ioqnet_tx_desc *txdesc;
+ struct sk_buff *skb;
+
+ txdesc = (struct ioqnet_tx_desc*)iter.desc->cookie;
+ skb = txdesc->skb;
+
+ /* Maintain stats */
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += skb->len;
+
+ /* Reset the descriptor */
+ mb();
+ iter.desc->alen = 0;
+ iter.desc->valid = 0;
+ mb();
+
+ dev_kfree_skb(skb);
+
+ /* Advance the valid-index tail */
+ ret = ioq_iter_pop(&iter, 0);
+ BUG_ON(ret < 0);
+
+ /* Toggle the lock */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
+ }
+
+ /*
+ * If we were previously stopped due to flow control, restart the
+ * processing
+ */
+ if (netif_queue_stopped(priv->dev)
+ && !ioq_full(priv->txq.queue, ioq_idxtype_inuse)) {
+
+ netif_wake_queue(priv->dev);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/*
+ * Ioctl commands
+ */
+int ioqnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ PDEBUG("ioctl\n");
+ return 0;
+}
+
+/*
+ * Return statistics to the caller
+ */
+struct net_device_stats *ioqnet_stats(struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ return &priv->stats;
+}
+
+static void ioq_rx_notify(struct ioq_notifier *notifier)
+{
+ struct ioqnet_priv *priv;
+ struct net_device *dev;
+
+ priv = container_of(notifier, struct ioqnet_priv, rxq.notifier);
+ dev = priv->dev;
+
+ ioqnet_rx_ints(dev, 0); /* Disable further interrupts */
+ netif_rx_schedule(dev);
+}
+
+static void ioq_tx_notify(struct ioq_notifier *notifier)
+{
+ struct ioqnet_priv *priv;
+
+ priv = container_of(notifier, struct ioqnet_priv, txq.notifier);
+
+ tasklet_schedule(&priv->txtask);
+}
+
+/* Perform a hypercall to register/connect our queues */
+static int ioqnet_connect(struct ioqnet_priv *priv)
+{
+ struct ioqnet_connect data = {
+ .rxq = priv->rxq.queue->id,
+ .txq = priv->txq.queue->id,
+ };
+
+ return pvbus_ops->call(priv->pvb_instance, IOQNET_CONNECT,
+ &data, sizeof(data), 0);
+}
+
+/* Perform a hypercall to get the assigned MAC addr */
+static int ioqnet_query_mac(struct ioqnet_priv *priv)
+{
+ return pvbus_ops->call(priv->pvb_instance,
+ IOQNET_QUERY_MAC,
+ priv->dev->dev_addr,
+ ETH_ALEN, 0);
+}
+
+/*
+ * The init function (sometimes called probe).
+ * It is invoked by register_netdev()
+ */
+void ioqnet_init(struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);;
+
+ ether_setup(dev); /* assign some of the fields */
+
+ dev->open = ioqnet_open;
+ dev->stop = ioqnet_release;
+ dev->set_config = ioqnet_config;
+ dev->hard_start_xmit = ioqnet_tx_start;
+ dev->do_ioctl = ioqnet_ioctl;
+ dev->get_stats = ioqnet_stats;
+ dev->poll = ioqnet_poll;
+ dev->weight = 2;
+ dev->hard_header_cache = NULL; /* Disable caching */
+
+ if (ioqnet_query_mac(priv) < 0)
+ printk("IOQNET: Could not obtain MAC address for %lld\n",
+ priv->pvb_instance);
+
+ spin_lock_init(&priv->lock);
+ priv->dev = dev;
+ tasklet_init(&priv->txtask, ioqnet_tx_complete, (unsigned long)priv);
+
+ ioqnet_queue_init(priv, &priv->rxq, RX_RINGLEN, ioq_rx_notify);
+ ioqnet_queue_init(priv, &priv->txq, TX_RINGLEN, ioq_tx_notify);
+
+ ioqnet_setup_rx(priv);
+ ioqnet_setup_tx(priv);
+
+ ioqnet_rx_ints(dev, 1); /* enable receive interrupts */
+ ioq_start(priv->txq.queue, 0); /* enable transmit interrupts */
+
+ /* Now connect the host side driver to us via the PVBUS/IOQ */
+ if (ioqnet_connect(priv) < 0)
+ printk("IOQNET: Could not initialize instance %lld\n",
+ priv->pvb_instance);
+
+}
+
+/*
+ * Finally, the module stuff
+ */
+
+void ioqnet_cleanup(void)
+{
+#if 0
+ if (ioqnet_dev) {
+ unregister_netdev(ioqnet_dev);
+ /* FIXME: free memory in rings */
+ /* FIXME: free IOQ interfaces */
+ free_netdev(ioqnet_dev);
+ }
+#endif
+ return;
+}
+
+#define MAX_DEVICES 16
+
+int ioqnet_init_module(void)
+{
+ int ret = -ENOMEM;
+ struct pvbus_dev devs[MAX_DEVICES];
+ size_t count = MAX_DEVICES;
+ int i;
+
+ ret = pvbus_ops->enumerate("ioqnet", devs, &count, 0);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < count; ++i) {
+ struct net_device *dev;
+ struct pvbus_dev *pdev = &devs[i];
+ struct ioqnet_priv *priv;
+
+ if (pdev->version != IOQNET_VERSION) {
+ printk(KERN_DEBUG "IOQNET: Skipping instance %lld " \
+ "due to mistatched version (found %d, " \
+ "expected %d)\n",
+ pdev->instance, pdev->version, IOQNET_VERSION);
+ continue;
+ }
+
+ dev = alloc_netdev(sizeof(struct ioqnet_priv), "ioq%d",
+ ioqnet_init);
+
+ if (!dev)
+ return -ENOMEM;
+
+ priv = netdev_priv(dev);
+
+ memset(priv, 0, sizeof(*priv));
+
+ /*
+ * Set the PVB instance id for now. The rest will be
+ * configured inside the init function
+ */
+ priv->pvb_instance = pdev->instance;
+
+ ret = register_netdev(dev);
+ if (ret < 0) {
+ printk("ioqnet: error %i registering device \"%s\"\n",
+ ret, dev->name);
+ free_netdev(dev);
+ }
+ }
+
+ return ret;
+}
+
+
+module_init(ioqnet_init_module);
+module_exit(ioqnet_cleanup);
diff --git a/include/linux/ioqnet.h b/include/linux/ioqnet.h
new file mode 100644
index 0000000..1dff3dd
--- /dev/null
+++ b/include/linux/ioqnet.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * IOQ Network Driver
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 _IOQNET_H
+#define _IOQNET_H
+
+#define IOQNET_VERSION 1
+
+/* IOQNET functions (invoked via pvbus_ops->call()) */
+#define IOQNET_CONNECT 1
+#define IOQNET_QUERY_MAC 2
+
+struct ioqnet_connect {
+ ioq_id_t rxq;
+ ioq_id_t txq;
+};
+
+struct ioqnet_tx_ptr {
+ u64 len;
+ u64 data;
+};
+
+#endif /* _IOQNET_H */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH 9/9] KVM: Add an IOQNET backend driver
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (7 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 8/9] IOQ: Add an IOQ network driver Gregory Haskins
@ 2007-08-14 23:34 ` Gregory Haskins
2007-08-15 2:50 ` [RFC PATCH 0/9] PV device infrastructure v2 Avi Kivity
9 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-14 23:34 UTC (permalink / raw)
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---
drivers/kvm/Kconfig | 5
drivers/kvm/Makefile | 2
drivers/kvm/ioqnet_host.c | 566 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 573 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index cb674bb..585581b 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -62,6 +62,11 @@ config KVM_PVBUS_HOST
of the hypervisor itself. You only need this option if you plan to
run PVBUS based PV guests in KVM.
+config KVM_IOQNET
+ tristate "IOQNET host support"
+ depends on KVM
+ select KVM_PVBUS_HOST
+
config KVM_NET_HOST
tristate "Para virtual network host device"
depends on KVM
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index 8926fa9..66e5272 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -22,3 +22,5 @@ kvm-net-host-objs = kvm_net_host.o
obj-$(CONFIG_KVM_NET_HOST) += kvm_net_host.o
kvm-pvbus-objs := ioq_guest.o pvbus_guest.o
obj-$(CONFIG_KVM_PVBUS_GUEST) += kvm-pvbus.o
+kvm-ioqnet-objs := ioqnet_host.o
+obj-$(CONFIG_KVM_IOQNET) += kvm-ioqnet.o
\ No newline at end of file
diff --git a/drivers/kvm/ioqnet_host.c b/drivers/kvm/ioqnet_host.c
new file mode 100644
index 0000000..0f4d055
--- /dev/null
+++ b/drivers/kvm/ioqnet_host.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * ioqnet - A paravirtualized network device based on the IOQ interface.
+ *
+ * This module represents the backend driver for an IOQNET driver on the KVM
+ * platform.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * Derived in part from the SNULL example from the book "Linux Device
+ * Drivers" by Alessandro Rubini and Jonathan Corbet, published
+ * by O'Reilly & Associates.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/slab.h> /* kmalloc() */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/in.h>
+#include <linux/netdevice.h> /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h> /* struct iphdr */
+#include <linux/tcp.h> /* struct tcphdr */
+#include <linux/skbuff.h>
+#include <linux/ioq.h>
+#include <linux/pvbus.h>
+
+#include <linux/in6.h>
+#include <asm/checksum.h>
+#include <linux/ioq.h>
+#include <linux/ioqnet.h>
+#include <linux/highmem.h>
+
+#include "pvbus_host.h"
+#include "kvm.h"
+
+MODULE_AUTHOR("Gregory Haskins");
+MODULE_LICENSE("GPL");
+
+#define IOQNET_NAME "ioqnet"
+
+/*
+ * FIXME: Any "BUG_ON" code that can be triggered by a malicious guest must
+ * be turned into an inject_gp()
+ */
+
+struct ioqnet_queue {
+ struct ioq *queue;
+ struct ioq_notifier notifier;
+};
+
+struct ioqnet_priv {
+ spinlock_t lock;
+ struct kvm *kvm;
+ struct kvm_pv_device pvdev;
+ struct net_device *netdev;
+ struct net_device_stats stats;
+ struct ioqnet_queue rxq;
+ struct ioqnet_queue txq;
+ struct tasklet_struct txtask;
+ int connected;
+ int opened;
+};
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef IOQNET_DEBUG
+# define PDEBUG(fmt, args...) printk( KERN_DEBUG "ioqnet: " fmt, ## args)
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+#endif
+
+/*
+ * Enable and disable receive interrupts.
+ */
+static void ioqnet_rx_ints(struct net_device *dev, int enable)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq *ioq = priv->rxq.queue;
+
+ if (priv->connected) {
+ if (enable)
+ ioq_start(ioq, 0);
+ else
+ ioq_stop(ioq, 0);
+ }
+}
+
+/*
+ * Open and close
+ */
+
+int ioqnet_open(struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+
+ priv->opened = 1;
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+int ioqnet_release(struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+
+ priv->opened = 0;
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+/*
+ * Configuration changes (passed on by ifconfig)
+ */
+int ioqnet_config(struct net_device *dev, struct ifmap *map)
+{
+ if (dev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
+
+ /* Don't allow changing the I/O address */
+ if (map->base_addr != dev->base_addr) {
+ printk(KERN_WARNING "ioqnet: Can't change I/O address\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* ignore other fields */
+ return 0;
+}
+
+/*
+ * The poll implementation.
+ */
+static int ioqnet_poll(struct net_device *dev, int *budget)
+{
+ int npackets = 0, quota = min(dev->quota, *budget);
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq_iterator iter;
+ unsigned long flags;
+ int ret;
+
+ if (!priv->connected)
+ return 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* We want to iterate on the tail of the in-use index */
+ ret = ioq_iter_init(priv->rxq.queue, &iter, ioq_idxtype_inuse, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_tail, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * We stop if we have met the quota or there are no more packets.
+ * The EOM is indicated by finding a packet that is still owned by
+ * the north side
+ */
+ while ((npackets < quota) && iter.desc->sown) {
+ struct ioq_ring_desc *desc = iter.desc;
+ struct ioqnet_tx_ptr *ptr = gpa_to_hva(priv->kvm, desc->ptr);
+ struct sk_buff *skb;
+ int i;
+ size_t len = 0;
+
+ /* First figure out how much of an skb we need */
+ for (i = 0; i < desc->alen; ++i) {
+ len += ptr[i].len;
+ }
+
+ skb = dev_alloc_skb(len + 2);
+ if (!skb) {
+ /* FIXME: This leaks... */
+ printk(KERN_ERR "FATAL: Out of memory on IOQNET\n");
+ netif_stop_queue(dev);
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, 2);
+
+ /* Then copy the data out to our fresh SKB */
+ for (i = 0; i < desc->alen; ++i) {
+ struct ioqnet_tx_ptr *p = &ptr[i];
+ void *d = gpa_to_hva(priv->kvm,
+ p->data);
+
+ memcpy(skb_push(skb, p->len), d, p->len);
+ kunmap(d);
+ }
+
+ /* Maintain stats */
+ npackets++;
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += len;
+
+ /* Pass the buffer up to the stack */
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_receive_skb(skb);
+
+ /*
+ * Ensure that we have finished reading before marking the
+ * state of the queue
+ */
+ mb();
+ desc->sown = 0;
+ mb();
+
+ /* Advance the in-use tail */
+ ret = ioq_iter_pop(&iter, 0);
+ BUG_ON(ret < 0);
+
+ /* Toggle the lock */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
+ }
+
+ /*
+ * If we processed all packets, we're done; tell the kernel and
+ * reenable ints
+ */
+ *budget -= npackets;
+ dev->quota -= npackets;
+ if (ioq_empty(priv->rxq.queue, ioq_idxtype_inuse)) {
+ /* FIXME: there is a race with enabling interrupts */
+ netif_rx_complete(dev);
+ ioqnet_rx_ints(dev, 1);
+ ret = 0;
+ } else
+ /* We couldn't process everything. */
+ ret = 1;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* And let the north side know that we changed the rx-queue */
+ ioq_signal(priv->rxq.queue, 0);
+
+ return ret;
+}
+
+/*
+ * Transmit a packet (called by the kernel)
+ */
+int ioqnet_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ struct ioq_iterator iter;
+ int ret;
+ unsigned long flags;
+ char *data;
+
+ if (skb->len < ETH_ZLEN)
+ return -EINVAL;
+
+ if (!priv->connected)
+ return 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (ioq_full(priv->txq.queue, ioq_idxtype_valid)) {
+ /*
+ * We must flow-control the kernel by disabling the queue
+ */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_stop_queue(dev);
+ return 0;
+ }
+
+ /*
+ * We want to iterate on the head of the "inuse" index
+ */
+ ret = ioq_iter_init(priv->txq.queue, &iter, ioq_idxtype_inuse, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_head, 0, 0);
+ BUG_ON(ret < 0);
+
+ if (skb->len > iter.desc->len)
+ return -EINVAL;
+
+ dev->trans_start = jiffies; /* save the timestamp */
+
+ /* Copy the data to the north-side buffer */
+ data = (char*)gpa_to_hva(priv->kvm, iter.desc->ptr);
+ memcpy(data, skb->data, skb->len);
+ kunmap(data);
+
+ /* Give ownership back to the north */
+ mb();
+ iter.desc->sown = 0;
+ mb();
+
+ /* Advance the index */
+ ret = ioq_iter_push(&iter, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * This will signal the north side to consume the packet
+ */
+ ioq_signal(priv->txq.queue, 0);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+void ioqnet_tx_intr(unsigned long data)
+{
+ struct ioqnet_priv *priv = (struct ioqnet_priv*)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /*
+ * If we were previously stopped due to flow control, restart the
+ * processing
+ */
+ if (netif_queue_stopped(priv->netdev)
+ && !ioq_full(priv->txq.queue, ioq_idxtype_inuse)) {
+
+ netif_wake_queue(priv->netdev);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/*
+ * Ioctl commands
+ */
+int ioqnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ PDEBUG("ioctl\n");
+ return 0;
+}
+
+/*
+ * Return statistics to the caller
+ */
+struct net_device_stats *ioqnet_stats(struct net_device *dev)
+{
+ struct ioqnet_priv *priv = netdev_priv(dev);
+ return &priv->stats;
+}
+
+static void ioq_rx_notify(struct ioq_notifier *notifier)
+{
+ struct ioqnet_priv *priv;
+ struct net_device *dev;
+
+ priv = container_of(notifier, struct ioqnet_priv, rxq.notifier);
+ dev = priv->netdev;
+
+ ioqnet_rx_ints(dev, 0); /* Disable further interrupts */
+ netif_rx_schedule(dev);
+}
+
+static void ioq_tx_notify(struct ioq_notifier *notifier)
+{
+ struct ioqnet_priv *priv;
+
+ priv = container_of(notifier, struct ioqnet_priv, txq.notifier);
+
+ tasklet_schedule(&priv->txtask);
+}
+
+/*
+ * The init function (sometimes called probe).
+ * It is invoked by register_netdev()
+ */
+void ioqnet_init(struct net_device *dev)
+{
+ ether_setup(dev); /* assign some of the fields */
+
+ dev->open = ioqnet_open;
+ dev->stop = ioqnet_release;
+ dev->set_config = ioqnet_config;
+ dev->hard_start_xmit = ioqnet_tx;
+ dev->do_ioctl = ioqnet_ioctl;
+ dev->get_stats = ioqnet_stats;
+ dev->poll = ioqnet_poll;
+ dev->weight = 2;
+ dev->hard_header_cache = NULL; /* Disable caching */
+
+ /* We go "link down" until the guest connects to us */
+ netif_carrier_off(dev);
+
+}
+
+
+/* -------------------------------------------------------------- */
+
+static inline struct ioqnet_priv* to_priv(struct kvm_pv_device *t)
+{
+ return container_of(t, struct ioqnet_priv, pvdev);
+}
+
+
+static int ioqnet_connect(struct ioqnet_priv *priv,
+ ioq_id_t id,
+ struct ioqnet_queue *q,
+ void (*func)(struct ioq_notifier*))
+{
+ int ret;
+ struct ioq_mgr *ioqmgr = priv->kvm->ioqmgr;
+
+ ret = ioqmgr->connect(ioqmgr, id, &q->queue, 0);
+ if (ret < 0)
+ return ret;
+
+ q->notifier.signal = func;
+
+ return 0;
+}
+
+static int ioqnet_pvbus_connect(struct ioqnet_priv *priv,
+ void *data, size_t len)
+{
+ struct ioqnet_connect *cnct = (struct ioqnet_connect*)data;
+ int ret;
+
+ /* We connect the north's rxq to our txq */
+ ret = ioqnet_connect(priv, cnct->rxq, &priv->txq, ioq_tx_notify);
+ if (ret < 0)
+ return ret;
+
+ /* And vice-versa */
+ ret = ioqnet_connect(priv, cnct->txq, &priv->rxq, ioq_rx_notify);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * So now that the guest has connected we can send a "link up" event
+ * to the kernel.
+ */
+ netif_carrier_on(priv->netdev);
+
+ priv->connected = 1;
+
+ return 0;
+}
+
+static int ioqnet_pvbus_query_mac(struct ioqnet_priv *priv,
+ void *data, size_t len)
+{
+ if (len != ETH_ALEN)
+ return -EINVAL;
+
+ memcpy(data, priv->netdev->dev_addr, ETH_ALEN);
+
+ return 0;
+}
+
+/*
+ * This function is invoked whenever a guest calls pvbus_ops->call() against
+ * our instance ID
+ */
+static int ioqnet_pvbus_device_call(struct kvm_pv_device *t, u32 func,
+ void *data, size_t len)
+{
+ struct ioqnet_priv *priv = to_priv(t);
+ int ret = -EINVAL;
+
+ switch (func) {
+ case IOQNET_CONNECT:
+ ret = ioqnet_pvbus_connect(priv, data, len);
+ break;
+ case IOQNET_QUERY_MAC:
+ ret = ioqnet_pvbus_query_mac(priv, data, len);
+ break;
+ }
+
+ return ret;
+}
+
+static void ioqnet_pvbus_device_destroy(struct kvm_pv_device *t)
+{
+
+}
+
+/*
+ * This function is invoked whenever someone instantiates an IOQNET object
+ */
+static int ioqnet_pvbus_devtype_create(struct kvm *kvm,
+ struct kvm_pv_devtype *t, u64 id,
+ const char *cfg,
+ struct kvm_pv_device **pvdev)
+{
+ struct net_device *dev;
+ struct ioqnet_priv *priv;
+ int ret;
+
+ dev = alloc_netdev(sizeof(struct ioqnet_priv), "ioq%d",
+ ioqnet_init);
+ if (!dev)
+ return -ENOMEM;
+
+ priv = netdev_priv(dev);
+
+ memset(priv, 0, sizeof(*priv));
+
+ priv->pvdev.call = ioqnet_pvbus_device_call;
+ priv->pvdev.destroy = ioqnet_pvbus_device_destroy;
+ priv->pvdev.id = id;
+ priv->pvdev.ver = IOQNET_VERSION;
+
+ spin_lock_init(&priv->lock);
+ priv->kvm = kvm;
+ priv->netdev = dev;
+ tasklet_init(&priv->txtask, ioqnet_tx_intr, (unsigned long)priv);
+
+ ret = register_netdev(dev);
+ if (ret < 0) {
+ printk("ioqnet: error %i registering device \"%s\"\n",
+ ret, dev->name);
+ free_netdev(dev);
+ }
+
+ *pvdev = &priv->pvdev;
+
+ return 0;
+}
+
+static void ioqnet_pvbus_devtype_destroy(struct kvm_pv_devtype *t)
+{
+
+}
+
+static struct kvm_pv_devtype ioqnet_devtype = {
+ .create = ioqnet_pvbus_devtype_create,
+ .destroy = ioqnet_pvbus_devtype_destroy,
+ .name = IOQNET_NAME,
+};
+
+static int __init ioqnet_init_module(void)
+{
+ return kvm_pvbus_registertype(&ioqnet_devtype);
+}
+
+static void __exit ioqnet_cleanup_module(void)
+{
+ kvm_pvbus_unregistertype(IOQNET_NAME);
+}
+
+module_init(ioqnet_init_module);
+module_exit(ioqnet_cleanup_module);
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
` (8 preceding siblings ...)
2007-08-14 23:34 ` [RFC PATCH 9/9] KVM: Add an IOQNET backend driver Gregory Haskins
@ 2007-08-15 2:50 ` Avi Kivity
[not found] ` <46C269EE.10807-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
9 siblings, 1 reply; 23+ messages in thread
From: Avi Kivity @ 2007-08-15 2:50 UTC (permalink / raw)
To: Gregory Haskins; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Gregory Haskins wrote:
> This series incorporates all of v1 plus the following changes based on
> feedback to date:
>
Are you positioning this as an alternative to virtio? If so, be aware
that virtio is (a) mostly done (b) very well done.
Can you describe what you are trying to achieve that virtio doesn't do?
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <46C269EE.10807-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2007-08-15 3:47 ` Gregory Haskins
[not found] ` <1187149634.4165.151.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-15 4:52 ` Rusty Russell
1 sibling, 1 reply; 23+ messages in thread
From: Gregory Haskins @ 2007-08-15 3:47 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Wed, 2007-08-15 at 05:50 +0300, Avi Kivity wrote:
> Gregory Haskins wrote:
> > This series incorporates all of v1 plus the following changes based on
> > feedback to date:
> >
>
> Are you positioning this as an alternative to virtio?
Absolutely not! I really just want to see a decent PV-IO solution
working.
When I originally started this project virtio didn't exist. And even
recently I was under the impression that there was no implementation of
virtio for KVM in existence. I just learned this morning that Dor is
pretty close to getting something working, but that was news to me.
> If so, be aware that virtio is (a) mostly done (b) very well done.
I would very much like to help make virtio work, which is really where I
was going with this. My design is a little bit different so I was
submitting it in case there was any ideas worth salvaging to be picked
up by the official project. (I tried to explain this in the v1
announcement so I apologize if anyone, particularly Rusty, felt
slighted....it was not my intention)
>
> Can you describe what you are trying to achieve that virtio doesn't do?
>
To be perfectly honest, I have never been able to find an implementation
of virtio (I looked and even asked Rusty directly via email but never
found/heard anything back) so I don't know exactly what its capabilities
are. My impressions from reading Rusty's email proposals are that there
are certainly similarities to the virtio interface and the ioq interface
in concept. Where they seem to differ is that the concept of the ring
is more exposed in IOQ via the iterator idiom instead of the sg-buffer
idiom.
At the time I first saw the virtio proposals, I couldn't quite wrap my
head around how I could do things like "zero copy" + deferred pointer
reaping, which was a design goal of mine. So I kept up with the IOQ
design for the interim to at least demonstrate where I was trying to go.
Perhaps it will be a useful innovation and the virtio interface design
will pick up some of my ideas. Perhaps virtio deals with it already.
Or perhaps no one will think its a good idea and it gets pushed
to /dev/null ;) I am not sure what the answer will be.
But in any case, I was also trying to go beyond the shared-ring
interface design. For instance, the series also provides:
*) a system for efficiently discovering/communicating with PV backend
devices that was not laden with legacy interfaces like PCI. (I am in
the process of converting over to use bus_register as Dor suggested).
*) generalization of as much of the shared-memory code as possible so it
could be reused (for instance, both guest and host can use the same IOQ
interface, and the code itself will largely work with any hypervisor, or
even non-hypervisor shared-memory systems, like RDMA/AMP).
Again, perhaps virtio will cover all these areas too. Without having
seen it I am not really sure where the overlap exists, but perhaps there
will be at least some aspects of my series that are useful. That is why
I submitted it. Ideally I can hook up with whomever is working on the
implementation (sounds like Dor?) and we can crank something out
together. :)
Again, apologies if anyone felt slighted. :(
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187149634.4165.151.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
@ 2007-08-15 3:58 ` Avi Kivity
[not found] ` <46C279E6.40004-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Avi Kivity @ 2007-08-15 3:58 UTC (permalink / raw)
To: Gregory Haskins; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Gregory Haskins wrote:
>
>> If so, be aware that virtio is (a) mostly done (b) very well done.
>>
>
> I would very much like to help make virtio work, which is really where I
> was going with this. My design is a little bit different so I was
> submitting it in case there was any ideas worth salvaging to be picked
> up by the official project. (I tried to explain this in the v1
> announcement so I apologize if anyone, particularly Rusty, felt
> slighted....it was not my intention)
>
Alternative implementation ideas should of course not slight anyone but
instead be welcomed.
>
>> Can you describe what you are trying to achieve that virtio doesn't do?
>>
>>
>
> To be perfectly honest, I have never been able to find an implementation
> of virtio (I looked and even asked Rusty directly via email but never
> found/heard anything back) so I don't know exactly what its capabilities
> are. My impressions from reading Rusty's email proposals are that there
> are certainly similarities to the virtio interface and the ioq interface
> in concept. Where they seem to differ is that the concept of the ring
> is more exposed in IOQ via the iterator idiom instead of the sg-buffer
> idiom.
>
Yes. virtio adapts the driver interface to an API can drive a shared
memory queue more easily, while you actually provide the queue protocol
(and ABI).
> At the time I first saw the virtio proposals, I couldn't quite wrap my
> head around how I could do things like "zero copy" + deferred pointer
> reaping, which was a design goal of mine. So I kept up with the IOQ
> design for the interim to at least demonstrate where I was trying to go.
> Perhaps it will be a useful innovation and the virtio interface design
> will pick up some of my ideas. Perhaps virtio deals with it already.
> Or perhaps no one will think its a good idea and it gets pushed
> to /dev/null ;) I am not sure what the answer will be.
>
> But in any case, I was also trying to go beyond the shared-ring
> interface design. For instance, the series also provides:
>
> *) a system for efficiently discovering/communicating with PV backend
> devices that was not laden with legacy interfaces like PCI. (I am in
> the process of converting over to use bus_register as Dor suggested).
>
> *) generalization of as much of the shared-memory code as possible so it
> could be reused (for instance, both guest and host can use the same IOQ
> interface, and the code itself will largely work with any hypervisor, or
> even non-hypervisor shared-memory systems, like RDMA/AMP).
>
> Again, perhaps virtio will cover all these areas too. Without having
> seen it I am not really sure where the overlap exists, but perhaps there
> will be at least some aspects of my series that are useful. That is why
> I submitted it. Ideally I can hook up with whomever is working on the
> implementation (sounds like Dor?) and we can crank something out
> together. :)
>
virtio seems to have more modest goals:
- make it easier to write guest/host (or guest/guest) transports, but
not actually provide them
- limited to guest only (and Linux only)
- no discovery/hotplug (yet?)
since it wants to be hypervisor agnostic, it cannot specify an ABI (as
some already have ABIs, for example Xen).
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <46C279E6.40004-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2007-08-15 4:13 ` Gregory Haskins
[not found] ` <1187151233.4165.166.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Gregory Haskins @ 2007-08-15 4:13 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Wed, 2007-08-15 at 06:58 +0300, Avi Kivity wrote:
>
>
> Yes. virtio adapts the driver interface to an API can drive a shared
> memory queue more easily, while you actually provide the queue protocol
> (and ABI).
If I understand what you are saying, it actually jives with something
that struck me as a potentially win-win a while back when I first heard
about virtio. That is: you can actually implement virtio with ioq. I
am not sure if that idea has any merit or not, especially given the news
that virtio for KVM is almost done....but I thought I would mention it.
>
> virtio seems to have more modest goals:
>
> - make it easier to write guest/host (or guest/guest) transports, but
> not actually provide them
> - limited to guest only (and Linux only)
> - no discovery/hotplug (yet?)
As an aside, the version of the pvbus that I am working on right now
(v3?) adds hotplug capability. I assume that there is some merit to me
continuing the work at least on the discovery/hotplug front then?
>
> since it wants to be hypervisor agnostic, it cannot specify an ABI (as
> some already have ABIs, for example Xen).
I see, and that is a good point. By only being an API, virtio can work
over XenBus or any other ABI it wants. IOQ is an API *and* an ABI.
While this doesnt preclude it from ever working on Xen, it does imply
that you would need to add the IOQ ABI to the Xen infrastructure if you
wanted to use it (at least, if you wanted to use it directly instead of
doing some kind of funky queue-in-queue with IOQ on XenBus..yuk).
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187151233.4165.166.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
@ 2007-08-15 4:31 ` Anthony Liguori
2007-08-15 12:15 ` Gregory Haskins
1 sibling, 0 replies; 23+ messages in thread
From: Anthony Liguori @ 2007-08-15 4:31 UTC (permalink / raw)
To: Gregory Haskins; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Wed, 2007-08-15 at 00:13 -0400, Gregory Haskins wrote:
> On Wed, 2007-08-15 at 06:58 +0300, Avi Kivity wrote:
> >
> >
> > Yes. virtio adapts the driver interface to an API can drive a shared
> > memory queue more easily, while you actually provide the queue protocol
> > (and ABI).
>
> If I understand what you are saying, it actually jives with something
> that struck me as a potentially win-win a while back when I first heard
> about virtio. That is: you can actually implement virtio with ioq. I
> am not sure if that idea has any merit or not, especially given the news
> that virtio for KVM is almost done....but I thought I would mention it.
BTW, the lguest virtio implementation is available in Rusty's patch
queue (linked off http://lguest.ozlabs.org).
Regards,
Anthony Liguori
> >
> > virtio seems to have more modest goals:
> >
> > - make it easier to write guest/host (or guest/guest) transports, but
> > not actually provide them
> > - limited to guest only (and Linux only)
> > - no discovery/hotplug (yet?)
>
> As an aside, the version of the pvbus that I am working on right now
> (v3?) adds hotplug capability. I assume that there is some merit to me
> continuing the work at least on the discovery/hotplug front then?
> >
> > since it wants to be hypervisor agnostic, it cannot specify an ABI (as
> > some already have ABIs, for example Xen).
>
> I see, and that is a good point. By only being an API, virtio can work
> over XenBus or any other ABI it wants. IOQ is an API *and* an ABI.
> While this doesnt preclude it from ever working on Xen, it does imply
> that you would need to add the IOQ ABI to the Xen infrastructure if you
> wanted to use it (at least, if you wanted to use it directly instead of
> doing some kind of funky queue-in-queue with IOQ on XenBus..yuk).
>
> -Greg
>
>
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> kvm-devel mailing list
> kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
> https://lists.sourceforge.net/lists/listinfo/kvm-devel
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <46C269EE.10807-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-08-15 3:47 ` Gregory Haskins
@ 2007-08-15 4:52 ` Rusty Russell
[not found] ` <1187153531.11093.119.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
1 sibling, 1 reply; 23+ messages in thread
From: Rusty Russell @ 2007-08-15 4:52 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Wed, 2007-08-15 at 05:50 +0300, Avi Kivity wrote:
> Gregory Haskins wrote:
> > This series incorporates all of v1 plus the following changes based on
> > feedback to date:
> >
>
> Are you positioning this as an alternative to virtio? If so, be aware
> that virtio is (a) mostly done (b) very well done.
>
> Can you describe what you are trying to achieve that virtio doesn't do?
As far as I can tell, Gregory in angling to take over the virtio work 8)
Given how little cycles I've been able to spare recently, I think it's a
good idea.
I'm not particularly attached to the current virtio implementation,
although I think the interface is getting pretty close. I'd love to see
Gregory take over the implementation part...
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187153531.11093.119.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2007-08-15 7:52 ` Dor Laor
[not found] ` <64F9B87B6B770947A9F8391472E032160D309340-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Dor Laor @ 2007-08-15 7:52 UTC (permalink / raw)
To: Rusty Russell, Avi Kivity, Gregory Haskins
Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
>> > This series incorporates all of v1 plus the following changes based
>on
>> > feedback to date:
>> >
>>
>> Are you positioning this as an alternative to virtio? If so, be
aware
>> that virtio is (a) mostly done (b) very well done.
>>
>> Can you describe what you are trying to achieve that virtio doesn't
>do?
>
>As far as I can tell, Gregory in angling to take over the virtio work
8)
>
>Given how little cycles I've been able to spare recently, I think it's
a
>good idea.
It is a good idea if the current implementatin is enhanced instead of
being replaced.
I also like to move in small steps each time:
- Implement a simple virtio backend for KVM. I just made it work,
using userspace only part.
- Make it stable and support all sort of options (config mac,
multicast, gso,..)
- Improve performance by having the backend in-kernel.
- Once we have a clear view of a good implementation, we can generalize
it by
a layer similat to IOQ or lguest_dma. IMHO lguest is well written
(and documented,
cheers Rusty) and we should take/generalize as much code as possible
instead of
rewriting it.
So bottom line, what we like to see in KVM is very similar to lguest's
bus/dma.
Maybe those can be generelized in a similar way to virtio, while keeping
the code
itslef and code style identical.
btw: Rusty, I tried to apply the new-io-lguest* patches and they failed
to apply cleanly.
What base repo do you use for that?
>
>I'm not particularly attached to the current virtio implementation,
>although I think the interface is getting pretty close. I'd love to
see
>Gregory take over the implementation part...
If the above is followed, any enhancement will be appriciated.
>
>Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <64F9B87B6B770947A9F8391472E032160D309340-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
@ 2007-08-15 12:06 ` Gregory Haskins
[not found] ` <1187179582.4165.197.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-16 0:03 ` Rusty Russell
1 sibling, 1 reply; 23+ messages in thread
From: Gregory Haskins @ 2007-08-15 12:06 UTC (permalink / raw)
To: Dor Laor; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Avi Kivity
On Wed, 2007-08-15 at 00:52 -0700, Dor Laor wrote:
> If the above is followed, any enhancement will be appriciated.
Since I am close, I will probably make at least one more v3 drop "as is"
with the new lguest_bus inspired pvbus (with hotplug, etc). From there,
we can (virtually) get together and figure out what can be used
directly, what can be used in spirit, and what should be thrown away.
Dor, I know you mentioned you wanted to go stepwise, but note that I
*did* break it up into a series. I just delivered it all at once ;)
But the fact is, I really need to do this stuff in-kernel so I am very
much interested in getting the solution designed with that in mind from
the get-go. So note that you will continue to see a series that is
oriented to support both your userspace approach and my current
in-kernel direction. (Note that my current series doesn't deal with the
userspace side yet).
Please point me to your current branch when it is available for me to
look at. I'm looking forward to helping out here!
Regards,
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187151233.4165.166.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-15 4:31 ` Anthony Liguori
@ 2007-08-15 12:15 ` Gregory Haskins
1 sibling, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-15 12:15 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Wed, 2007-08-15 at 00:13 -0400, Gregory Haskins wrote:
> On Wed, 2007-08-15 at 06:58 +0300, Avi Kivity wrote:
> > since it wants to be hypervisor agnostic, it cannot specify an ABI (as
> > some already have ABIs, for example Xen).
>
> I see, and that is a good point. By only being an API, virtio can work
> over XenBus or any other ABI it wants. IOQ is an API *and* an ABI.
> While this doesnt preclude it from ever working on Xen, it does imply
> that you would need to add the IOQ ABI to the Xen infrastructure if you
> wanted to use it (at least, if you wanted to use it directly instead of
> doing some kind of funky queue-in-queue with IOQ on XenBus..yuk).
I think I misspoke when I said this (it was up way to late for coherent
thought ;)
While what you said is true (virtio = API, IOQ = API+ABI) note that I
believe both can be considered hypervisor agnostic. (That was a primary
design goal of mine). All the hypervisor would need to do is write an
ioq_mgr layer. Xen for instance, could use either hypercalls/interrupts
directly like I do for the KVM implementation. Or it could use XenBus
as a signaling transport.
I am only bringing this up as a correction to my statement, not to try
to sway someone in some kind of IOQ vs VirtIO debate. :)
Regards,
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187179582.4165.197.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
@ 2007-08-15 22:37 ` Dor Laor
[not found] ` <64F9B87B6B770947A9F8391472E032160D3B02FB-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Dor Laor @ 2007-08-15 22:37 UTC (permalink / raw)
To: Gregory Haskins; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Avi Kivity
>Since I am close, I will probably make at least one more v3 drop "as
is"
>with the new lguest_bus inspired pvbus (with hotplug, etc). From
there,
>we can (virtually) get together and figure out what can be used
>directly, what can be used in spirit, and what should be thrown away.
Sure thing.
>
>Dor, I know you mentioned you wanted to go stepwise, but note that I
>*did* break it up into a series. I just delivered it all at once ;)
The series is good, though personally I prefer to test each stage using
live packets. Well, I recon the IOQ already tested and only the other
mechanisms
are new.
>
>But the fact is, I really need to do this stuff in-kernel so I am very
>much interested in getting the solution designed with that in mind from
>the get-go. So note that you will continue to see a series that is
>oriented to support both your userspace approach and my current
>in-kernel direction. (Note that my current series doesn't deal with
the
>userspace side yet).
>
>Please point me to your current branch when it is available for me to
>look at. I'm looking forward to helping out here!
Currently things at my end are a bit broken since I replaced the dma
backend with a generic dma based on Rusty's code. Hope that it will work
tomorrow.
If you'll be quick enough you can rip the lguest_bus into a very light
weight
virtio_bus. Please keep it thin as possible, Rusty's code is 217 lines
long, half
of it comments. I'm planing to have a flexible use of this bus while one
can either choose virtio_bus or pci bus.
>
>Regards,
>-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <64F9B87B6B770947A9F8391472E032160D3B02FB-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
@ 2007-08-15 23:56 ` Gregory Haskins
0 siblings, 0 replies; 23+ messages in thread
From: Gregory Haskins @ 2007-08-15 23:56 UTC (permalink / raw)
To: Dor Laor; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Avi Kivity
On Wed, 2007-08-15 at 15:37 -0700, Dor Laor wrote:
>
> If you'll be quick enough you can rip the lguest_bus into a very light
> weight
> virtio_bus. Please keep it thin as possible, Rusty's code is 217 lines
> long, half
> of it comments. I'm planing to have a flexible use of this bus while one
> can either choose virtio_bus or pci bus.
Already done ;)
Its not quite polished yet. I will send tomorrow. Currently it looks
like this:
arch/x86_64/Kconfig | 2
drivers/Makefile | 1
drivers/pvbus/Kconfig | 7 +++
drivers/pvbus/Makefile | 6 ++
drivers/pvbus/pvbus-driver.c | 89
+++++++++++++++++++++++++++++++++++++++++++
include/linux/pvbus.h | 55 ++++++++++++++++++++++++++
6 files changed, 160 insertions(+)
Of course its still IOQ oriented currently, but we can reconcile that
when we get together.
-Greg
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <64F9B87B6B770947A9F8391472E032160D309340-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
2007-08-15 12:06 ` Gregory Haskins
@ 2007-08-16 0:03 ` Rusty Russell
[not found] ` <1187222609.11093.141.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
1 sibling, 1 reply; 23+ messages in thread
From: Rusty Russell @ 2007-08-16 0:03 UTC (permalink / raw)
To: Dor Laor; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Avi Kivity
On Wed, 2007-08-15 at 00:52 -0700, Dor Laor wrote:
> btw: Rusty, I tried to apply the new-io-lguest* patches and they failed
> to apply cleanly.
> What base repo do you use for that?
Sorry, with all the movement of getting lguest in tree, those patches
have rotted slightly (particularly the new-io-lguest-readwrite.patch
which needs a complete rework).
I've restored them now (well, they apply and compile again...)
Cheers,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH 0/9] PV device infrastructure v2
[not found] ` <1187222609.11093.141.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2007-08-16 8:07 ` Dor Laor
0 siblings, 0 replies; 23+ messages in thread
From: Dor Laor @ 2007-08-16 8:07 UTC (permalink / raw)
To: Rusty Russell; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Avi Kivity
>> btw: Rusty, I tried to apply the new-io-lguest* patches and they
>failed
>> to apply cleanly.
>> What base repo do you use for that?
>
>Sorry, with all the movement of getting lguest in tree, those patches
>have rotted slightly (particularly the new-io-lguest-readwrite.patch
>which needs a complete rework).
>
>I've restored them now (well, they apply and compile again...)
I tried to apply the series on 2.6.23-rc3 and it failed :(
I tried to apply all the series (looks like virtio doesn't have the arch
independent support)
and only the the virtio patches broke in the lguest-desc patch.
-- Dor.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2007-08-16 8:07 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-14 23:33 [RFC PATCH 0/9] PV device infrastructure v2 Gregory Haskins
[not found] ` <20070814233352.11895.55788.stgit-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-14 23:33 ` [RFC PATCH 1/9] IOQ: Adding basic definitions for IO-Queue logic Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 2/9] PARAVIRTUALIZATION: Add support for a bus abstraction Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 3/9] IRQ: Export create_irq/destroy_irq Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 4/9] KVM: Add a guest side driver for IOQ Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 5/9] KVM: Add a gpa_to_hva helper function Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 6/9] KVM: Add support for IOQ Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 7/9] KVM: Add PVBUS support to the KVM host Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 8/9] IOQ: Add an IOQ network driver Gregory Haskins
2007-08-14 23:34 ` [RFC PATCH 9/9] KVM: Add an IOQNET backend driver Gregory Haskins
2007-08-15 2:50 ` [RFC PATCH 0/9] PV device infrastructure v2 Avi Kivity
[not found] ` <46C269EE.10807-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-08-15 3:47 ` Gregory Haskins
[not found] ` <1187149634.4165.151.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-15 3:58 ` Avi Kivity
[not found] ` <46C279E6.40004-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-08-15 4:13 ` Gregory Haskins
[not found] ` <1187151233.4165.166.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-15 4:31 ` Anthony Liguori
2007-08-15 12:15 ` Gregory Haskins
2007-08-15 4:52 ` Rusty Russell
[not found] ` <1187153531.11093.119.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-08-15 7:52 ` Dor Laor
[not found] ` <64F9B87B6B770947A9F8391472E032160D309340-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
2007-08-15 12:06 ` Gregory Haskins
[not found] ` <1187179582.4165.197.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-08-15 22:37 ` Dor Laor
[not found] ` <64F9B87B6B770947A9F8391472E032160D3B02FB-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
2007-08-15 23:56 ` Gregory Haskins
2007-08-16 0:03 ` Rusty Russell
[not found] ` <1187222609.11093.141.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-08-16 8:07 ` Dor Laor
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.