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 +#include +#include +#include +#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 +#include +#include +#include +#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 +#include +#include +#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