Unverified Commit 7f688be7 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3300 Add sharepool support v3

Merge Pull Request from: @ci-robot 
 
PR sync from: Wang Wensheng <wangwensheng4@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2YPFNNCJKIDNZJXT443RNHNWNQTGRDZC/ 
This patch series migrates share pool features from OLK-5.10 to
OLK-6.6. We don't want to do this work patch by patch since
there are hundreds of patches in OLK-5.10 including bugfix and small
features generation. Instead we just take the final version and
split it into a few small patches, each of which contains one
feature at the final version.

The share pool features is a big feature, it is mainly used to share
user virtual memory for different processes in the same group.
It could be used by this steps:

Process A create a new group which is owned by process A.
Process A add process B to the group.
Process A add process C to the same group.
Process B alloc a new memory VA, and write something in it.
The VA was send to the process C by IPC, then process C got it.
The process C access the VA and got the data directly.
The process A could add more processes in the group to share the
memory.
Fix the memory by use the free function or exit the group.
The new features is enabled both by CONFIG_SHARE_POOL and the
enable_ascend_share_pool bootarg, it would not affect anything if disabled.

v1->v2:
Delete some unused code.
v2->v3:
Rename several function.

Wang Wensheng (19):
  mm/hugetlb: Introduce hugetlb_insert_hugepage_pte[_by_pa]
  mm/vmalloc: Extend vmalloc usage about hugepage
  mm: Extend mmap assocated functions to accept mm_struct
  mm/sharepool: Add base framework for share_pool
  mm/sharepool: Add sp_area management code
  mm/sharepool: Reserve the va space for share_pool
  mm/sharepool: Implement mg_sp_make_share_u2k()
  mm/sharepool: Implement mg_sp_unshare_kva
  mm/sharepool: Implement mg_sp_walk_page_range()
  mm/sharepool: Implement mg_sp_free()
  mm/sharepool: Implement mg_sp_alloc()
  mm/sharepool: Implement mg_sp_make_share_k2u()
  mm/sharepool: Implement mg_sp_group_add_task()
  mm/sharepool: Implement mg_sp_group_id_by_pid()
  mm/sharepool: Implement mg_sp_id_of_current()
  mm/sharepool: Implement mg_sp_config_dvpp_range()
  mm/sharepool: Add proc interfaces to show sp info
  mm/sharepool: support fork() and exit() to handle the mm
  mm/sharepool: Protect the va reserved for sharepool


-- 
2.17.1
 
https://gitee.com/openeuler/kernel/issues/I8LNGH 
 
Link:https://gitee.com/openeuler/kernel/pulls/3300

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Reviewed-by: default avatarZucheng Zheng <zhengzucheng@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 0684c49b 7be202c5
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -282,6 +282,26 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
bool is_hugetlb_entry_migration(pte_t pte);
void hugetlb_unshare_all_pmds(struct vm_area_struct *vma);

#ifdef CONFIG_HUGETLB_INSERT_PAGE
int hugetlb_insert_hugepage_pte(struct mm_struct *mm, unsigned long addr,
				pgprot_t prot, struct page *hpage);
int hugetlb_insert_hugepage_pte_by_pa(struct mm_struct *mm,
				unsigned long vir_addr,
				pgprot_t prot, unsigned long phy_addr);
#else /* CONFIG_HUGETLB_INSERT_PAGE */
static inline int hugetlb_insert_hugepage_pte(struct mm_struct *mm, unsigned long addr,
				pgprot_t prot, struct page *hpage)
{
	return -EPERM;
}
static inline int hugetlb_insert_hugepage_pte_by_pa(struct mm_struct *mm,
				unsigned long vir_addr,
				pgprot_t prot, unsigned long phy_addr)
{
	return -EPERM;
}
#endif /* CONFIG_HUGETLB_INSERT_PAGE */

#else /* !CONFIG_HUGETLB_PAGE */

