On Thu, 2013-02-21 at 17:48 +0000, David Vrabel wrote: > From: David Vrabel <david.vrabel at 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 at citrix.com> > > Signed-off-by: David Vrabel <david.vrabel at 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;