mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Adjust user-space callers to use the new interface. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Anthony PERARD <anthony.perard@vates.tech> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
348 lines
9.0 KiB
C
348 lines
9.0 KiB
C
/*
|
|
* Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
|
|
* Copyright (c) 2016-2017, Akshay Jaggi <jaggi@FreeBSD.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Split out from linux.c
|
|
*/
|
|
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mman.h>
|
|
|
|
#include <xen/sys/gntdev.h>
|
|
|
|
#include <xenctrl.h>
|
|
#include <xen-tools/common-macros.h>
|
|
|
|
#include "private.h"
|
|
|
|
#define DEVXEN "/dev/xen/gntdev"
|
|
|
|
int osdep_gnttab_open(xengnttab_handle *xgt)
|
|
{
|
|
int fd = open(DEVXEN, O_RDWR|O_CLOEXEC);
|
|
|
|
if ( fd == -1 )
|
|
return -1;
|
|
xgt->fd = fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int osdep_gnttab_close(xengnttab_handle *xgt)
|
|
{
|
|
if ( xgt->fd == -1 )
|
|
return 0;
|
|
|
|
return close(xgt->fd);
|
|
}
|
|
|
|
int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
|
|
uint32_t count, int flags, int prot,
|
|
uint32_t *domids, uint32_t *refs,
|
|
uint32_t notify_offset,
|
|
evtchn_port_t notify_port)
|
|
{
|
|
uint32_t i;
|
|
int fd = xgt->fd;
|
|
struct ioctl_gntdev_map_grant_ref map;
|
|
void *addr = NULL;
|
|
int domids_stride;
|
|
unsigned int refs_size = ROUNDUP(count *
|
|
sizeof(struct ioctl_gntdev_grant_ref),
|
|
XC_PAGE_SIZE);
|
|
int os_page_size = getpagesize();
|
|
|
|
domids_stride = (flags & XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN) ? 0 : 1;
|
|
if ( refs_size <= os_page_size )
|
|
map.refs = malloc(refs_size);
|
|
else
|
|
{
|
|
map.refs = mmap(NULL, refs_size, PROT_READ | PROT_WRITE,
|
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
if ( map.refs == MAP_FAILED )
|
|
{
|
|
GTERROR(xgt->logger, "anon mmap of map failed");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
map.refs[i].domid = domids[i * domids_stride];
|
|
map.refs[i].ref = refs[i];
|
|
}
|
|
|
|
map.count = count;
|
|
|
|
if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, &map) )
|
|
{
|
|
GTERROR(xgt->logger, "ioctl MAP_GRANT_REF failed");
|
|
goto out;
|
|
}
|
|
|
|
addr = mmap(NULL, XC_PAGE_SIZE * count, prot, MAP_SHARED, fd,
|
|
map.index);
|
|
if ( addr != MAP_FAILED )
|
|
{
|
|
int rv = 0;
|
|
struct ioctl_gntdev_unmap_notify notify;
|
|
|
|
notify.index = map.index;
|
|
notify.action = 0;
|
|
if ( notify_offset < XC_PAGE_SIZE * count )
|
|
{
|
|
notify.index += notify_offset;
|
|
notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
|
|
}
|
|
if ( notify_port != -1 )
|
|
{
|
|
notify.event_channel_port = notify_port;
|
|
notify.action |= UNMAP_NOTIFY_SEND_EVENT;
|
|
}
|
|
if ( notify.action )
|
|
rv = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, ¬ify);
|
|
if ( rv )
|
|
{
|
|
GTERROR(xgt->logger, "ioctl SET_UNMAP_NOTIFY failed");
|
|
munmap(addr, count * XC_PAGE_SIZE);
|
|
addr = MAP_FAILED;
|
|
}
|
|
}
|
|
if ( addr == MAP_FAILED )
|
|
{
|
|
int saved_errno = errno;
|
|
struct ioctl_gntdev_unmap_grant_ref unmap_grant;
|
|
|
|
/* Unmap the driver slots used to store the grant information. */
|
|
GTERROR(xgt->logger, "mmap failed");
|
|
unmap_grant.index = map.index;
|
|
unmap_grant.count = count;
|
|
ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
|
|
errno = saved_errno;
|
|
addr = NULL;
|
|
}
|
|
|
|
out:
|
|
if ( refs_size > os_page_size )
|
|
munmap(map.refs, refs_size);
|
|
else
|
|
free(map.refs);
|
|
|
|
return addr;
|
|
}
|
|
|
|
int osdep_gnttab_unmap(xengnttab_handle *xgt,
|
|
void *start_address,
|
|
uint32_t count)
|
|
{
|
|
int rc;
|
|
int fd = xgt->fd;
|
|
struct ioctl_gntdev_unmap_grant_ref unmap_grant;
|
|
struct ioctl_gntdev_get_offset_for_vaddr get_offset;
|
|
|
|
if ( start_address == NULL )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* First, it is necessary to get the offset which was initially used to
|
|
* mmap() the pages.
|
|
*/
|
|
get_offset.vaddr = (unsigned long)start_address;
|
|
if ( (rc = ioctl(fd, IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR,
|
|
&get_offset)) )
|
|
return rc;
|
|
|
|
if ( get_offset.count != count )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/* Next, unmap the memory. */
|
|
if ( (rc = munmap(start_address, count * XC_PAGE_SIZE)) )
|
|
return rc;
|
|
|
|
/* Finally, unmap the driver slots used to store the grant information. */
|
|
unmap_grant.index = get_offset.offset;
|
|
unmap_grant.count = count;
|
|
if ( (rc = ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant)) )
|
|
return rc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
|
|
uint32_t count,
|
|
xengnttab_grant_copy_segment_t *segs)
|
|
{
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
int osdep_gntshr_open(xengntshr_handle *xgs)
|
|
{
|
|
|
|
int fd = open(DEVXEN, O_RDWR);
|
|
|
|
if ( fd == -1 )
|
|
return -1;
|
|
xgs->fd = fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int osdep_gntshr_close(xengntshr_handle *xgs)
|
|
{
|
|
if ( xgs->fd == -1 )
|
|
return 0;
|
|
|
|
return close(xgs->fd);
|
|
}
|
|
|
|
void *osdep_gntshr_share_pages(xengntshr_handle *xgs,
|
|
uint32_t domid, int count,
|
|
uint32_t *refs, int writable,
|
|
uint32_t notify_offset,
|
|
evtchn_port_t notify_port)
|
|
{
|
|
int err;
|
|
int fd = xgs->fd;
|
|
void *area = NULL;
|
|
struct ioctl_gntdev_unmap_notify notify;
|
|
struct ioctl_gntdev_dealloc_gref gref_drop;
|
|
struct ioctl_gntdev_alloc_gref gref_info;
|
|
|
|
gref_info.gref_ids = malloc(count * sizeof(uint32_t));
|
|
if ( gref_info.gref_ids == NULL )
|
|
return NULL;
|
|
gref_info.domid = domid;
|
|
gref_info.flags = writable ? GNTDEV_ALLOC_FLAG_WRITABLE : 0;
|
|
gref_info.count = count;
|
|
|
|
err = ioctl(fd, IOCTL_GNTDEV_ALLOC_GREF, &gref_info);
|
|
if ( err )
|
|
{
|
|
GSERROR(xgs->logger, "ioctl failed");
|
|
goto out;
|
|
}
|
|
|
|
area = mmap(NULL, count * XC_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
fd, gref_info.index);
|
|
|
|
if ( area == MAP_FAILED )
|
|
{
|
|
area = NULL;
|
|
GSERROR(xgs->logger, "mmap failed");
|
|
goto out_remove_fdmap;
|
|
}
|
|
|
|
notify.index = gref_info.index;
|
|
notify.action = 0;
|
|
if ( notify_offset < XC_PAGE_SIZE * count )
|
|
{
|
|
notify.index += notify_offset;
|
|
notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
|
|
}
|
|
if ( notify_port != -1 )
|
|
{
|
|
notify.event_channel_port = notify_port;
|
|
notify.action |= UNMAP_NOTIFY_SEND_EVENT;
|
|
}
|
|
if ( notify.action )
|
|
err = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, ¬ify);
|
|
if ( err )
|
|
{
|
|
GSERROR(xgs->logger, "ioctl SET_UNMAP_NOTIFY failed");
|
|
munmap(area, count * XC_PAGE_SIZE);
|
|
area = NULL;
|
|
}
|
|
|
|
memcpy(refs, gref_info.gref_ids, count * sizeof(uint32_t));
|
|
|
|
out_remove_fdmap:
|
|
/*
|
|
* Removing the mapping from the file descriptor does not cause the
|
|
* pages to be deallocated until the mapping is removed.
|
|
*/
|
|
gref_drop.index = gref_info.index;
|
|
gref_drop.count = count;
|
|
ioctl(fd, IOCTL_GNTDEV_DEALLOC_GREF, &gref_drop);
|
|
out:
|
|
free(gref_info.gref_ids);
|
|
|
|
return area;
|
|
}
|
|
|
|
int osdep_gntshr_unshare(xengntshr_handle *xgs,
|
|
void *start_address, uint32_t count)
|
|
{
|
|
return munmap(start_address, count * XC_PAGE_SIZE);
|
|
}
|
|
|
|
/*
|
|
* The functions below are Linux-isms that will likely never be implemented
|
|
* on FreeBSD unless FreeBSD also implements something akin to Linux dmabuf.
|
|
*/
|
|
int osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
|
|
uint32_t flags, uint32_t count,
|
|
const uint32_t *refs,
|
|
uint32_t *dmabuf_fd)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
int osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt,
|
|
uint32_t fd, uint32_t wait_to_ms)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
int osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
|
|
uint32_t fd, uint32_t count, uint32_t *refs)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
int osdep_gnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-file-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* tab-width: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|