static inline void hugetlb_dup_vma_private(struct vm_area_struct *vma)
@@ -491,6 +511,18 @@ static inline vm_fault_t hugetlb_fault(struct mm_struct *mm,

static inline void hugetlb_unshare_all_pmds(struct vm_area_struct *vma) { }

static inline int hugetlb_insert_hugepage_pte(struct mm_struct *mm, unsigned long addr,
				pgprot_t prot, struct page *hpage)
{
	return -EPERM;
}
static inline int hugetlb_insert_hugepage_pte_by_pa(struct mm_struct *mm,
				unsigned long vir_addr,
				pgprot_t prot, unsigned long phy_addr)
{
	return -EPERM;
}

#endif /* !CONFIG_HUGETLB_PAGE */
/*
 * hugepages at page global directory. If arch support
+11 −0
Original line number Diff line number Diff line
@@ -184,6 +184,9 @@ static inline bool mpol_is_preferred_many(struct mempolicy *pol)

extern bool apply_policy_zone(struct mempolicy *policy, enum zone_type zone);

extern long __do_mbind(unsigned long start, unsigned long len,
		     unsigned short mode, unsigned short mode_flags,
		     nodemask_t *nmask, unsigned long flags, struct mm_struct *mm);
#else

struct mempolicy {};
@@ -294,5 +297,13 @@ static inline bool mpol_is_preferred_many(struct mempolicy *pol)
	return  false;
}

static inline long __do_mbind(unsigned long start, unsigned long len,
		     unsigned short mode, unsigned short mode_flags,
		     nodemask_t *nmask, unsigned long flags, struct mm_struct *mm)
{
	return 0;
}


#endif /* CONFIG_NUMA */
#endif
+17 −0
Original line number Diff line number Diff line
@@ -382,6 +382,12 @@ extern unsigned int kobjsize(const void *objp);
# define VM_MTE_ALLOWED	VM_NONE
#endif

#if defined(CONFIG_SHARE_POOL)
# define VM_SHARE_POOL VM_HIGH_ARCH_4
#else
# define VM_SHARE_POOL VM_NONE
#endif

#ifndef VM_GROWSUP
# define VM_GROWSUP	VM_NONE
#endif
@@ -3288,6 +3294,10 @@ extern unsigned long do_mmap(struct file *file, unsigned long addr,
	unsigned long len, unsigned long prot, unsigned long flags,
	vm_flags_t vm_flags, unsigned long pgoff, unsigned long *populate,
	struct list_head *uf);
extern unsigned long __do_mmap_mm(struct mm_struct *mm, struct file *file, unsigned long addr,
			unsigned long len, unsigned long prot,
			unsigned long flags, vm_flags_t vm_flags, unsigned long pgoff,
			unsigned long *populate, struct list_head *uf);
extern int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm,
			 unsigned long start, size_t len, struct list_head *uf,
			 bool unlock);
@@ -3301,6 +3311,8 @@ extern int do_vma_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
			 struct list_head *uf, bool unlock);
extern int __mm_populate(unsigned long addr, unsigned long len,
			 int ignore_errors);
extern int do_mm_populate(struct mm_struct *mm, unsigned long start, unsigned long len,
			  int ignore_errors);
static inline void mm_populate(unsigned long addr, unsigned long len)
{
	/* Ignore errors */
@@ -3308,6 +3320,11 @@ static inline void mm_populate(unsigned long addr, unsigned long len)
}
#else
static inline void mm_populate(unsigned long addr, unsigned long len) {}
static inline int do_mm_populate(struct mm_struct *mm, unsigned long start, unsigned long len,
				 int ignore_errors)
{
	return -EPERM;
}
#endif

/* These take the mm semaphore themselves */
+6 −0
Original line number Diff line number Diff line
@@ -674,6 +674,9 @@ struct vm_area_struct {
	struct vma_numab_state *numab_state;	/* NUMA Balancing state */
#endif
	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
#ifdef CONFIG_SHARE_POOL
	struct sp_area *spa;
#endif
} __randomize_layout;

#ifdef CONFIG_SCHED_MM_CID
@@ -931,6 +934,9 @@ struct mm_struct {
#endif
		} lru_gen;
#endif /* CONFIG_LRU_GEN */
#ifdef CONFIG_SHARE_POOL
		struct sp_group_master *sp_group_master;
#endif
	} __randomize_layout;

	/*
+267 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LINUX_SHARE_POOL_H
#define LINUX_SHARE_POOL_H

#include <linux/mman.h>
#include <linux/mm_types.h>
#include <linux/notifier.h>
#include <linux/vmalloc.h>
#include <linux/printk.h>
#include <linux/hashtable.h>
#include <linux/numa.h>
#include <linux/jump_label.h>

#define SP_HUGEPAGE		(1 << 0)
#define SP_HUGEPAGE_ONLY	(1 << 1)
#define SP_DVPP			(1 << 2)
#define SP_SPEC_NODE_ID		(1 << 3)
#define SP_PROT_RO		(1 << 16)
/*
 * SP_PROT_FOCUS should used with SP_PROT_RO,
 * to alloc a memory within sharepool ro memory.
 */
