Commit 6783c881 authored by Ian Campbell's avatar Ian Campbell

libxc: osdep: convert hypercall buffer allocation

This will allow us to use OS specific interfaces to ensure that the
allocated memory is safe for use as a hypercall buffer in the future.
Signed-off-by: default avatarIan Campbell <ian.campbell@citrix.com>
parent b8984679
......@@ -17,7 +17,7 @@
*/
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <pthread.h>
#include "xc_private.h"
......@@ -95,15 +95,6 @@ static int hypercall_buffer_cache_free(xc_interface *xch, void *p, int nr_pages)
return rc;
}
static void do_hypercall_buffer_free_pages(void *ptr, int nr_pages)
{
#ifndef __sun__
(void) munlock(ptr, nr_pages * PAGE_SIZE);
#endif
free(ptr);
}
void xc__hypercall_buffer_cache_release(xc_interface *xch)
{
void *p;
......@@ -126,7 +117,7 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch)
while ( xch->hypercall_buffer_cache_nr > 0 )
{
p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
do_hypercall_buffer_free_pages(p, 1);
xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, p, 1);
}
hypercall_buffer_cache_unlock(xch);
......@@ -134,36 +125,18 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch)
void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages)
{
size_t size = nr_pages * PAGE_SIZE;
void *p = hypercall_buffer_cache_alloc(xch, nr_pages);
if ( !p ) {
#if defined(_POSIX_C_SOURCE) && !defined(__sun__)
int ret;
ret = posix_memalign(&p, PAGE_SIZE, size);
if (ret != 0)
return NULL;
#elif defined(__NetBSD__) || defined(__OpenBSD__)
p = valloc(size);
#else
p = memalign(PAGE_SIZE, size);
#endif
if (!p)
return NULL;
#ifndef __sun__
if ( mlock(p, size) < 0 )
{
free(p);
return NULL;
}
#endif
}
if ( !p )
p = xch->ops->u.privcmd.alloc_hypercall_buffer(xch, xch->ops_handle, nr_pages);
if (!p)
return NULL;
b->hbuf = p;
memset(p, 0, size);
memset(p, 0, nr_pages * PAGE_SIZE);
return b->hbuf;
}
......@@ -173,7 +146,7 @@ void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b
return;
if ( !hypercall_buffer_cache_free(xch, b->hbuf, nr_pages) )
do_hypercall_buffer_free_pages(b->hbuf, nr_pages);
xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, b->hbuf, nr_pages);
}
struct allocation_header {
......
......@@ -86,6 +86,30 @@ static int linux_privcmd_close(xc_interface *xch, xc_osdep_handle h)
return close(fd);
}
static void *linux_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
{
size_t size = npages * XC_PAGE_SIZE;
void *p;
int ret;
ret = posix_memalign(&p, XC_PAGE_SIZE, size);
if (ret != 0 || !p)
return NULL;
if ( mlock(p, size) < 0 )
{
free(p);
return NULL;
}
return p;
}
static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
{
(void) munlock(ptr, npages * XC_PAGE_SIZE);
free(ptr);
}
static int linux_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
{
int fd = (int)h;
......@@ -344,6 +368,9 @@ static struct xc_osdep_ops linux_privcmd_ops = {
.close = &linux_privcmd_close,
.u.privcmd = {
.alloc_hypercall_buffer = &linux_privcmd_alloc_hypercall_buffer,
.free_hypercall_buffer = &linux_privcmd_free_hypercall_buffer,
.hypercall = &linux_privcmd_hypercall,
.map_foreign_batch = &linux_privcmd_map_foreign_batch,
......
......@@ -37,6 +37,7 @@
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
#include <malloc.h>
#include "xc_private.h"
......@@ -70,6 +71,16 @@ void minios_interface_close_fd(int fd)
files[fd].type = FTYPE_NONE;
}
static void *minios_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
{
return memalign(PAGE_SIZE, npages * PAGE_SIZE);
}
static void minios_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
{
free(ptr);
}
static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
{
multicall_entry_t call;
......@@ -187,6 +198,9 @@ static struct xc_osdep_ops minios_privcmd_ops = {
.close = &minios_privcmd_close,
.u.privcmd = {
.alloc_hypercall_buffer = &minios_privcmd_alloc_hypercall_buffer,
.free_hypercall_buffer = &minios_privcmd_free_hypercall_buffer,
.hypercall = &minios_privcmd_hypercall,
.map_foreign_batch = &minios_privcmd_map_foreign_batch,
......
......@@ -23,6 +23,8 @@
#include <xen/sys/evtchn.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/mman.h>
static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
{
......@@ -66,6 +68,28 @@ static int netbsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
return close(fd);
}
static void *netbsd_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
{
size_t size = npages * XC_PAGE_SIZE;
void *p = valloc(size);
if (!p)
return NULL;
if ( mlock(p, size) < 0 )
{
free(p);
return NULL;
}
return p;
}
static void netbsd_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
{
(void) munlock(ptr, npages * XC_PAGE_SIZE);
free(ptr);
}
static int netbsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
{
int fd = (int)h;
......@@ -181,6 +205,9 @@ static struct xc_osdep_ops netbsd_privcmd_ops = {
.close = &netbsd_privcmd_close,
.u.privcmd = {
.alloc_hypercall_buffer = &netbsd_privcmd_alloc_hypercall_buffer,
.free_hypercall_buffer = &netbsd_privcmd_free_hypercall_buffer,
.hypercall = &netbsd_privcmd_hypercall,
.map_foreign_batch = &netbsd_privcmd_map_foreign_batch,
......
......@@ -24,6 +24,7 @@
#include <xen/sys/evtchn.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
{
......@@ -67,6 +68,16 @@ static int solaris_privcmd_close(xc_interface *xch, xc_osdep_handle h)
return close(fd);
}
static void *solaris_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
{
return memalign(XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
}
static void solaris_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
{
free(ptr);
}
static int solaris_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
{
int fd = (int)h;
......@@ -172,6 +183,9 @@ static struct xc_osdep_ops solaris_privcmd_ops = {
.close = &solaris_privcmd_close,
.u.privcmd = {
.alloc_hypercall_buffer = &solaris_privcmd_alloc_hypercall_buffer,
.free_hypercall_buffer = &solaris_privcmd_free_hypercall_buffer,
.hypercall = &solaris_privcmd_hypercall;
.map_foreign_batch = &solaris_privcmd_map_foreign_batch,
......
......@@ -74,6 +74,9 @@ struct xc_osdep_ops
union {
struct {
void *(*alloc_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, int npages);
void (*free_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages);
int (*hypercall)(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall);
void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment