Commit 444ec524 authored by ZhangPeng's avatar ZhangPeng Committed by Ma Wupeng
Browse files

userswap: introduce UFFDIO_COPY_MODE_DIRECT_MAP to map without copying

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I6CAIM



--------------------------------

Add a new UFFDIO_COPY mode UFFDIO_COPY_MODE_DIRECT_MAP to map physical
pages without copy_from_user().
We introduce uswap_unmap_anon_page() to unmap an anonymous page and
uswap_map_anon_page() to map page to src addr. We also introduce
mfill_atomic_pte_nocopy() to achieve zero copy by unmapping src_addr to the
physical page and establishing the mapping from dst_addr to the physical
page.

Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent c098198d
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -27,13 +27,11 @@
#include <linux/ioctl.h>
#include <linux/security.h>
#include <linux/hugetlb.h>
#include <linux/userswap.h>

int sysctl_unprivileged_userfaultfd __read_mostly = 1;

static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
#ifdef CONFIG_USERSWAP
int enable_userswap;
#endif

/*
 * Start with fault_pending_wqh and fault_wqh so they're more likely
@@ -1717,7 +1715,10 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
	ret = -EINVAL;
	if (uffdio_copy.src + uffdio_copy.len <= uffdio_copy.src)
		goto out;
	if (uffdio_copy.mode & ~(UFFDIO_COPY_MODE_DONTWAKE|UFFDIO_COPY_MODE_WP))
	if (uffdio_copy.mode & ~(UFFDIO_COPY_MODE_DONTWAKE |
				 UFFDIO_COPY_MODE_WP |
				 IS_ENABLED(CONFIG_USERSWAP) ?
				 UFFDIO_COPY_MODE_DIRECT_MAP : 0))
		goto out;
	if (mmget_not_zero(ctx->mm)) {
		ret = mcopy_atomic(ctx->mm, uffdio_copy.dst, uffdio_copy.src,
+0 −3
Original line number Diff line number Diff line
@@ -31,9 +31,6 @@
#define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)

extern int sysctl_unprivileged_userfaultfd;
#ifdef CONFIG_USERSWAP
extern int enable_userswap;
#endif

extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason);

+28 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) Huawei Technologies Co., Ltd. 2023. All rights reserved.
 */

#ifndef _LINUX_USERSWAP_H
#define _LINUX_USERSWAP_H

#ifdef CONFIG_USERSWAP

extern int enable_userswap;

int mfill_atomic_pte_nocopy(struct mm_struct *dst_mm,
			    pmd_t *dst_pmd,
			    struct vm_area_struct *dst_vma,
			    unsigned long dst_addr,
			    unsigned long src_addr);

static inline bool uswap_check_copy_mode(struct vm_area_struct *vma, __u64 mode)
{
	if (!(vma->vm_flags & VM_USWAP) && (mode & UFFDIO_COPY_MODE_DIRECT_MAP))
		return false;
	return true;
}

#endif /* CONFIG_USERSWAP */

#endif /* _LINUX_USERSWAP_H */
+1 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ struct uffdio_copy {
	 * according to the uffdio_register.ioctls.
	 */
#define UFFDIO_COPY_MODE_WP			((__u64)1<<1)
#define UFFDIO_COPY_MODE_DIRECT_MAP		((__u64)1<<10)
	__u64 mode;

	/*
+1 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ obj-$(CONFIG_MEMORY_BALLOON) += balloon_compaction.o
obj-$(CONFIG_PAGE_EXTENSION) += page_ext.o
obj-$(CONFIG_CMA_DEBUGFS) += cma_debug.o
obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
obj-$(CONFIG_USERSWAP) += userswap.o
obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
Loading