#define SP_PROT_FOCUS		(1 << 17)

#define DEVICE_ID_BITS		4UL
#define DEVICE_ID_MASK		((1UL << DEVICE_ID_BITS) - 1UL)
#define DEVICE_ID_SHIFT		32UL
#define NODE_ID_BITS		NODES_SHIFT
#define NODE_ID_MASK		((1UL << NODE_ID_BITS) - 1UL)
#define NODE_ID_SHIFT		(DEVICE_ID_SHIFT + DEVICE_ID_BITS)

#define SP_FLAG_MASK		(SP_HUGEPAGE | SP_HUGEPAGE_ONLY | SP_DVPP | \
				 SP_SPEC_NODE_ID | SP_PROT_RO | SP_PROT_FOCUS | \
				(DEVICE_ID_MASK << DEVICE_ID_SHIFT) | \
				(NODE_ID_MASK << NODE_ID_SHIFT))

#define sp_flags_device_id(flags) (((flags) >> DEVICE_ID_SHIFT) & DEVICE_ID_MASK)
#define sp_flags_node_id(flags) (((flags) >> NODE_ID_SHIFT) & NODE_ID_MASK)

#define SPG_ID_NONE	(-1)	/* not associated with sp_group, only for specified thread */
#define SPG_ID_DEFAULT	0	/* use the spg id of current thread */
#define SPG_ID_MIN	1	/* valid id should be >= 1 */
#define SPG_ID_MAX	99999
#define SPG_ID_AUTO_MIN 100000
#define SPG_ID_AUTO_MAX 199999
#define SPG_ID_AUTO     200000  /* generate group id automatically */
#define SPG_ID_LOCAL_MIN	200001
#define SPG_ID_LOCAL_MAX	299999
#define SPG_ID_LOCAL		300000 /* generate group id in local range */

#define MAX_DEVID 8	/* the max num of Da-vinci devices */

extern struct static_key_false share_pool_enabled_key;

struct sp_walk_data {
	struct page **pages;
	unsigned int page_count;
	unsigned long uva_aligned;
	unsigned long page_size;
	bool is_hugepage;
	bool is_page_type_set;
	pmd_t *pmd;
};

#define MAP_SHARE_POOL			0x200000

#define MMAP_TOP_4G_SIZE		0x100000000UL

/* 8T - 64G size */
#define MMAP_SHARE_POOL_NORMAL_SIZE	0x7F000000000UL
/* 64G */
#define MMAP_SHARE_POOL_RO_SIZE		0x1000000000UL
/* 8T size*/
#define MMAP_SHARE_POOL_DVPP_SIZE	0x80000000000UL
/* 16G size */
#define MMAP_SHARE_POOL_16G_SIZE	0x400000000UL
/* skip 8T for stack */
#define MMAP_SHARE_POOL_SKIP		0x80000000000UL
#define MMAP_SHARE_POOL_END		(TASK_SIZE - MMAP_SHARE_POOL_SKIP)
#define MMAP_SHARE_POLL_DVPP_END	(MMAP_SHARE_POOL_END)
/* MMAP_SHARE_POOL_DVPP_START should be align to 16G */
#define MMAP_SHARE_POOL_DVPP_START	(MMAP_SHARE_POLL_DVPP_END - MMAP_SHARE_POOL_DVPP_SIZE)
#define MMAP_SHARE_POOL_RO_END		(MMAP_SHARE_POOL_DVPP_START)
#define MMAP_SHARE_POOL_RO_START	(MMAP_SHARE_POOL_RO_END - MMAP_SHARE_POOL_RO_SIZE)
#define MMAP_SHARE_POOL_NORMAL_END	(MMAP_SHARE_POOL_RO_START)
#define MMAP_SHARE_POOL_NORMAL_START	(MMAP_SHARE_POOL_NORMAL_END - MMAP_SHARE_POOL_NORMAL_SIZE)
#define MMAP_SHARE_POOL_START		(MMAP_SHARE_POOL_NORMAL_START)

#define MMAP_SHARE_POOL_DYNAMIC_DVPP_BASE	0x100000000000ULL
#define MMAP_SHARE_POOL_DYNAMIC_DVPP_END	(MMAP_SHARE_POOL_DYNAMIC_DVPP_BASE + \
						MMAP_SHARE_POOL_16G_SIZE * 64)

#ifdef CONFIG_SHARE_POOL

/*
 * Those interfaces are exported for modules
 */
extern int mg_sp_group_add_task(int tgid, unsigned long prot, int spg_id);
extern int mg_sp_group_id_by_pid(int tgid, int *spg_ids, int *num);

