|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH Linux v4 16/16] xen/privcmd: Add new ABI to allow copying foreign memory
From: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
This new ABI allows to copy foreign domain memory to/from a buffer.
This avoids having to map/copy/unmap foreign memory which is
expensive.
This operation is done particularly when migrating VMs.
Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
---
arch/x86/include/asm/xen/interface.h | 1 +
drivers/xen/privcmd.c | 51 ++++++++++++++++++++++++++++
include/uapi/xen/privcmd.h | 10 ++++++
include/xen/interface/memory.h | 37 ++++++++++++++++++++
4 files changed, 99 insertions(+)
diff --git a/arch/x86/include/asm/xen/interface.h
b/arch/x86/include/asm/xen/interface.h
index a078a2b0f032..bac3c3bc60fd 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -91,6 +91,7 @@ DEFINE_GUEST_HANDLE(int);
DEFINE_GUEST_HANDLE(void);
DEFINE_GUEST_HANDLE(uint64_t);
DEFINE_GUEST_HANDLE(uint32_t);
+DEFINE_GUEST_HANDLE(uint8_t);
DEFINE_GUEST_HANDLE(xen_pfn_t);
DEFINE_GUEST_HANDLE(xen_ulong_t);
#endif
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 725a49a0eee7..4ae9138dd314 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -62,6 +62,10 @@ MODULE_LICENSE("GPL");
#define PRIV_VMA_LOCKED ((void *)1)
+#ifndef UINT32_MAX
+#define UINT32_MAX ((uint32_t)~0U)
+#endif
+
static unsigned int privcmd_dm_op_max_num = 16;
module_param_named(dm_op_max_nr_bufs, privcmd_dm_op_max_num, uint, 0644);
MODULE_PARM_DESC(dm_op_max_nr_bufs,
@@ -1522,6 +1526,49 @@ static inline void privcmd_ioeventfd_exit(void)
}
#endif /* CONFIG_XEN_PRIVCMD_EVENTFD */
+static long privcmd_ioctl_foreigncopy(
+ struct file *file, void __user *udata)
+{
+ const struct privcmd_data *const data = file->private_data;
+ long ret;
+ struct privcmd_foreigncopy copy;
+ struct xen_foreigncopy xcopy;
+
+ if (copy_from_user(©, udata, sizeof(copy)))
+ return -EFAULT;
+ if (copy.dir & ~1u)
+ return -EINVAL;
+ if (copy.num >= UINT32_MAX >> PAGE_SHIFT)
+ return -EINVAL;
+ if (!access_ok(copy.pfns, copy.num * sizeof(*copy.pfns)))
+ return -EFAULT;
+ if (!access_ok(copy.buffer, copy.num << PAGE_SHIFT))
+ return -EFAULT;
+
+ /* If restriction is in place, check the domid matches */
+ if (data->domid != DOMID_INVALID && data->domid != copy.dom)
+ return -EPERM;
+
+ xcopy.domid = copy.dom;
+ xcopy.flags = copy.dir;
+ xcopy.nr_frames = copy.num;
+ xcopy.frame_list = (void *) copy.pfns;
+ xcopy.buffer = copy.buffer;
+
+ ret = HYPERVISOR_memory_op(XENMEM_foreigncopy, &xcopy);
+
+ /* copy values back in case of error */
+ if (ret) {
+ copy.num = xcopy.nr_frames = copy.num;
+ copy.pfns = xcopy.frame_list;
+ copy.buffer = xcopy.buffer;
+ if (copy_to_user(udata, ©, sizeof(copy)))
+ ret = -EFAULT;
+ }
+
+ return ret;
+}
+
static long privcmd_ioctl(struct file *file,
unsigned int cmd, unsigned long data)
{
@@ -1569,6 +1616,10 @@ static long privcmd_ioctl(struct file *file,
ret = privcmd_ioctl_pcidev_get_gsi(file, udata);
break;
+ case IOCTL_PRIVCMD_FOREIGNCOPY:
+ ret = privcmd_ioctl_foreigncopy(file, udata);
+ break;
+
default:
break;
}
diff --git a/include/uapi/xen/privcmd.h b/include/uapi/xen/privcmd.h
index 8e2c8fd44764..786d769ad4f8 100644
--- a/include/uapi/xen/privcmd.h
+++ b/include/uapi/xen/privcmd.h
@@ -131,6 +131,14 @@ struct privcmd_pcidev_get_gsi {
__u32 gsi;
};
+struct privcmd_foreigncopy {
+ domid_t dom; /* foreign domain */
+ __u16 dir; /* direction, 0 from, 1 to */
+ __u32 num; /* number of pages to copy */
+ const xen_pfn_t __user *pfns; /* array of pfns */
+ void __user *buffer; /* buffer to copy to/from */
+};
+
/*
* @cmd: IOCTL_PRIVCMD_HYPERCALL
* @arg: &privcmd_hypercall_t
@@ -164,5 +172,7 @@ struct privcmd_pcidev_get_gsi {
_IOW('P', 9, struct privcmd_ioeventfd)
#define IOCTL_PRIVCMD_PCIDEV_GET_GSI \
_IOC(_IOC_NONE, 'P', 10, sizeof(struct privcmd_pcidev_get_gsi))
+#define IOCTL_PRIVCMD_FOREIGNCOPY \
+ _IOC(_IOC_NONE, 'P', 11, sizeof(struct privcmd_foreigncopy))
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
index 1a371a825c55..5981402fccde 100644
--- a/include/xen/interface/memory.h
+++ b/include/xen/interface/memory.h
@@ -325,4 +325,41 @@ struct xen_mem_acquire_resource {
};
DEFINE_GUEST_HANDLE_STRUCT(xen_mem_acquire_resource);
+/*
+ * Copy memory from/to a given domain.
+ */
+#define XENMEM_foreigncopy 29
+struct xen_foreigncopy {
+ /* IN - The domain whose resource is to be copied */
+ domid_t domid;
+
+ /* IN - Flags */
+#define XENMEM_foreigncopy_from 0
+#define XENMEM_foreigncopy_to 1
+#define XENMEM_foreigncopy_direction 1
+ uint16_t flags;
+
+ /*
+ * IN
+ *
+ * As an IN parameter number of frames of the domain to be copied.
+ */
+ uint32_t nr_frames;
+
+ /*
+ * IN
+ *
+ * Frames to be copied.
+ */
+ GUEST_HANDLE(xen_pfn_t) frame_list;
+
+ /*
+ * IN/OUT
+ *
+ * Userspace buffer to read/write from.
+ */
+ GUEST_HANDLE(uint8_t) buffer;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_foreigncopy);
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |