>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 <[EMAIL PROTECTED]>
>---
>
> include/linux/ioq.h | 178 +++++++++++++++++++++++++++++++++++++++++
> lib/Kconfig | 11 +++
> lib/Makefile | 1
> lib/ioq.c | 219
>+++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 409 insertions(+), 0 deletions(-)
>
>diff --git a/include/linux/ioq.h b/include/linux/ioq.h
>new file mode 100644
>index 0000000..52f68f5
>--- /dev/null
>+++ b/include/linux/ioq.h
>@@ -0,0 +1,178 @@
>+/*
>+ * 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).
Why not use the standard naming for guest/host or front/backend?
>+ * #) 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 <[EMAIL PROTECTED]>
>+ *
>+ * This file is free software; you can redistribute it and/or modify
>+ * it under the terms of version 2 of the GNU General Public License
>+ * as published by the Free Software Foundation.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
>+ */
>+
>+#ifndef _LINUX_IOQ_H
>+#define _LINUX_IOQ_H
>+
>+#include <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 */
I didn’t see usage for cookie in downstream patches. Is it obslete?
>+ u64 ptr;
>+ u64 offset;
The ptr & offset can be united.
Making the ring_desc small will help keeping such an array in a single page.
>+ u64 len;
>+ u64 alen;
What's alen?
>+ u8 valid;
>+ u8 sown; /* South owned = 1, North owned = 0 */
What about no-one owns it? if you plan of using the valid field you might need
to handle complex races.
>+};
>+
>+#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;
full = head==tail ???
>+};
>+
>+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;
>+ unsigned long flags;
>+ int update;
>+ struct ioq_ring_idx *idx;
>+ u32 pos;
>+ struct ioq_ring_desc *desc;
>+};
>+
>+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;
Why have a notifier in a separate structure?
>+};
>+
>+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(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..a808047
>--- /dev/null
>+++ b/lib/ioq.c
>@@ -0,0 +1,219 @@
>+/*
>+ * Copyright 2007 Novell. All Rights Reserved.
>+ *
>+ * See include/linux/ioq.h for documentation
>+ *
>+ * Author:
>+ * Gregory Haskins <[EMAIL PROTECTED]>
>+ *
>+ * This file is free software; you can redistribute it and/or modify
>+ * it under the terms of version 2 of the GNU General Public License
>+ * as published by the Free Software Foundation.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
>+ */
>+
>+#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;
>+
>+ ret = ioq_iter_seek(iter, ioq_seek_next, 0, flags);
Instead of the above code I would call to iter_seek and do everything inside
then return a proper error code if needed.
>+
>+ 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;
>+
>+ 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(struct ioq *ioq, struct ioq_iterator *iter,
>+ enum ioq_idx_type type, int flags)
ioq_iter_init ?
>+{
>+ BUG_ON((type < 0) || (type >= ioq_idxtype_invalid));
>+
>+ iter->ioq = ioq;
>+ iter->flags = 0;
>+ 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);
>+
>+int ioq_start(struct ioq *ioq, int flags)
>+{
>+ struct ioq_irq *irq = &ioq->head_desc->irq[ioq->locale];
>+
>+ irq->enabled = 1;
>+ 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;
>+
>+ 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;
>+ 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;
>+
>+ 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/
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel