@@ -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__ */
@@ -120,6 +120,48 @@ 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;
+
+ fres = calloc(1, sizeof(*fres));
+ if ( !fres )
+ 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 )
+ goto fail;
+
+ *paddr = fres->addr;
+ return fres;
+
+fail:
+ free(fres);
+
+ return NULL;
+}
+
+void xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ osdep_xenforeignmemory_unmap_resource(fmem, fres);
+
+ free(fres);
+}
+
/*
* Local variables:
* mode: C
@@ -138,6 +138,45 @@ 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 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
+ */
+void 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);
}
+void osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ (void) 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;
+ 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;
+
+ memset(&mr, 0, sizeof(mr));
+ mr.dom = fres->domid;
+ mr.type = fres->type;
+ mr.id = fres->id;
+ mr.idx = fres->frame;
+ mr.num = fres->nr_frames;
+ 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;
+ osdep_xenforeignmemory_unmap_resource(fmem, fres);
+ errno = saved_errno;
+
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
@@ -42,6 +42,36 @@ 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;
+}
+
+void osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+}
+#else
+int osdep_xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+void osdep_xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+#endif
+
#define PERROR(_f...) \
xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f)
A previous patch introduced a new HYPERVISOR_memory_op to acquire guest resources for direct priv-mapping. This patch adds new functionality into libxenforeignmemory to make use of a new privcmd ioctl [1] that uses the new memory op to make such resources available via mmap(2). [1] http://xenbits.xen.org/gitweb/?p=people/pauldu/linux.git;a=commit;h=c5cf2b15f7a448277716a7e96fea1c93df6c17a5 Signed-off-by: Paul Durrant <paul.durrant@citrix.com> --- Cc: Ian Jackson <ian.jackson@eu.citrix.com> Cc: Wei Liu <wei.liu2@citrix.com> --- tools/include/xen-sys/Linux/privcmd.h | 11 ++++++ tools/libs/foreignmemory/core.c | 42 ++++++++++++++++++++ .../libs/foreignmemory/include/xenforeignmemory.h | 39 +++++++++++++++++++ tools/libs/foreignmemory/libxenforeignmemory.map | 5 +++ tools/libs/foreignmemory/linux.c | 45 ++++++++++++++++++++++ tools/libs/foreignmemory/private.h | 30 +++++++++++++++ 6 files changed, 172 insertions(+)