extern void *mg_sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id);
extern void *mg_sp_alloc_nodemask(unsigned long size, unsigned long sp_flags, int spg_id,
		nodemask_t nodemask);
extern int mg_sp_free(unsigned long addr, int id);

extern void *mg_sp_make_share_k2u(unsigned long kva, unsigned long size,
			unsigned long sp_flags, int tgid, int spg_id);
extern void *mg_sp_make_share_u2k(unsigned long uva, unsigned long size, int tgid);
extern int mg_sp_unshare(unsigned long va, unsigned long size, int spg_id);

extern int mg_sp_walk_page_range(unsigned long uva, unsigned long size,
	struct task_struct *tsk, struct sp_walk_data *sp_walk_data);

extern void mg_sp_walk_page_free(struct sp_walk_data *sp_walk_data);

extern bool mg_sp_config_dvpp_range(size_t start, size_t size, int device_id, int tgid);

extern bool mg_is_sharepool_addr(unsigned long addr);

extern int mg_sp_id_of_current(void);

static inline bool sp_is_enabled(void)
{
	return static_branch_likely(&share_pool_enabled_key);
}

extern void __sp_mm_clean(struct mm_struct *mm);
static inline void sp_mm_clean(struct mm_struct *mm)
{
	if (sp_is_enabled())
		__sp_mm_clean(mm);
}

static inline void sp_area_work_around(struct vm_unmapped_area_info *info)
{
	if (sp_is_enabled())
		info->high_limit = min(info->high_limit, MMAP_SHARE_POOL_START);
}

extern void __sp_area_drop(struct vm_area_struct *vma);
static inline void sp_area_drop(struct vm_area_struct *vma)
{
	if (sp_is_enabled())
		__sp_area_drop(vma);
}

static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
	return sp_is_enabled() && (vm_flags & VM_SHARE_POOL);
}

static inline void sp_init_mm(struct mm_struct *mm)
{
	mm->sp_group_master = NULL;
}

static inline bool sp_check_addr(unsigned long addr)
{
	return sp_is_enabled() && mg_is_sharepool_addr(addr);
}

static inline bool sp_check_mmap_addr(unsigned long addr, unsigned long flags)
{
	return sp_is_enabled() && mg_is_sharepool_addr(addr) && !(flags & MAP_SHARE_POOL);
}

#else /* CONFIG_SHARE_POOL */

static inline int mg_sp_group_add_task(int tgid, unsigned long prot, int spg_id)
{
	return -EPERM;
}

static inline int mg_sp_group_id_by_pid(int tgid, int *spg_ids, int *num)
{
	return -EPERM;
}

static inline void *mg_sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
{
	return NULL;
}

static inline int mg_sp_free(unsigned long addr, int id)
{
	return -EPERM;
}

static inline void *mg_sp_make_share_k2u(unsigned long kva, unsigned long size,
			unsigned long sp_flags, int tgid, int spg_id)
{
	return NULL;
}

static inline void *mg_sp_make_share_u2k(unsigned long uva, unsigned long size, int tgid)
{
	return NULL;
}

static inline int mg_sp_unshare(unsigned long va, unsigned long size, int id)
{
	return -EPERM;
}

static inline int mg_sp_id_of_current(void)
{
	return -EPERM;
}

static inline void sp_mm_clean(struct mm_struct *mm)
{
}

static inline void sp_area_drop(struct vm_area_struct *vma)
{
}

static inline void sp_init_mm(struct mm_struct *mm)
{
}

static inline int mg_sp_walk_page_range(unsigned long uva, unsigned long size,
	struct task_struct *tsk, struct sp_walk_data *sp_walk_data)
{
	return 0;
}

static inline void mg_sp_walk_page_free(struct sp_walk_data *sp_walk_data)
{
}

static inline bool mg_sp_config_dvpp_range(size_t start, size_t size, int device_id, int tgid)
{
	return false;
}

static inline bool mg_is_sharepool_addr(unsigned long addr)
{
	return false;
}

static inline bool sp_is_enabled(void)
{
	return false;
}

static inline void sp_area_work_around(struct vm_unmapped_area_info *info)
{
}

static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
	return false;
}

static inline bool sp_check_addr(unsigned long addr)
{
	return false;
}

static inline bool sp_check_mmap_addr(unsigned long addr, unsigned long flags)
{
	return false;
}
#endif /* !CONFIG_SHARE_POOL */

#endif /* LINUX_SHARE_POOL_H */
Loading