@@ -86,6 +86,15 @@ typedef struct privcmd_dm_op {
const privcmd_dm_op_buf_t __user *ubufs;
} privcmd_dm_op_t;
+typedef struct privcmd_mmap_resource {
+ domid_t dom;
+ __u32 type;
+ __u32 id;
+ __u32 idx;
+ __u64 num;
+ __u64 addr;
+} privcmd_mmap_resource_t;
+
/*
* @cmd: IOCTL_PRIVCMD_HYPERCALL
* @arg: &privcmd_hypercall_t
@@ -103,5 +112,7 @@ typedef struct privcmd_dm_op {
_IOC(_IOC_NONE, 'P', 5, sizeof(privcmd_dm_op_t))
#define IOCTL_PRIVCMD_RESTRICT \
_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
+#define IOCTL_PRIVCMD_MMAP_RESOURCE \
+ _IOC(_IOC_NONE, 'P', 7, sizeof(privcmd_mmap_resource_t))
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
@@ -2,7 +2,7 @@ XEN_ROOT = $(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
MAJOR = 1
-MINOR = 2
+MINOR = 3
SHLIB_LDFLAGS += -Wl,--version-script=libxenforeignmemory.map
CFLAGS += -Werror -Wmissing-prototypes
@@ -17,6 +17,8 @@
#include <assert.h>
#include <errno.h>
+#include <sys/mman.h>
+
#include "private.h"
xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger,
@@ -120,6 +122,57 @@ int xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
return osdep_xenforeignmemory_restrict(fmem, domid);
}
+xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
+ unsigned int id, unsigned long frame, unsigned long nr_frames,
+ void **paddr, int prot, int flags)
+{
+ xenforeignmemory_resource_handle *fres;
+ int rc;
+
+ /* Check flags only contains POSIX defined values */
+ if ( flags & ~(MAP_SHARED | MAP_PRIVATE) )
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ fres = calloc(1, sizeof(*fres));
+ if ( !fres )
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ fres->domid = domid;
+ fres->type = type;
+ fres->id = id;
+ fres->frame = frame;
+ fres->nr_frames = nr_frames;
+ fres->addr = *paddr;
+ fres->prot = prot;
+ fres->flags = flags;
+
+ rc = osdep_xenforeignmemory_map_resource(fmem, fres);
+ if ( rc )
+ {
+ free(fres);
+ fres = NULL;
+ } else
+ *paddr = fres->addr;
+
+ return fres;
+}
+
+int xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ int rc = osdep_xenforeignmemory_unmap_resource(fmem, fres);
+
+ free(fres);
+ return rc;
+}
+
/*
* Local variables:
* mode: C
@@ -138,6 +138,47 @@ int xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
int xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
domid_t domid);
+typedef struct xenforeignmemory_resource_handle xenforeignmemory_resource_handle;
+
+/**
+ * This function maps a guest resource.
+ *
+ * @parm fmem handle to the open foreignmemory interface
+ * @parm domid the domain id
+ * @parm type the resource type
+ * @parm id the type-specific resource identifier
+ * @parm frame base frame index within the resource
+ * @parm nr_frames number of frames to map
+ * @parm paddr pointer to an address passed through to mmap(2)
+ * @parm prot passed through to mmap(2)
+ * @parm POSIX-only flags passed through to mmap(2)
+ * @return pointer to foreignmemory resource handle on success, NULL on
+ * failure
+ *
+ * *paddr is used, on entry, as a hint address for foreign map placement
+ * (see mmap(2)) so should be set to NULL if no specific placement is
+ * required. On return *paddr contains the address where the resource is
+ * mapped.
+ * As for xenforeignmemory_map2() flags is a set of additional flags
+ * for mmap(2). Not all of the flag combinations are possible due to
+ * implementation details on different platforms.
+ */
+xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
+ unsigned int id, unsigned long frame, unsigned long nr_frames,
+ void **paddr, int prot, int flags);
+
+/**
+ * This function releases a previously acquired resource.
+ *
+ * @parm fmem handle to the open foreignmemory interface
+ * @parm fres handle to the acquired resource
+ *
+ * Returns 0 on success on failure sets errno and returns -1.
+ */
+int xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+
#endif
/*
@@ -14,3 +14,8 @@ VERS_1.2 {
global:
xenforeignmemory_map2;
} VERS_1.1;
+VERS_1.3 {
+ global:
+ xenforeignmemory_map_resource;
+ xenforeignmemory_unmap_resource;
+} VERS_1.2;
@@ -277,6 +277,51 @@ int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
return ioctl(fmem->fd, IOCTL_PRIVCMD_RESTRICT, &domid);
}
+int osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ return munmap(fres->addr, fres->nr_frames << PAGE_SHIFT);
+}
+
+int osdep_xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ privcmd_mmap_resource_t mr = {
+ .dom = fres->domid,
+ .type = fres->type,
+ .id = fres->id,
+ .idx = fres->frame,
+ .num = fres->nr_frames,
+ };
+ int rc;
+
+ fres->addr = mmap(fres->addr, fres->nr_frames << PAGE_SHIFT,
+ fres->prot, fres->flags | MAP_SHARED, fmem->fd, 0);
+ if ( fres->addr == MAP_FAILED )
+ return -1;
+
+ mr.addr = (uintptr_t)fres->addr;
+
+ rc = ioctl(fmem->fd, IOCTL_PRIVCMD_MMAP_RESOURCE, &mr);
+ if ( rc )
+ {
+ int saved_errno;
+
+ if ( errno != ENOTTY )
+ PERROR("ioctl failed");
+ else
+ errno = EOPNOTSUPP;
+
+ saved_errno = errno;
+ (void)osdep_xenforeignmemory_unmap_resource(fmem, fres);
+ errno = saved_errno;
+
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
@@ -42,6 +42,37 @@ void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
xen_pfn_t *arr, int num);
#endif
+struct xenforeignmemory_resource_handle {
+ domid_t domid;
+ unsigned int type;
+ unsigned int id;
+ unsigned long frame;
+ unsigned long nr_frames;
+ void *addr;
+ int prot;
+ int flags;
+};
+
+#ifndef __linux__
+static inline int osdep_xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static inline int osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ return 0;
+}
+#else
+int osdep_xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+int osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+#endif
+
#define PERROR(_f...) \
xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f)