From: David Vrabel Date: Tue, 12 Nov 2013 10:46:39 +0000 (+0100) Subject: libxc: add hypercall buffer arrays X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~5991 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=e07d1cb67b61e60e2baf93725e0bd55a15372111;p=xen.git libxc: add hypercall buffer arrays Hypercall buffer arrays are used when a hypercall takes a variable length array of buffers. Signed-off-by: David Vrabel Acked-by: Ian Campbell Reviewed-by: Daniel Kiper Tested-by: Daniel Kiper Reviewed-by: Andrew Cooper Reviewed-by: Don Slutz Tested-by: Don Slutz Acked-by: Keir Fraser --- diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c index c354677ea2..e762a93a67 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 8cf3f3bd15..a7e8c318e1 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -320,6 +320,33 @@ void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages); #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 */