[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] gnttab: Add gntdev device mappings for FreeBSD
On Thu, Aug 04, 2016 at 06:23:51PM +0530, Akshay Jaggi wrote: > Add grant table userspace device mappings for > FreeBSD (enables support for qdisk backend > on FreeBSD Dom0). > > Signed-off-by: Akshay Jaggi <akshay1994.leo@xxxxxxxxx> > --- > tools/include/xen-sys/FreeBSD/gntdev.h | 118 ++++++++++++ > tools/libs/gnttab/Makefile | 2 +- > tools/libs/gnttab/freebsd.c | 335 > +++++++++++++++++++++++++++++++++ > 3 files changed, 454 insertions(+), 1 deletion(-) > create mode 100644 tools/include/xen-sys/FreeBSD/gntdev.h > create mode 100644 tools/libs/gnttab/freebsd.c > > diff --git a/tools/include/xen-sys/FreeBSD/gntdev.h > b/tools/include/xen-sys/FreeBSD/gntdev.h > new file mode 100644 > index 0000000..1d09c5d > --- /dev/null > +++ b/tools/include/xen-sys/FreeBSD/gntdev.h > @@ -0,0 +1,118 @@ > +/*- > + * Copyright (c) 2016 Akshay Jaggi <jaggi@xxxxxxxxxxx> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * gntdev.h > + * > + * Interface to /dev/xen/gntdev. > + * > + */ > + > +#ifndef __XEN_GNTDEV_H__ > +#define __XEN_GNTDEV_H__ > + > +#include <sys/types.h> > + > +#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY > \ > + _IOW('E', 0, struct ioctl_gntdev_unmap_notify) > +struct ioctl_gntdev_unmap_notify { > + /* IN parameters */ > + uint64_t index; > + uint32_t action; > + uint32_t event_channel_port; > +}; > + > +#define UNMAP_NOTIFY_CLEAR_BYTE 0x1 > +#define UNMAP_NOTIFY_SEND_EVENT 0x2 > + > +/*-------------------- Grant Creation IOCTLs > --------------------------------*/ > + > +#define IOCTL_GNTDEV_ALLOC_GREF > \ > + _IOWR('E', 1, struct ioctl_gntdev_alloc_gref) > +struct ioctl_gntdev_alloc_gref { > + /* IN parameters */ > + uint16_t domid; > + uint16_t flags; > + uint32_t count; > + /* OUT parameters */ > + uint64_t index; > + /* Variable OUT parameter */ > + uint32_t gref_ids[1]; > +}; > + > +#define GNTDEV_ALLOC_FLAG_WRITABLE 1 > + > +#define IOCTL_GNTDEV_DEALLOC_GREF \ > + _IOW('E', 2, struct ioctl_gntdev_dealloc_gref) > +struct ioctl_gntdev_dealloc_gref { > + /* IN parameters */ > + uint64_t index; > + uint32_t count; > +}; > + > +/*-------------------- Grant Accessing IOCTLs > -------------------------------*/ ^ I would say "Mapping" here instead. > + > +struct ioctl_gntdev_grant_ref { > + uint32_t domid; > + uint32_t ref; > +}; > + > +#define IOCTL_GNTDEV_MAP_GRANT_REF \ > + _IOWR('E', 3, struct ioctl_gntdev_map_grant_ref) > +struct ioctl_gntdev_map_grant_ref { > + /* IN parameters */ > + uint32_t count; > + uint32_t pad0; > + /* OUT parameters */ > + uint64_t index; > + /* Variable IN parameter */ > + struct ioctl_gntdev_grant_ref refs[1]; > +}; > + > +#define IOCTL_GNTDEV_UNMAP_GRANT_REF \ > + _IOW('E', 4, struct ioctl_gntdev_unmap_grant_ref) > +struct ioctl_gntdev_unmap_grant_ref { > + /* IN parameters */ > + uint64_t index; > + uint32_t count; > +}; > + > +#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \ > + _IOWR('E', 5, struct ioctl_gntdev_get_offset_for_vaddr) > +struct ioctl_gntdev_get_offset_for_vaddr { > + /* IN parameters */ > + uint64_t vaddr; > + /* OUT parameters */ > + uint64_t offset; > + uint32_t count; > +}; > + > +#define IOCTL_GNTDEV_SET_MAX_GRANTS \ > + _IOW('E', 6, struct ioctl_gntdev_set_max_grants) > +struct ioctl_gntdev_set_max_grants { > + /* IN parameters */ > + uint32_t count; This seems useless, I don't see any reason to introduce an IOCTL that is deprecated, and that will never be implemented in FreeBSD. > +}; > + > +#endif /* __XEN_GNTDEV_H__ */ > diff --git a/tools/libs/gnttab/Makefile b/tools/libs/gnttab/Makefile > index af64542..69bb207 100644 > --- a/tools/libs/gnttab/Makefile > +++ b/tools/libs/gnttab/Makefile > @@ -14,7 +14,7 @@ SRCS-GNTSHR += gntshr_core.c > > SRCS-$(CONFIG_Linux) += $(SRCS-GNTTAB) $(SRCS-GNTSHR) linux.c > SRCS-$(CONFIG_MiniOS) += $(SRCS-GNTTAB) gntshr_unimp.c minios.c > -SRCS-$(CONFIG_FreeBSD) += gnttab_unimp.c gntshr_unimp.c > +SRCS-$(CONFIG_FreeBSD) += $(SRCS-GNTTAB) $(SRCS-GNTSHR) freebsd.c > SRCS-$(CONFIG_SunOS) += gnttab_unimp.c gntshr_unimp.c > SRCS-$(CONFIG_NetBSD) += gnttab_unimp.c gntshr_unimp.c > > diff --git a/tools/libs/gnttab/freebsd.c b/tools/libs/gnttab/freebsd.c > new file mode 100644 > index 0000000..eef0238 > --- /dev/null > +++ b/tools/libs/gnttab/freebsd.c > @@ -0,0 +1,335 @@ > +/* > + * Copyright (c) 2007-2008, D G Murray <Derek.Murray@xxxxxxxxxxxx> > + * Copyright (c) 2016-2017, Akshay Jaggi <jaggi@xxxxxxxxxxx> > + * > + * 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 "private.h" > + > +#define DEVXEN "/dev/xen/" This should be /dev/xen/gntdev, FreeBSD only has one gnt device, there's no reason to not have the full path here. > +#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & > ~((1UL<<(_w))-1)) > + > +#define GTERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gnttab", _f) > +#define GSERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gntshr", _f) > + > +#define PAGE_SHIFT 12 > +#define PAGE_SIZE (1UL << PAGE_SHIFT) > +#define PAGE_MASK (~(PAGE_SIZE-1)) > > +#ifndef O_CLOEXEC > +#define O_CLOEXEC 0 No need for this, the version of FreeBSD that support Xen all have O_CLOEXEC defined. > +#endif > + > +int osdep_gnttab_open(xengnttab_handle *xgt) > +{ > + int fd = open(DEVXEN "gntdev", 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) This should just return 0, the ioctl is not implemented and will never be. > +{ > + int fd = xgt->fd, rc; > + struct ioctl_gntdev_set_max_grants max_grants = { .count = count }; > + > + rc = ioctl(fd, IOCTL_GNTDEV_SET_MAX_GRANTS, &max_grants); > + if (rc) { Coding style, the bracket should be on a new line and you need spaces inside the conditional. > + /* > + * FreeBSD kernel doesn't implement this IOCTL, > + * so ignore the resulting specific failure, if any. > + */ > + if (errno == ENOTTY) Same here, missing spaces inside of the conditional (I'm not going to comment on all of those). > + rc = 0; > + else > + GTERROR(xgt->logger, "ioctl SET_MAX_GRANTS failed"); > + } > + > + return rc; > +} > + > +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) > +{ > + int fd = xgt->fd; > + struct ioctl_gntdev_map_grant_ref *map; > + unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) * > + sizeof(struct > ioctl_gntdev_map_grant_ref)), > + PAGE_SHIFT); > + void *addr = NULL; > + int domids_stride = 1; > + int i; > + > + if (flags & XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN) > + domids_stride = 0; > + > + if ( map_size <= PAGE_SIZE ) > + map = alloca(sizeof(*map) + > + (count - 1) * sizeof(struct > ioctl_gntdev_map_grant_ref)); > + else > + { > + map = mmap(NULL, map_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANON, -1, 0); > + if ( map == MAP_FAILED ) > + { > + GTERROR(xgt->logger, "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; > + } > + > + retry: > + addr = mmap(NULL, PAGE_SIZE * count, prot, MAP_SHARED, fd, > + map->index); > + > + if (addr == MAP_FAILED && errno == EAGAIN) > + { > + /* > + * The grant hypercall can return EAGAIN if the granted page > + * is swapped out. Since the paging daemon may be in the same > + * domain, the hypercall cannot block without causing a > + * deadlock. > + * > + * Because there are no notifications when the page is swapped > + * in, wait a bit before retrying, and hope that the page will > + * arrive eventually. > + */ > + usleep(1000); > + goto retry; > + } > + > + if (addr != MAP_FAILED) > + { > + int rv = 0; > + struct ioctl_gntdev_unmap_notify notify; New line between variable declaration and code. > + notify.index = map->index; > + notify.action = 0; > + if (notify_offset < 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 * 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 ( map_size > PAGE_SIZE ) > + munmap(map, map_size); > + > + return addr; > +} > + > +int osdep_gnttab_unmap(xengnttab_handle *xgt, > + void *start_address, > + uint32_t count) > +{ > + int fd = xgt->fd; > + struct ioctl_gntdev_get_offset_for_vaddr get_offset; > + struct ioctl_gntdev_unmap_grant_ref unmap_grant; > + int rc; > + > + if ( start_address == NULL ) > + { > + errno = EINVAL; > + return -1; > + } > + > + /* First, it is necessary to get the offset which was initially used to > + * mmap() the pages. > + */ Comment style, please leave the initial line empty in a multi line comment (like you have done above). > + 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 * 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_gntshr_open(xengntshr_handle *xgs) > +{ > + int fd = open(DEVXEN "gntdev", O_RDWR); New line. > + if ( fd == -1 ) > + return -1; > + xgs->fd = fd; New line. > + 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) > +{ > + struct ioctl_gntdev_alloc_gref *gref_info = NULL; > + struct ioctl_gntdev_unmap_notify notify; > + struct ioctl_gntdev_dealloc_gref gref_drop; > + int fd = xgs->fd; > + int err; > + void *area = NULL; > + gref_info = malloc(sizeof(*gref_info) + count * sizeof(uint32_t)); New line. Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |