For what it is worth. Reviewed-by: Don Slutz <dslutz at verizon.com> -Don Slutz On 11/06/13 09:49, 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. > > Signed-off-by: David Vrabel <david.vrabel at citrix.com> > Acked-by: Ian Campbell <ian.campbell at citrix.com> > Reviewed-by: Daniel Kiper <daniel.kiper at oracle.com> > Tested-by: Daniel Kiper <daniel.kiper at oracle.com> > Reviewed-by: Andrew Cooper <andrew.cooper3 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 c354677..e762a93 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 8cf3f3b..a7e8c31 100644 > --- a/tools/libxc/xenctrl.h > +++ b/tools/libxc/xenctrl.h > @@ -321,6 +321,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;