On Thu, 2013-02-21 at 17:48 +0000, David Vrabel wrote:> From: David Vrabel <david.vrabel@citrix.com>
>
> Hypercall buffer arrays are used when a hypercall takes a variable
> length array of buffers.
This looks good to me, I took a quick peek at the 4/4 patch in the kexec
tools series which uses it as well.
Acked-by: Ian Campbell <ian.campbell@citrix.com>
>
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> ---
> tools/libxc/xc_hcall_buf.c | 73
++++++++++++++++++++++++++++++++++++++++++++
> tools/libxc/xenctrl.h | 27 ++++++++++++++++
> 2 files changed, 100 insertions(+), 0 deletions(-)
>
> diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
> index ced9abd..3e01f3f 100644
> --- a/tools/libxc/xc_hcall_buf.c
> +++ b/tools/libxc/xc_hcall_buf.c
> @@ -228,6 +228,79 @@ void xc__hypercall_bounce_post(xc_interface *xch,
xc_hypercall_buffer_t *b)
> xc__hypercall_buffer_free(xch, b);
> }
>
> +struct xc_hypercall_buffer_array {
> + unsigned max_bufs;
> + xc_hypercall_buffer_t *bufs;
> +};
> +
> +xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface
*xch,
> + unsigned n)
> +{
> + xc_hypercall_buffer_array_t *array;
> + xc_hypercall_buffer_t *bufs = NULL;
> +
> + array = malloc(sizeof(*array));
> + if ( array == NULL )
> + goto error;
> +
> + bufs = calloc(n, sizeof(*bufs));
> + if ( bufs == NULL )
> + goto error;
> +
> + array->max_bufs = n;
> + array->bufs = bufs;
> +
> + return array;
> +
> +error:
> + free(bufs);
> + free(array);
> + return NULL;
> +}
> +
> +void *xc__hypercall_buffer_array_alloc(xc_interface *xch,
> + xc_hypercall_buffer_array_t *array,
> + unsigned index,
> + xc_hypercall_buffer_t *hbuf,
> + size_t size)
> +{
> + void *buf;
> +
> + if ( index >= array->max_bufs || array->bufs[index].hbuf )
> + abort();
> +
> + buf = xc__hypercall_buffer_alloc(xch, hbuf, size);
> + if ( buf )
> + array->bufs[index] = *hbuf;
> + return buf;
> +}
> +
> +void *xc__hypercall_buffer_array_get(xc_interface *xch,
> + xc_hypercall_buffer_array_t *array,
> + unsigned index,
> + xc_hypercall_buffer_t *hbuf)
> +{
> + if ( index >= array->max_bufs || array->bufs[index].hbuf ==
NULL )
> + abort();
> +
> + *hbuf = array->bufs[index];
> + return array->bufs[index].hbuf;
> +}
> +
> +void xc_hypercall_buffer_array_destroy(xc_interface *xc,
> + xc_hypercall_buffer_array_t *array)
> +{
> + unsigned i;
> +
> + if ( array == NULL )
> + return;
> +
> + for (i = 0; i < array->max_bufs; i++ )
> + xc__hypercall_buffer_free(xc, &array->bufs[i]);
> + free(array->bufs);
> + free(array);
> +}
> +
> /*
> * Local variables:
> * mode: C
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index 32122fd..c3b2c28 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -317,6 +317,33 @@ void xc__hypercall_buffer_free_pages(xc_interface
*xch, xc_hypercall_buffer_t *b
> #define xc_hypercall_buffer_free_pages(_xch, _name, _nr)
xc__hypercall_buffer_free_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
>
> /*
> + * Array of hypercall buffers.
> + *
> + * Create an array with xc_hypercall_buffer_array_create() and
> + * populate it by declaring one hypercall buffer in a loop and
> + * allocating the buffer with xc_hypercall_buffer_array_alloc().
> + *
> + * To access a previously allocated buffers, declare a new hypercall
> + * buffer and call xc_hypercall_buffer_array_get().
> + *
> + * Destroy the array with xc_hypercall_buffer_array_destroy() to free
> + * the array and all its alocated hypercall buffers.
> + */
> +struct xc_hypercall_buffer_array;
> +typedef struct xc_hypercall_buffer_array xc_hypercall_buffer_array_t;
> +
> +xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface
*xch, unsigned n);
> +void *xc__hypercall_buffer_array_alloc(xc_interface *xch,
xc_hypercall_buffer_array_t *array,
> + unsigned index,
xc_hypercall_buffer_t *hbuf, size_t size);
> +#define xc_hypercall_buffer_array_alloc(_xch, _array, _index, _name,
_size) \
> + xc__hypercall_buffer_array_alloc(_xch, _array, _index,
HYPERCALL_BUFFER(_name), _size)
> +void *xc__hypercall_buffer_array_get(xc_interface *xch,
xc_hypercall_buffer_array_t *array,
> + unsigned index, xc_hypercall_buffer_t
*hbuf);
> +#define xc_hypercall_buffer_array_get(_xch, _array, _index, _name, _size)
\
> + xc__hypercall_buffer_array_get(_xch, _array, _index,
HYPERCALL_BUFFER(_name))
> +void xc_hypercall_buffer_array_destroy(xc_interface *xc,
xc_hypercall_buffer_array_t *array);
> +
> +/*
> * CPUMAP handling
> */
> typedef uint8_t *xc_cpumap_t;