提交 70ae4a24 编写于 作者: W Wang Wensheng 提交者: Zheng Zengkai

mm/sharepool: Allow share THP to kernel

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5DS9S
CVE: NA

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

This is not used for THP but the user page table is just like THP. The
user alloc hugepages via a special driver and its vma is not marked with
VM_HUGETLB. This commit allow to share those vma to kernel.
Signed-off-by: NWang Wensheng <wangwensheng4@huawei.com>
Reviewed-by: NWeilong Chen <chenweilong@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 aa14d16c
...@@ -178,6 +178,7 @@ struct sp_walk_data { ...@@ -178,6 +178,7 @@ struct sp_walk_data {
unsigned long uva_aligned; unsigned long uva_aligned;
unsigned long page_size; unsigned long page_size;
bool is_hugepage; bool is_hugepage;
bool is_page_type_set;
pmd_t *pmd; pmd_t *pmd;
}; };
......
...@@ -2994,9 +2994,40 @@ EXPORT_SYMBOL_GPL(mg_sp_make_share_k2u); ...@@ -2994,9 +2994,40 @@ EXPORT_SYMBOL_GPL(mg_sp_make_share_k2u);
static int sp_pmd_entry(pmd_t *pmd, unsigned long addr, static int sp_pmd_entry(pmd_t *pmd, unsigned long addr,
unsigned long next, struct mm_walk *walk) unsigned long next, struct mm_walk *walk)
{ {
struct page *page;
struct sp_walk_data *sp_walk_data = walk->private; struct sp_walk_data *sp_walk_data = walk->private;
/*
* There exist a scene in DVPP where the pagetable is huge page but its
* vma doesn't record it, something like THP.
* So we cannot make out whether it is a hugepage map until we access the
* pmd here. If mixed size of pages appear, just return an error.
*/
if (pmd_huge(*pmd)) {
if (!sp_walk_data->is_page_type_set) {
sp_walk_data->is_page_type_set = true;
sp_walk_data->is_hugepage = true;
} else if (!sp_walk_data->is_hugepage)
return -EFAULT;
/* To skip pte level walk */
walk->action = ACTION_CONTINUE;
page = pmd_page(*pmd);
get_page(page);
sp_walk_data->pages[sp_walk_data->page_count++] = page;
return 0;
}
if (!sp_walk_data->is_page_type_set) {
sp_walk_data->is_page_type_set = true;
sp_walk_data->is_hugepage = false;
} else if (sp_walk_data->is_hugepage)
return -EFAULT;
sp_walk_data->pmd = pmd; sp_walk_data->pmd = pmd;
return 0; return 0;
} }
...@@ -3140,6 +3171,8 @@ static int __sp_walk_page_range(unsigned long uva, unsigned long size, ...@@ -3140,6 +3171,8 @@ static int __sp_walk_page_range(unsigned long uva, unsigned long size,
sp_walk.pmd_entry = sp_pmd_entry; sp_walk.pmd_entry = sp_pmd_entry;
} }
sp_walk_data->is_page_type_set = false;
sp_walk_data->page_count = 0;
sp_walk_data->page_size = page_size; sp_walk_data->page_size = page_size;
uva_aligned = ALIGN_DOWN(uva, page_size); uva_aligned = ALIGN_DOWN(uva, page_size);
sp_walk_data->uva_aligned = uva_aligned; sp_walk_data->uva_aligned = uva_aligned;
...@@ -3164,8 +3197,12 @@ static int __sp_walk_page_range(unsigned long uva, unsigned long size, ...@@ -3164,8 +3197,12 @@ static int __sp_walk_page_range(unsigned long uva, unsigned long size,
ret = walk_page_range(mm, uva_aligned, uva_aligned + size_aligned, ret = walk_page_range(mm, uva_aligned, uva_aligned + size_aligned,
&sp_walk, sp_walk_data); &sp_walk, sp_walk_data);
if (ret) if (ret) {
while (sp_walk_data->page_count--)
put_page(pages[sp_walk_data->page_count]);
kvfree(pages); kvfree(pages);
sp_walk_data->pages = NULL;
}
return ret; return ret;
} }
...@@ -3201,9 +3238,7 @@ void *sp_make_share_u2k(unsigned long uva, unsigned long size, int pid) ...@@ -3201,9 +3238,7 @@ void *sp_make_share_u2k(unsigned long uva, unsigned long size, int pid)
int ret = 0; int ret = 0;
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
void *p = ERR_PTR(-ESRCH); void *p = ERR_PTR(-ESRCH);
struct sp_walk_data sp_walk_data = { struct sp_walk_data sp_walk_data;
.page_count = 0,
};
struct vm_struct *area; struct vm_struct *area;
check_interrupt_context(); check_interrupt_context();
...@@ -3544,7 +3579,6 @@ int sp_walk_page_range(unsigned long uva, unsigned long size, ...@@ -3544,7 +3579,6 @@ int sp_walk_page_range(unsigned long uva, unsigned long size,
return -ESRCH; return -ESRCH;
} }
sp_walk_data->page_count = 0;
down_write(&mm->mmap_lock); down_write(&mm->mmap_lock);
if (likely(!mm->core_state)) if (likely(!mm->core_state))
ret = __sp_walk_page_range(uva, size, mm, sp_walk_data); ret = __sp_walk_page_range(uva, size, mm, sp_walk_data);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册