* [PATCH][3/17] USB virt 2.6 split driver---xenidc buffer references
@ 2005-11-21 13:18 harry
2005-11-21 20:31 ` Muli Ben-Yehuda
0 siblings, 1 reply; 3+ messages in thread
From: harry @ 2005-11-21 13:18 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 758 bytes --]
This patch implements the generic code to support local and remote
buffer references for the xenidc transport which is used by the USB
driver.
Local buffer references are used to describe local memory and are
converted into remote buffer references for communication with other
domains. The other domains use remote buffer references to map the
buffers into their local address space for bulk data transfer.
Grant references provide a mechanism to share memory on a per-page basis
and couple the client to a specific memory sharing mechanism. Remote
buffer references provide a memory sharing mechanism on a more
convenient whole-buffer basis and are independent of the underlying
implementation.
Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>
[-- Attachment #2: p3-xenidc-buffer-references.patch --]
[-- Type: text/x-patch, Size: 56015 bytes --]
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile Sun Nov 20 14:54:21 2005
@@ -4,3 +4,5 @@
xenidc-objs += xenidc_callback.o
xenidc-objs += xenidc_work.o
xenidc-objs += xenidc_buffer_resource_provider.o
+xenidc-objs += xenidc_local_buffer_reference.o
+xenidc-objs += xenidc_remote_buffer_reference.o
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_local_buffer_reference.c
--- /dev/null Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_local_buffer_reference.c Sun Nov 20 14:54:21 2005
@@ -0,0 +1,627 @@
+/*****************************************************************************/
+/* Xen inter-domain communication local buffer references. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_local_buffer_reference.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "xenidc_trace.h"
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN( X, Y ) ( ( (X) < (Y) ) ? (X) : (Y) )
+
+#define XENIDC_BUFFER_HASH_COUNT 255
+
+static DEFINE_RWLOCK(xenidc_local_buffer_reference_lock);
+
+static struct list_head xenidc_buffer_concrete_hash[XENIDC_BUFFER_HASH_COUNT];
+
+static struct list_head xenidc_buffer_copy_hash[XENIDC_BUFFER_HASH_COUNT];
+
+static struct list_head xenidc_buffer_virtual_hash[XENIDC_BUFFER_HASH_COUNT];
+
+static void xenidc_local_buffer_reference_init(void)
+{
+ trace();
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ {
+ static int initialised = 0;
+
+ if (!initialised) {
+ int i;
+
+ for (i = 0; i < XENIDC_BUFFER_HASH_COUNT; i++) {
+ INIT_LIST_HEAD
+ (&xenidc_buffer_concrete_hash[i]);
+ INIT_LIST_HEAD(&xenidc_buffer_copy_hash
+ [i]);
+ INIT_LIST_HEAD
+ (&xenidc_buffer_virtual_hash[i]);
+ }
+
+ initialised = 1;
+ }
+ }
+
+ write_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+ }
+}
+
+static void xenidc_local_buffer_reference_default_zero
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr) {
+ trace();
+
+ {
+ u8 buffer[64];
+
+ xenidc_local_buffer_reference temp_lbr = *lbr;
+
+ memset(buffer, 0, 64);
+
+ do {
+ xenidc_buffer_byte_count this_go =
+ MIN(temp_lbr.byte_count, 64);
+
+ class->copy_in_or_out(class, &temp_lbr, buffer, this_go,
+ 0);
+
+ xenidc_local_buffer_reference_advance(&temp_lbr,
+ this_go);
+ }
+ while (temp_lbr.byte_count != 0);
+ }
+}
+
+xenidc_buffer_type xenidc_local_buffer_reference_register_buffer_concrete_class
+ (xenidc_buffer_concrete_class * class, void (*copy_in_or_out)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ void *buffer, xenidc_buffer_byte_count byte_count, int out), void (*zero)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr), int (*calculate_rbr_resources)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_list * list),
+ xenidc_buffer_concrete_class ** (*create_rbr)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ xenidc_remote_buffer_reference * rbr,
+ int access_flags), void (*revoke_rbr)
+ (xenidc_buffer_concrete_class ** context, xenidc_callback * callback)
+ ) {
+ trace();
+
+ xenidc_local_buffer_reference_init();
+
+ INIT_LIST_HEAD(&class->link);
+
+ if (zero == NULL) {
+ zero = xenidc_local_buffer_reference_default_zero;
+ }
+
+ class->copy_in_or_out = copy_in_or_out;
+ class->zero = zero;
+ class->calculate_rbr_resources = calculate_rbr_resources;
+ class->create_rbr = create_rbr;
+ class->revoke_rbr = revoke_rbr;
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ {
+ static xenidc_buffer_type type_index = 0;
+
+ class->type = ++type_index;
+ }
+
+ {
+ int i = (class->type % XENIDC_BUFFER_HASH_COUNT);
+
+ list_add_tail(&class->link,
+ &xenidc_buffer_concrete_hash[i]);
+ }
+
+ write_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+ }
+
+ return class->type;
+}
+
+static inline xenidc_buffer_concrete_class
+ *xenidc_local_buffer_reference_find_concrete_class(xenidc_buffer_type type)
+{
+ trace();
+
+ {
+ int i = type % XENIDC_BUFFER_HASH_COUNT;
+
+ xenidc_buffer_concrete_class *class;
+
+ unsigned long flags;
+
+ read_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ list_for_each_entry(class, &xenidc_buffer_concrete_hash[i],
+ link) {
+ if (class->type == type) {
+ read_unlock_irqrestore
+ (&xenidc_local_buffer_reference_lock,
+ flags);
+
+ return class;
+ }
+ }
+
+ read_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+
+ BUG();
+
+ return NULL;
+ }
+}
+
+void xenidc_local_buffer_reference_register_buffer_copy_class
+ (xenidc_buffer_copy_class * class,
+ xenidc_buffer_type target_type,
+ xenidc_buffer_type source_type, void (*copy)
+ (xenidc_buffer_copy_class * class,
+ xenidc_local_buffer_reference * target,
+ xenidc_local_buffer_reference * source,
+ xenidc_buffer_byte_count byte_count)
+ ) {
+ trace();
+
+ INIT_LIST_HEAD(&class->link);
+
+ class->target_type = target_type;
+ class->source_type = source_type;
+ class->copy = copy;
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ {
+ int i = ((class->target_type << 16 | class->source_type)
+ % XENIDC_BUFFER_HASH_COUNT);
+
+ list_add_tail(&class->link,
+ &xenidc_buffer_copy_hash[i]);
+ }
+
+ write_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+ }
+}
+
+static inline xenidc_buffer_copy_class
+ *xenidc_local_buffer_reference_find_copy_class(xenidc_buffer_type
+ target_type,
+ xenidc_buffer_type
+ source_type) {
+ trace();
+
+ {
+ int i =
+ ((target_type << 16 | source_type) %
+ XENIDC_BUFFER_HASH_COUNT);
+
+ xenidc_buffer_copy_class *class;
+
+ unsigned long flags;
+
+ read_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ list_for_each_entry(class, &xenidc_buffer_copy_hash[i], link) {
+ if ((class->target_type == target_type)
+ && (class->source_type == source_type)
+ ) {
+ read_unlock_irqrestore
+ (&xenidc_local_buffer_reference_lock,
+ flags);
+
+ return class;
+ }
+ }
+
+ read_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+
+ return NULL;
+ }
+}
+
+xenidc_buffer_type xenidc_local_buffer_reference_register_buffer_virtual_class
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference(*resolve)
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference * lbr), void (*advance)
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count)
+ ) {
+ trace();
+
+ xenidc_local_buffer_reference_init();
+
+ INIT_LIST_HEAD(&class->link);
+
+ class->resolve = resolve;
+ class->advance = advance;
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ {
+ static xenidc_buffer_type type_index = 0;
+
+ class->type =
+ (++type_index
+ |
+ XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL
+ | ((advance != NULL)
+ ?
+ XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL_ADVANCE
+ : 0)
+ );
+ }
+
+ {
+ int i = (class->type % XENIDC_BUFFER_HASH_COUNT);
+
+ list_add_tail(&class->link,
+ &xenidc_buffer_virtual_hash[i]);
+ }
+
+ write_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+ }
+
+ return class->type;
+}
+
+static inline xenidc_buffer_virtual_class
+ *xenidc_local_buffer_reference_find_virtual_class(xenidc_buffer_type type)
+{
+ trace();
+
+ {
+ int i = type % XENIDC_BUFFER_HASH_COUNT;
+
+ xenidc_buffer_virtual_class *class;
+
+ unsigned long flags;
+
+ read_lock_irqsave(&xenidc_local_buffer_reference_lock, flags);
+
+ list_for_each_entry(class, &xenidc_buffer_virtual_hash[i], link) {
+ if (class->type == type) {
+ read_unlock_irqrestore
+ (&xenidc_local_buffer_reference_lock,
+ flags);
+
+ return class;
+ }
+ }
+
+ read_unlock_irqrestore(&xenidc_local_buffer_reference_lock,
+ flags);
+
+ BUG();
+
+ return NULL;
+ }
+}
+
+xenidc_local_buffer_reference xenidc_local_buffer_reference_resolve
+ (xenidc_local_buffer_reference * lbr) {
+ trace();
+
+ {
+ xenidc_local_buffer_reference resolved_lbr = *lbr;
+
+ while (1) {
+ if ((resolved_lbr.type
+ & XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL)
+ == 0) {
+ return resolved_lbr;
+ } else {
+ xenidc_buffer_virtual_class *class =
+ xenidc_local_buffer_reference_find_virtual_class
+ (resolved_lbr.type);
+
+ resolved_lbr =
+ class->resolve(class, &resolved_lbr);
+ }
+ }
+ }
+}
+
+int xenidc_local_buffer_reference_calculate_rbr_resources
+ (xenidc_local_buffer_reference * lbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list) {
+ trace();
+
+ if (lbr->byte_count != 0) {
+ xenidc_buffer_concrete_class *class =
+ xenidc_local_buffer_reference_find_concrete_class(lbr->
+ type);
+
+ return class->calculate_rbr_resources(class, lbr, address,
+ list);
+ } else {
+ *list = xenidc_buffer_resource_list_null();
+
+ return 0;
+ }
+}
+
+xenidc_buffer_concrete_class **xenidc_local_buffer_reference_create_rbr
+ (xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ xenidc_remote_buffer_reference * rbr, int access_flags) {
+ trace();
+
+ if (lbr->byte_count != 0) {
+ xenidc_buffer_concrete_class *class =
+ xenidc_local_buffer_reference_find_concrete_class(lbr->
+ type);
+
+ return class->create_rbr
+ (class, lbr, address, provider, rbr, access_flags);
+ } else {
+ memset(rbr, 0, sizeof(*rbr));
+
+ return NULL;
+ }
+}
+
+void xenidc_local_buffer_reference_revoke_rbr
+ (xenidc_buffer_concrete_class ** context, xenidc_callback * callback) {
+ trace();
+
+ if (context != NULL) {
+ (*context)->revoke_rbr(context, callback);
+ } else {
+ xenidc_callback_success(callback);
+ }
+}
+
+xenidc_buffer_byte_count xenidc_local_buffer_reference_copy_in_or_out
+ (xenidc_local_buffer_reference * lbr,
+ void *buffer, xenidc_buffer_byte_count buffer_byte_count, int out) {
+ trace();
+
+ {
+ /* Total amount to copy is the smaller of the two buffers. */
+
+ xenidc_buffer_byte_count byte_count =
+ MIN(lbr->byte_count, buffer_byte_count);
+
+ xenidc_buffer_byte_count remainder_offset = 0;
+ xenidc_buffer_byte_count remainder_count = byte_count;
+
+ xenidc_local_buffer_reference top_lbr = *lbr;
+
+ while (remainder_count != 0) {
+ /* top_lbr might be virtual so we resolve it to get a concrete */
+ /* lbr for the first contiguous chunk of top_lbr. */
+
+ xenidc_local_buffer_reference resolved_lbr =
+ xenidc_local_buffer_reference_resolve(&top_lbr);
+
+ /* resolved_lbr is guaranteed to be concrete so we can look up */
+ /* its copy method. */
+
+ xenidc_buffer_concrete_class *class =
+ xenidc_local_buffer_reference_find_concrete_class
+ (resolved_lbr.type);
+
+ /* Amount to copy this go may be restricted by the size of the */
+ /* resolved lbr. */
+
+ xenidc_buffer_byte_count this_go =
+ MIN(resolved_lbr.byte_count, remainder_count);
+
+ class->copy_in_or_out
+ (class,
+ &resolved_lbr,
+ ((char *)buffer) + remainder_offset, this_go, out);
+
+ remainder_offset += this_go;
+ remainder_count -= this_go;
+
+ xenidc_local_buffer_reference_advance(&top_lbr,
+ this_go);
+ }
+
+ return byte_count;
+ }
+}
+
+void xenidc_local_buffer_reference_zero(xenidc_local_buffer_reference * lbr)
+{
+ trace();
+
+ {
+ xenidc_local_buffer_reference top_lbr = *lbr;
+
+ while (top_lbr.byte_count != 0) {
+ /* top_lbr might be virtual so we resolve it to get a concrete */
+ /* lbr for the first contiguous chunk of top_lbr. */
+
+ xenidc_local_buffer_reference resolved_lbr =
+ xenidc_local_buffer_reference_resolve(&top_lbr);
+
+ xenidc_buffer_concrete_class *class =
+ xenidc_local_buffer_reference_find_concrete_class
+ (resolved_lbr.type);
+
+ class->zero(class, &resolved_lbr);
+
+ xenidc_local_buffer_reference_advance
+ (&top_lbr, resolved_lbr.byte_count);
+ }
+ }
+}
+
+xenidc_buffer_byte_count xenidc_local_buffer_reference_copy
+ (xenidc_local_buffer_reference * target,
+ xenidc_local_buffer_reference * source) {
+ trace();
+
+ {
+ /* Total amount to copy is the smaller of the two buffers. */
+
+ xenidc_buffer_byte_count byte_count =
+ MIN(target->byte_count, source->byte_count);
+
+ xenidc_local_buffer_reference top_target_lbr = *target;
+ xenidc_local_buffer_reference top_source_lbr = *source;
+
+ xenidc_buffer_byte_count remainder_count = byte_count;
+
+ while (remainder_count != 0) {
+ xenidc_local_buffer_reference resolved_target_lbr =
+ xenidc_local_buffer_reference_resolve
+ (&top_target_lbr);
+
+ xenidc_local_buffer_reference resolved_source_lbr =
+ xenidc_local_buffer_reference_resolve
+ (&top_source_lbr);
+
+ xenidc_buffer_byte_count this_go = MIN
+ (resolved_target_lbr.byte_count,
+ resolved_source_lbr.byte_count);
+
+ xenidc_buffer_copy_class *copy_class =
+ xenidc_local_buffer_reference_find_copy_class
+ (resolved_target_lbr.type,
+ resolved_source_lbr.type);
+
+ if (copy_class != NULL) {
+ copy_class->copy
+ (copy_class,
+ &resolved_target_lbr,
+ &resolved_source_lbr, this_go);
+ } else {
+ u8 buffer[64];
+
+ xenidc_buffer_concrete_class
+ *target_concrete_class =
+ xenidc_local_buffer_reference_find_concrete_class
+ (resolved_target_lbr.type);
+
+ xenidc_buffer_concrete_class
+ *source_concrete_class =
+ xenidc_local_buffer_reference_find_concrete_class
+ (resolved_source_lbr.type);
+
+ xenidc_local_buffer_reference temp_target =
+ resolved_target_lbr;
+ xenidc_local_buffer_reference temp_source =
+ resolved_source_lbr;
+
+ xenidc_buffer_byte_count nested_remainder_count
+ = this_go;
+
+ do {
+ xenidc_buffer_byte_count nested_this_go
+ = MIN(64, nested_remainder_count);
+
+ source_concrete_class->copy_in_or_out
+ (source_concrete_class,
+ &temp_source,
+ buffer, nested_this_go, 1);
+
+ target_concrete_class->copy_in_or_out
+ (target_concrete_class,
+ &temp_target,
+ buffer, nested_this_go, 0);
+
+ xenidc_local_buffer_reference_advance
+ (&temp_target, nested_this_go);
+
+ xenidc_local_buffer_reference_advance
+ (&temp_source, nested_this_go);
+
+ nested_remainder_count -=
+ nested_this_go;
+ }
+ while (nested_remainder_count != 0);
+ }
+
+ xenidc_local_buffer_reference_advance(&top_target_lbr,
+ this_go);
+ xenidc_local_buffer_reference_advance(&top_source_lbr,
+ this_go);
+
+ remainder_count -= this_go;
+ }
+
+ return byte_count;
+ }
+}
+
+xenidc_buffer_byte_count xenidc_local_buffer_reference_virtual_advance
+ (xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count) {
+ trace();
+
+ {
+ xenidc_buffer_byte_count actual_byte_count =
+ MIN(lbr->byte_count, byte_count);
+
+ xenidc_buffer_virtual_class *class =
+ xenidc_local_buffer_reference_find_virtual_class(lbr->type);
+
+ class->advance(class, lbr, actual_byte_count);
+
+ return actual_byte_count;
+ }
+}
+
+EXPORT_SYMBOL(xenidc_local_buffer_reference_register_buffer_concrete_class);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_register_buffer_copy_class);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_register_buffer_virtual_class);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_copy_in_or_out);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_zero);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_copy);
+EXPORT_SYMBOL(xenidc_local_buffer_reference_virtual_advance);
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_remote_buffer_reference.c
--- /dev/null Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_remote_buffer_reference.c Sun Nov 20 14:54:21 2005
@@ -0,0 +1,191 @@
+/*****************************************************************************/
+/* Xen inter-domain communication remote buffer references */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_remote_buffer_reference.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "xenidc_trace.h"
+
+#define XENIDC_BUFFER_HASH_COUNT 255
+
+static DEFINE_RWLOCK(xenidc_remote_buffer_reference_lock);
+
+static struct list_head xenidc_buffer_mappable_hash[XENIDC_BUFFER_HASH_COUNT];
+
+static void xenidc_remote_buffer_reference_init(void)
+{
+ trace();
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_remote_buffer_reference_lock, flags);
+
+ {
+ static int initialised = 0;
+
+ if (!initialised) {
+ int i;
+
+ for (i = 0; i < XENIDC_BUFFER_HASH_COUNT; i++) {
+ INIT_LIST_HEAD
+ (&xenidc_buffer_mappable_hash[i]);
+ }
+
+ initialised = 1;
+ }
+ }
+
+ write_unlock_irqrestore(&xenidc_remote_buffer_reference_lock,
+ flags);
+ }
+}
+
+void xenidc_remote_buffer_reference_register_buffer_mappable_class
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference_type type, int (*calculate_map_resources)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_list * list),
+ xenidc_buffer_mappable_class ** (*map_rbr)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ void **mapping,
+ int access_flags),
+ void (*unmap_rbr) (xenidc_buffer_mappable_class ** context)
+ ) {
+ trace();
+
+ xenidc_remote_buffer_reference_init();
+
+ INIT_LIST_HEAD(&class->link);
+
+ class->type = type;
+
+ class->calculate_map_resources = calculate_map_resources;
+ class->map_rbr = map_rbr;
+ class->unmap_rbr = unmap_rbr;
+
+ {
+ unsigned long flags;
+
+ write_lock_irqsave(&xenidc_remote_buffer_reference_lock, flags);
+
+ {
+ int i = (class->type % XENIDC_BUFFER_HASH_COUNT);
+
+ list_add_tail(&class->link,
+ &xenidc_buffer_mappable_hash[i]);
+ }
+
+ write_unlock_irqrestore(&xenidc_remote_buffer_reference_lock,
+ flags);
+ }
+}
+
+static inline xenidc_buffer_mappable_class
+ *xenidc_remote_buffer_reference_find_mappable_class
+ (xenidc_remote_buffer_reference_type type) {
+ trace();
+
+ {
+ int i = type % XENIDC_BUFFER_HASH_COUNT;
+
+ xenidc_buffer_mappable_class *class;
+
+ unsigned long flags;
+
+ read_lock_irqsave(&xenidc_remote_buffer_reference_lock, flags);
+
+ list_for_each_entry(class, &xenidc_buffer_mappable_hash[i],
+ link) {
+ if (class->type == type) {
+ read_unlock_irqrestore
+ (&xenidc_remote_buffer_reference_lock,
+ flags);
+
+ return class;
+ }
+ }
+
+ read_unlock_irqrestore(&xenidc_remote_buffer_reference_lock,
+ flags);
+
+ return NULL;
+ }
+}
+
+int xenidc_remote_buffer_reference_calculate_map_resources
+ (xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list) {
+ trace();
+
+ if (rbr->byte_count != 0) {
+ xenidc_buffer_mappable_class *class =
+ xenidc_remote_buffer_reference_find_mappable_class(rbr->
+ type);
+
+ if (class != NULL) {
+ return class->calculate_map_resources(class, rbr,
+ address, list);
+ } else {
+ return 1;
+ }
+ } else {
+ *list = xenidc_buffer_resource_list_null();
+
+ return 0;
+ }
+}
+
+xenidc_buffer_mappable_class **xenidc_remote_buffer_reference_map_rbr
+ (xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ void **mapping, int access_flags) {
+ trace();
+
+ if (rbr->byte_count != 0) {
+ xenidc_buffer_mappable_class *class =
+ xenidc_remote_buffer_reference_find_mappable_class(rbr->
+ type);
+
+ return class->map_rbr
+ (class, rbr, address, provider, mapping, access_flags);
+ } else {
+ *mapping = NULL;
+
+ return (xenidc_buffer_mappable_class **) 1; /* FIXME: use PTR_ERR?? */
+ }
+}
+
+void xenidc_remote_buffer_reference_unmap_rbr
+ (xenidc_buffer_mappable_class ** context) {
+ trace();
+
+ if (context != (xenidc_buffer_mappable_class **) 1) {
+ (*context)->unmap_rbr(context);
+ }
+}
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/include/asm-xen/xenidc_address.h
--- /dev/null Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_address.h Sun Nov 20 14:54:21 2005
@@ -0,0 +1,61 @@
+/*****************************************************************************/
+/* Xen inter-domain communication address. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+/* */
+/* The xenidc_address type represents an address on the */
+/* interdomain-communication bus. This is useful as an opaque type to pass */
+/* through any layers of code that don't need to be coupled to the */
+/* underlying implementation details of the IDC code. */
+
+#ifndef __ASM_XEN_XENIDC_ADDRESS_H__
+#define __ASM_XEN_XENIDC_ADDRESS_H__
+
+typedef struct xenidc_address_struct xenidc_address;
+
+struct xenidc_address_struct {
+ const char *local;
+ const char *remote;
+ int remote_id;
+};
+
+static inline void xenidc_address_init
+ (xenidc_address * address,
+ const char *local, const char *remote, int remote_id) {
+ address->local = local;
+ address->remote = remote;
+ address->remote_id = remote_id;
+}
+
+static inline const char *xenidc_address_query_local_domain
+ (xenidc_address * address) {
+ return address->local;
+}
+
+static inline const char *xenidc_address_query_remote_domain
+ (xenidc_address * address) {
+ return address->remote;
+}
+
+static inline int xenidc_address_query_remote_domain_id
+ (xenidc_address * address) {
+ return address->remote_id;
+}
+
+#endif
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/include/asm-xen/xenidc_local_buffer_reference.h
--- /dev/null Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_local_buffer_reference.h Sun Nov 20 14:54:21 2005
@@ -0,0 +1,379 @@
+/*****************************************************************************/
+/* Xen inter-domain communication local buffer reference object. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+/* */
+/* Local buffer references are an abstraction for pointers to memory which */
+/* are useful for the following reasons: */
+/* */
+/* They allow clients to describe what type of memory they are passing to a */
+/* service which makes it possible to implement services which deal with */
+/* whatever memory the client happens to have rather than forcing the client */
+/* to implement memory management code to convert to the form required by */
+/* the service. This makes it possible to move memory management code out */
+/* of clients and out of services and into a single core memory management */
+/* implementation. This is good for code quality and maintainability. */
+/* */
+/* They also bundle together the buffer pointer, any start offset (for */
+/* example into a page table) and the buffer length into one convenient */
+/* structure and provide functions for performing all the necessary buffer */
+/* manipulation arithmetic operations. This is convenient for clients and */
+/* good for code quality because the buffer manipulations are easy to use */
+/* and make it less likely for arithmetic errors to lead to buffer overflows.*/
+/* */
+/* They are also useful for implementing logical buffer operations like */
+/* concatenation of buffers and viewing a buffer as a wrapping buffer. */
+/* Again, this is a convenient mechanism which is easier to review and less */
+/* error prone than explicit arithmetic. */
+/* */
+/* This interface provides the basic functions and mechanisms for installing */
+/* different types of local buffer references for referencing different */
+/* kinds of memory, referencing memory in different ways an copying between */
+/* different kinds of memory. */
+/* */
+/* There are three kinds of registration: */
+/* */
+/* A concrete class is used to register a type of memory. For example */
+/* "kernel virtual address space" would be one kind of memory. Another kind */
+/* might for example be shared page cache memory not mapped into the kernel */
+/* virtual address space but for which synchronous access was possible using */
+/* some hypervisor calls. */
+/* */
+/* A virtual class is used to register a way of viewing other local buffers. */
+/* For example, concatenation is a way of looking at two buffers and */
+/* wrapping is a way of looking at a single buffer. */
+/* */
+/* A copy class is used to implement a fast-path mechanism for copying */
+/* between two potentially different types of concrete classes. */
+/* There is an inefficient default mechanism as a fallback but any kinds of */
+/* copying for which performance is a concern should have a bespoke copy */
+/* class. */
+
+#ifndef __ASM_XEN_XENIDC_LOCAL_BUFFER_REFERENCE_H__
+#define __ASM_XEN_XENIDC_LOCAL_BUFFER_REFERENCE_H__
+
+#include "xenidc_buffer_resource_provider.h"
+#include "xenidc_remote_buffer_reference.h"
+#include "xenidc_address.h"
+#include "xenidc_callback.h"
+
+/* These flags are private to the implementation but exposed for use in */
+/* inline functions below. */
+
+#define XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL 0x80000000
+#define XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL_ADVANCE 0x40000000
+
+/* When used, these flags specify what kind of access is _allowed_. */
+
+#define XENIDC_LOCAL_BUFFER_REFERENCE_ACCESS_FLAGS_READ 1
+#define XENIDC_LOCAL_BUFFER_REFERENCE_ACCESS_FLAGS_WRITE 2
+
+typedef u32 xenidc_buffer_type;
+
+/* A local buffer reference consists of a type, a type-specific base, a */
+/* byte_offset into the buffer referenced by the base and a byte_count of */
+/* the size of the buffer starting at the byte_offset. */
+/* */
+/* It's OK to copy xenidc_local_buffer_reference structs and pass them */
+/* around. They are just a convenient way of bundling what would otherwise */
+/* be four parameters. */
+
+typedef struct xenidc_local_buffer_reference_struct
+ xenidc_local_buffer_reference;
+
+struct xenidc_local_buffer_reference_struct {
+ xenidc_buffer_type type;
+ void *base;
+ xenidc_buffer_byte_count byte_offset;
+ xenidc_buffer_byte_count byte_count;
+};
+
+static inline xenidc_buffer_byte_count
+ xenidc_local_buffer_reference_query_byte_offset
+ (xenidc_local_buffer_reference * lbr) {
+ return lbr->byte_offset;
+}
+
+static inline xenidc_buffer_byte_count
+ xenidc_local_buffer_reference_query_byte_count
+ (xenidc_local_buffer_reference * lbr) {
+ return lbr->byte_count;
+}
+
+/* Concrete class for registering a new type of memory. */
+
+typedef struct xenidc_buffer_concrete_class_struct
+ xenidc_buffer_concrete_class;
+
+struct xenidc_buffer_concrete_class_struct {
+ struct list_head link;
+ xenidc_buffer_type type;
+ void (*copy_in_or_out)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ void *buffer, xenidc_buffer_byte_count byte_count, int out);
+ void (*zero)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr);
+ int (*calculate_rbr_resources)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list);
+ xenidc_buffer_concrete_class **(*create_rbr)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ xenidc_remote_buffer_reference * rbr, int access_flags);
+ void (*revoke_rbr)
+ (xenidc_buffer_concrete_class ** context, xenidc_callback * callback);
+};
+
+/* xenidc_local_buffer_reference_register_buffer_concrete_class returns a */
+/* xenidc_buffer_type which the type implementation must use when creating */
+/* local buffer references for its clients. */
+/* */
+/* The type implementation provides a few methods: */
+/* */
+/* copy_in_or_out is used for copying into the LBR from the kernel virtual */
+/* address space or vice-versa and is used in the fallback mechanism for */
+/* copying between different lbr types by staging the data. */
+/* */
+/* zero is optional and implements a fast zero of the buffer passed in. The */
+/* inefficient default zero operation stages zero bytes into the buffer */
+/* using copy_in_or_out. */
+/* */
+/* The type implementation is required to provide a method to generate a */
+/* remote buffer reference for remote access to the buffer. There is */
+/* currently no default for this though one could be implemented. The */
+/* calculate_rbr_resources function returns a list of resources that would */
+/* be required to create a rbr for the lbr. */
+/* */
+/* create_rbr creates an rbr for the lbr. */
+/* */
+/* revoke_rbr revokes a created rbr. */
+
+extern xenidc_buffer_type
+ xenidc_local_buffer_reference_register_buffer_concrete_class
+ (xenidc_buffer_concrete_class * class, void (*copy_in_or_out)
+ (xenidc_buffer_concrete_class * class, xenidc_local_buffer_reference * lbr, void *buffer, xenidc_buffer_byte_count byte_count, int out), void (*zero) /* NULL for the inefficient default */
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr), int (*calculate_rbr_resources)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_list * list),
+ xenidc_buffer_concrete_class ** (*create_rbr)
+ (xenidc_buffer_concrete_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ xenidc_remote_buffer_reference * rbr,
+ int access_flags), void (*revoke_rbr)
+ (xenidc_buffer_concrete_class ** context, xenidc_callback * callback)
+ );
+
+/* Concrete class for registering a fast-path copy function. */
+
+typedef struct xenidc_buffer_copy_class_struct xenidc_buffer_copy_class;
+
+struct xenidc_buffer_copy_class_struct {
+ struct list_head link;
+ xenidc_buffer_type target_type;
+ xenidc_buffer_type source_type;
+ void (*copy)
+ (xenidc_buffer_copy_class * class,
+ xenidc_local_buffer_reference * target,
+ xenidc_local_buffer_reference * source,
+ xenidc_buffer_byte_count byte_count);
+};
+
+/* xenidc_local_buffer_reference_register_buffer_copy_class is used to */
+/* register a function for performing an efficient copy between two types of */
+/* local buffer references. */
+
+extern void xenidc_local_buffer_reference_register_buffer_copy_class
+ (xenidc_buffer_copy_class * class,
+ xenidc_buffer_type target_type,
+ xenidc_buffer_type source_type, void (*copy)
+ (xenidc_buffer_copy_class * class,
+ xenidc_local_buffer_reference * target,
+ xenidc_local_buffer_reference * source,
+ xenidc_buffer_byte_count byte_count)
+ );
+
+/* Virtual class for registering a way of viewing local buffers. */
+
+typedef struct xenidc_buffer_virtual_class_struct xenidc_buffer_virtual_class;
+
+struct xenidc_buffer_virtual_class_struct {
+ struct list_head link;
+ xenidc_buffer_type type;
+ xenidc_local_buffer_reference(*resolve)
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference * lbr);
+ void (*advance)
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference * lbr,
+ xenidc_buffer_byte_count byte_count);
+};
+
+/* xenidc_local_buffer_reference_register_buffer_virtual_class is used to */
+/* register a virtual class for a new way of viewing local buffers. */
+/* The type implementation provides a resolve function which takes its type */
+/* of local buffer reference and returns a local buffer reference for an */
+/* underlying buffer type which is the maximal contiguous chunk at the front */
+/* of the reference passed as a parameter. This is generally sufficient to */
+/* implement all the buffer operations. The wrapping type also needs to */
+/* provide a virtual advance function for wrapping the buffer offset. */
+
+extern xenidc_buffer_type
+ xenidc_local_buffer_reference_register_buffer_virtual_class
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference(*resolve)
+ (xenidc_buffer_virtual_class * class, xenidc_local_buffer_reference * lbr), void (*advance) /* NULL for the efficient default */
+ (xenidc_buffer_virtual_class * class,
+ xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count)
+ );
+
+/* Resolve returns a concrete lbr referencing a contiguous chunk at the head */
+/* of the lbr passed as a parameter. This is used by the implementation of */
+/* the bulk data transfer service. */
+
+extern xenidc_local_buffer_reference xenidc_local_buffer_reference_resolve
+ (xenidc_local_buffer_reference * lbr);
+
+/* Calculate RBR resources calculates the resources required to create an */
+/* RBR for the LBR. */
+/* This is used by the implementation of the bulk data transfer service. */
+
+extern int xenidc_local_buffer_reference_calculate_rbr_resources
+ (xenidc_local_buffer_reference * lbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list);
+
+/* Create RBR creates a RBR for the LBR by calling the appropriate type */
+/* specific implementation. This is called by the implementation of the */
+/* bulk data transfer services. */
+
+extern xenidc_buffer_concrete_class **xenidc_local_buffer_reference_create_rbr
+ (xenidc_local_buffer_reference * lbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ xenidc_remote_buffer_reference * rbr, int access_flags);
+
+/* Revoke RBR revokes a created RBR by calling the appropriate type specific */
+/* implementation. This is called by the implementation of the bulk data */
+/* transfer services. */
+
+extern void xenidc_local_buffer_reference_revoke_rbr
+ (xenidc_buffer_concrete_class ** context, xenidc_callback * callback);
+
+/* Copy between an lbr and a buffer. Returns the number of bytes copied */
+/* which is the minimum of the source and target byte_counts. */
+
+extern xenidc_buffer_byte_count xenidc_local_buffer_reference_copy_in_or_out
+ (xenidc_local_buffer_reference * lbr,
+ void *buffer, xenidc_buffer_byte_count buffer_byte_count, int out);
+
+static inline xenidc_buffer_byte_count xenidc_local_buffer_reference_copy_out
+ (xenidc_local_buffer_reference * lbr,
+ void *target, xenidc_buffer_byte_count target_byte_count) {
+ return xenidc_local_buffer_reference_copy_in_or_out
+ (lbr, target, target_byte_count, 1);
+}
+
+static inline xenidc_buffer_byte_count xenidc_local_buffer_reference_copy_in
+ (xenidc_local_buffer_reference * lbr,
+ void *source, xenidc_buffer_byte_count source_byte_count) {
+ return xenidc_local_buffer_reference_copy_in_or_out
+ (lbr, source, source_byte_count, 0);
+}
+
+/* Zero a local buffer. */
+
+extern void xenidc_local_buffer_reference_zero
+ (xenidc_local_buffer_reference * lbr);
+
+/* Copy between two local buffers. */
+
+extern xenidc_buffer_byte_count xenidc_local_buffer_reference_copy
+ (xenidc_local_buffer_reference * target,
+ xenidc_local_buffer_reference * source);
+
+/* xenidc_local_buffer_reference_virtual_advance is only exposed for the */
+/* inline function below. Do not call it directly. */
+
+extern xenidc_buffer_byte_count xenidc_local_buffer_reference_virtual_advance
+ (xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count);
+
+/* Advance increments the offset and decrements the length by the amount */
+/* specified which is useful to advance the reference after having copied a */
+/* chunk of data into the start of the buffer. */
+/* Advance returns the remaining length. */
+
+static inline xenidc_buffer_byte_count xenidc_local_buffer_reference_advance
+ (xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count) {
+ if ((lbr->
+ type & XENIDC_LOCAL_BUFFER_REFERENCE_TYPE_FLAG_VIRTUAL_ADVANCE)
+ == 0) {
+ if (lbr->byte_count > byte_count) {
+ lbr->byte_offset += byte_count;
+ lbr->byte_count -= byte_count;
+ } else {
+ lbr->byte_offset += lbr->byte_count;
+ lbr->byte_count = 0;
+ }
+
+ return lbr->byte_count;
+ } else {
+ return
+ xenidc_local_buffer_reference_virtual_advance(lbr,
+ byte_count);
+ }
+}
+
+/* Truncate reduces the length of the buffer which results in a reference to */
+/* the first byte_count bytes of the buffer (or the whole buffer, whichever */
+/* is less). */
+/* Truncate returns the resulting length of the buffer. */
+
+static inline xenidc_buffer_byte_count xenidc_local_buffer_reference_truncate
+ (xenidc_local_buffer_reference * lbr, xenidc_buffer_byte_count byte_count) {
+ if (lbr->byte_count > byte_count) {
+ lbr->byte_count = byte_count;
+ }
+
+ return lbr->byte_count;
+}
+
+/* Subrange reduces the range of the buffer by advancing the start */
+/* byte_offset bytes and reducing the length to the minimum of byte_count */
+/* and the remaining length. Subrange returns the resulting length of the */
+/* buffer. */
+
+static inline xenidc_buffer_byte_count xenidc_local_buffer_reference_subrange
+ (xenidc_local_buffer_reference * lbr,
+ xenidc_buffer_byte_count byte_offset,
+ xenidc_buffer_byte_count byte_count) {
+ (void)xenidc_local_buffer_reference_advance(lbr, byte_offset);
+
+ return xenidc_local_buffer_reference_truncate(lbr, byte_count);
+}
+
+#endif
diff -r 1e2c0ff9c46a -r 2055d5e00d68 linux-2.6-xen-sparse/include/asm-xen/xenidc_remote_buffer_reference.h
--- /dev/null Sun Nov 20 14:53:55 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_remote_buffer_reference.h Sun Nov 20 14:54:21 2005
@@ -0,0 +1,164 @@
+/*****************************************************************************/
+/* Xen inter-domain communication remote buffer references. */
+/* */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2 of the License, or (at your */
+/* option) any later version. */
+/* */
+/* 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/*****************************************************************************/
+/* */
+/* A xenidc_remote_buffer_reference object is sent on the wire between */
+/* two domains to allow the receiving domain to access a buffer belonging to */
+/* the sending domain. */
+/* */
+/* In general, there may be a number of different kinds of buffers and ways */
+/* of describing them. This interface provides a default 'NULL' */
+/* implementation of remote buffer references (for zero length buffers) and */
+/* a mechanism for installing new types of remote buffer reference for other */
+/* kinds of buffers or buffers described in different ways. */
+
+#ifndef __ASM_XEN_XENIDC_REMOTE_BUFFER_REFERENCE_H__
+#define __ASM_XEN_XENIDC_REMOTE_BUFFER_REFERENCE_H__
+
+#include <asm/types.h>
+#include <asm-xen/xenidc_buffer_resource_provider.h>
+#include <linux/list.h>
+#include "xenidc_address.h"
+
+typedef u32 xenidc_remote_buffer_reference_type;
+
+#define XENIDC_REMOTE_BUFFER_REFERENCE_TYPE_NULL 0
+
+#define XENIDC_REMOTE_BUFFER_REFERENCE_ACCESS_FLAGS_READ 1
+#define XENIDC_REMOTE_BUFFER_REFERENCE_ACCESS_FLAGS_WRITE 2
+
+/* The different types of remote buffer reference must all use the same */
+/* xenidc_remote_buffer_reference structure which provides 32 bytes of space */
+/* for type-specific use. */
+
+#define XENIDC_REMOTE_BUFFER_REFERENCE_BASE_BYTE_COUNT 32
+
+typedef u32 xenidc_buffer_byte_count;
+
+typedef struct xenidc_remote_buffer_reference_struct
+ xenidc_remote_buffer_reference;
+
+struct xenidc_remote_buffer_reference_struct {
+ xenidc_remote_buffer_reference_type type;
+ u32 reserved;
+ struct {
+ u64 base_space
+ [ XENIDC_REMOTE_BUFFER_REFERENCE_BASE_BYTE_COUNT / 8 ];
+ } base;
+ xenidc_buffer_byte_count byte_offset;
+ xenidc_buffer_byte_count byte_count;
+};
+
+/* xenidc_remote_buffer_reference_query_byte_count returns the size of the */
+/* buffer in bytes. */
+
+static inline xenidc_buffer_byte_count
+ xenidc_remote_buffer_reference_query_byte_count
+ (xenidc_remote_buffer_reference * rbr) {
+ return rbr->byte_count;
+}
+
+/* If a client might attempt to map a remote buffer reference into the local */
+/* address space (determined by design) then the remote buffer reference */
+/* type implementation must register the methods required to perform the */
+/* mapping. */
+
+/* The type implementation must provide a xenidc_buffer_mappable_class. */
+
+typedef struct xenidc_buffer_mappable_class_struct
+ xenidc_buffer_mappable_class;
+
+struct xenidc_buffer_mappable_class_struct {
+ struct list_head link;
+ xenidc_remote_buffer_reference_type type;
+ int (*calculate_map_resources)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list);
+ xenidc_buffer_mappable_class **(*map_rbr)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ void **mapping, int access_flags);
+ void (*unmap_rbr) (xenidc_buffer_mappable_class ** context);
+};
+
+/* The type implementation calls the register function with its class */
+/* structure, type, calculate_map_resources, map and unmap functions. */
+
+extern void xenidc_remote_buffer_reference_register_buffer_mappable_class
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference_type type, int (*calculate_map_resources)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_list * list),
+ xenidc_buffer_mappable_class ** (*map_rbr)
+ (xenidc_buffer_mappable_class * class,
+ xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ void **mapping,
+ int access_flags),
+ void (*unmap_rbr) (xenidc_buffer_mappable_class ** context)
+ );
+
+/* xenidc_remote_buffer_reference_calculate_map_resources is called to */
+/* calculate what buffer resources would be required to map the rbr into the */
+/* local address space. This is called by the generic code that does mapping */
+/* on behalf of clients and resolves to the type specific implementation. */
+
+extern int xenidc_remote_buffer_reference_calculate_map_resources
+ (xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address, xenidc_buffer_resource_list * list);
+
+/* xenidc_remote_buffer_reference_map_rbr is called to map a rbr into the */
+/* local address space. This is called by the generic code that does */
+/* mapping on behalf of the clients and resolves to the type specific */
+/* implementation. */
+/* */
+/* FIXME: This is a synchronous call. A network transparent RBR */
+/* implementation may need to stage the data into a buffer during this call */
+/* so would require this to be an asynchronous call with a callback. Since */
+/* the damage here is contained within the generic code and won't impact the */
+/* drivers we can add this feature later if required. */
+
+extern xenidc_buffer_mappable_class **xenidc_remote_buffer_reference_map_rbr
+ (xenidc_remote_buffer_reference * rbr,
+ xenidc_address * address,
+ xenidc_buffer_resource_provider * provider,
+ void **mapping, int access_flags);
+
+/* xenidc_remote_buffer_reference_unmap_rbr is called to unmap a rbr from */
+/* the local address space. This is called by the generic code that does */
+/* unmapping on behalf of the clients and resolves to the type specific */
+/* implementation. */
+/* */
+/* FIXME: This is a synchronous call. A network transparent RBR */
+/* implementation may need to stage the data from a buffer during this call */
+/* so would require this to be an asynchronous call with a callback. Since */
+/* the damage here is contained within the generic code and won't impact the */
+/* drivers we can add this feature later if required. */
+
+extern void xenidc_remote_buffer_reference_unmap_rbr
+ (xenidc_buffer_mappable_class ** context);
+
+#endif
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH][3/17] USB virt 2.6 split driver---xenidc buffer references
2005-11-21 13:18 [PATCH][3/17] USB virt 2.6 split driver---xenidc buffer references harry
@ 2005-11-21 20:31 ` Muli Ben-Yehuda
2005-11-21 21:34 ` Harry Butterworth
0 siblings, 1 reply; 3+ messages in thread
From: Muli Ben-Yehuda @ 2005-11-21 20:31 UTC (permalink / raw)
To: harry; +Cc: xen-devel
On Mon, Nov 21, 2005 at 01:18:48PM +0000, harry wrote:
> +#ifdef MIN
> +#undef MIN
> +#endif
> +
> +#define MIN( X, Y ) ( ( (X) < (Y) ) ? (X) : (Y) )
Linux has a much better definition.
> + memset(buffer, 0, 64);
s/64/sizeof(buffer)/? (there are arguments either way)
> +xenidc_buffer_type xenidc_local_buffer_reference_register_buffer_concrete_class
> + (xenidc_buffer_concrete_class * class, void (*copy_in_or_out)
> + (xenidc_buffer_concrete_class * class,
> + xenidc_local_buffer_reference * lbr,
> + void *buffer, xenidc_buffer_byte_count byte_count, int out), void (*zero)
> + (xenidc_buffer_concrete_class * class,
> + xenidc_local_buffer_reference * lbr), int (*calculate_rbr_resources)
> + (xenidc_buffer_concrete_class * class,
> + xenidc_local_buffer_reference * lbr,
> + xenidc_address * address,
> + xenidc_buffer_resource_list * list),
> + xenidc_buffer_concrete_class ** (*create_rbr)
> + (xenidc_buffer_concrete_class * class,
> + xenidc_local_buffer_reference * lbr,
> + xenidc_address * address,
> + xenidc_buffer_resource_provider * provider,
> + xenidc_remote_buffer_reference * rbr,
> + int access_flags), void (*revoke_rbr)
> + (xenidc_buffer_concrete_class ** context, xenidc_callback * callback)
> + ) {
I guess this is one case where typedefs would improve the code ;-)
> + if (zero == NULL) {
> + zero = xenidc_local_buffer_reference_default_zero;
> + }
no braces please
Cheers,
Muli
--
Muli Ben-Yehuda
http://www.mulix.org | http://mulix.livejournal.com/
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH][3/17] USB virt 2.6 split driver---xenidc buffer references
2005-11-21 20:31 ` Muli Ben-Yehuda
@ 2005-11-21 21:34 ` Harry Butterworth
0 siblings, 0 replies; 3+ messages in thread
From: Harry Butterworth @ 2005-11-21 21:34 UTC (permalink / raw)
To: Muli Ben-Yehuda; +Cc: xen-devel
On Mon, 2005-11-21 at 22:31 +0200, Muli Ben-Yehuda wrote:
> On Mon, Nov 21, 2005 at 01:18:48PM +0000, harry wrote:
>
> > +#ifdef MIN
> > +#undef MIN
> > +#endif
> > +
> > +#define MIN( X, Y ) ( ( (X) < (Y) ) ? (X) : (Y) )
>
> Linux has a much better definition.
So it does. Didn't manage to find it last time.
>
> > + memset(buffer, 0, 64);
>
> s/64/sizeof(buffer)/? (there are arguments either way)
>
> > +xenidc_buffer_type xenidc_local_buffer_reference_register_buffer_concrete_class
> > + (xenidc_buffer_concrete_class * class, void (*copy_in_or_out)
> > + (xenidc_buffer_concrete_class * class,
> > + xenidc_local_buffer_reference * lbr,
> > + void *buffer, xenidc_buffer_byte_count byte_count, int out), void (*zero)
> > + (xenidc_buffer_concrete_class * class,
> > + xenidc_local_buffer_reference * lbr), int (*calculate_rbr_resources)
> > + (xenidc_buffer_concrete_class * class,
> > + xenidc_local_buffer_reference * lbr,
> > + xenidc_address * address,
> > + xenidc_buffer_resource_list * list),
> > + xenidc_buffer_concrete_class ** (*create_rbr)
> > + (xenidc_buffer_concrete_class * class,
> > + xenidc_local_buffer_reference * lbr,
> > + xenidc_address * address,
> > + xenidc_buffer_resource_provider * provider,
> > + xenidc_remote_buffer_reference * rbr,
> > + int access_flags), void (*revoke_rbr)
> > + (xenidc_buffer_concrete_class ** context, xenidc_callback * callback)
> > + ) {
>
> I guess this is one case where typedefs would improve the code ;-)
This looked much neater before Lindent got hold of it.
>
> > + if (zero == NULL) {
> > + zero = xenidc_local_buffer_reference_default_zero;
> > + }
>
> no braces please
OK
>
> Cheers,
> Muli
--
Harry Butterworth <harry@hebutterworth.freeserve.co.uk>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-11-21 21:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-21 13:18 [PATCH][3/17] USB virt 2.6 split driver---xenidc buffer references harry
2005-11-21 20:31 ` Muli Ben-Yehuda
2005-11-21 21:34 ` Harry Butterworth
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.